app:statemachine
  • Required Attributes (1)
  • Optional Attributes (1)
  • Examples (1)
  • Source code
Name Type Description Default value
id Unknown Id of the statemachine, which can be used as a web expression condition Not specified
Back to menuExample: Simple Example

This is a simple example that uses the <app:statemachine>.

Here’s an example of a State Machine using my personal defense condition (MYDEFCON). Click the links below to generate changes to MYDEFCON state.

Some jerk getting chocolate in my peanut butter
Stuck in Atlanta traffic
The world supply of Gruyere cheese is eliminated by angry cheese-eating locusts
I see another Jerry Bruckheimer film
Free Beer
MYDEFCON 1 [comments censored by legal department]
MYDEFCON 2. Redrum. Redrum. Redrum.
MYDEFCON 3. Damn. Now I'm getting angry.
MYDEFCON 4. Okay that's 2 hours I'll never get back, but I'm maintaining my composure.
MYDEFCON 5. Me - at peace...
<a on="click then l:mydefcon.change[value=one]">Some jerk getting chocolate in my peanut butter</a> <br />
<a on="click then l:mydefcon.change[value=two]">Stuck in Atlanta traffic</a>  <br />
<a on="click then l:mydefcon.change[value=three]">The world supply of Gruyere cheese is eliminated by angry cheese-eating locusts</a>  <br />
<a on="click then l:mydefcon.change[value=four]">I see another Jerry Bruckheimer film</a> <br />
<a on="click then l:mydefcon.change[value=five]">Free Beer</a>


<div style="margin:10px"> 
</div>

<div class="defcon1" on="mydefcon[one] then show else hide">
	MYDEFCON 1 [comments censored by legal department]
</div>
<div class="defcon2" on="mydefcon[two] then show else hide">
	MYDEFCON 2. Redrum.  Redrum.  Redrum.
</div>
<div class="defcon3" on="mydefcon[three] then show else hide">
	MYDEFCON 3. Damn. Now I'm getting angry.
</div>
<div class="defcon4" on="mydefcon[four] then show else hide">
	MYDEFCON 4. Okay that's 2 hours I'll never get back, but I'm maintaining my composure.
</div>
<div class="defcon5" on="mydefcon[five] then show else hide">
	MYDEFCON 5. Me - at peace... 
</div>

<app:statemachine id="mydefcon" initial="five">  
	<state name="one" if="l:mydefcon.change[value=one]"></state>  
	<state name="two" if="l:mydefcon.change[value=two]"></state>  
	<state name="three" if="l:mydefcon.change[value=three]"></state>  
	<state name="four" if="l:mydefcon.change[value=four]"></state>  
	<state name="five" if="l:mydefcon.change[value=five]"></state>  
</app:statemachine>
  1 /*
  2  * This file is part of Appcelerator.
  3  *
  4  * Copyright (C) 2006-2008 by Appcelerator, Inc. All Rights Reserved.
  5  * For more information, please visit http://www.appcelerator.org
  6  *
  7  * Appcelerator is free software: you can redistribute it and/or modify
  8  * it under the terms of the GNU General Public License as published by
  9  * the Free Software Foundation, either version 3 of the License, or
 10  * (at your option) any later version.
 11  *
 12  * This program is distributed in the hope that it will be useful,
 13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 15  * GNU General Public License for more details.
 16  * 
 17  * You should have received a copy of the GNU General Public License
 18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 19  *
 20  */
 21 
 22 
 23 Appcelerator.Widget.Statemachine =
 24 {
 25 	getName: function()
 26 	{
 27 		return 'appcelerator statemachine';
 28 	},
 29 	getDescription: function()
 30 	{
 31 		return 'statemachine widget';
 32 	},
 33 	getVersion: function()
 34 	{
 35 		return 1.0;
 36 	},
 37 	getSpecVersion: function()
 38 	{
 39 		return 1.0;
 40 	},
 41 	getAuthor: function()
 42 	{
 43 		return 'Jeff Haynie';
 44 	},
 45 	getModuleURL: function ()
 46 	{
 47 		return 'http://www.appcelerator.org';
 48 	},
 49 	isWidget: function ()
 50 	{
 51 		return true;
 52 	},
 53 	getWidgetName: function()
 54 	{
 55 		return 'app:statemachine';
 56 	},
 57     getAttributes: function(){
 58         return [{
 59             name: 'initial',
 60             optional: true,
 61             description: "Initial state of the state machine."
 62         }, {
 63             name: 'id',
 64             optional: false,
 65             description: "Id of the statemachine, which can be used as a web expression condition"
 66         }];
 67     },
 68     getChildNodes: function(){
 69         return [{
 70             name: 'state',
 71             attributes: [{
 72                 name: 'name',
 73                 description: 'state name'
 74             }, {
 75                 name: 'if',
 76                 description: 'state condition'
 77             }]
 78         }];
 79     },
 80 	buildWidget: function(element, parameters)
 81 	{
 82         var initial = parameters['initial'];
 83         var initialFound = false;
 84         var id = parameters['id'];
 85         
 86         var states = [];
 87         if (Appcelerator.Browser.isIE)
 88         {
 89             // NOTE: in IE, you have to append with namespace
 90             var newhtml = element.innerHTML;
 91             newhtml = newhtml.replace(/<STATE/g,'<APP:STATE');
 92             newhtml = newhtml.replace(/\/STATE>/g,'/APP:STATE>');
 93             element.innerHTML = newhtml;
 94         }
 95         
 96         for (var c=0,len=element.childNodes.length;c<len;c++)   
 97         {
 98             var child = element.childNodes[c];
 99             if (child.nodeType == 1 && child.nodeName.toLowerCase() == 'state')
100             {
101                 var name = child.getAttribute('name');
102                 var cond = child.getAttribute('if');
103                 
104                 if (initial && initial == name)
105                 {
106                     initialFound = true;
107                 }
108                 states.push({'name':name,'cond':cond});
109             }
110         }
111 
112         if (initial)
113         {
114             if (!initialFound)
115             {
116                 throw "invalid initial state - couldn't find state: "+initial+" for "+id;
117             }
118         }
119 
120         parameters['states']=states;
121         
122         return {
123             'position' : Appcelerator.Compiler.POSITION_REPLACE,
124             'presentation':'',
125             'compile' : true
126         };
127 	},
128 	compileWidget:function(parameters)
129 	{
130 	    var id = parameters['id'];
131 	    var element = $(id);
132 	    var initial = parameters['initial'];
133 		element.value = initial || '';
134 		var states = parameters['states'];
135 		var conditions = [];
136 		
137 		for (var c=0,len=states.length;c<len;c++)	
138 		{
139 			var state = states[c];
140 		    var name = state.name;
141 			var cond = state.cond;
142 			Appcelerator.Compiler.StateMachine.addState(id,name,null);
143 			conditions.push(Appcelerator.Compiler.StateMachine.compileStateCondition(name,cond));
144 		}
145 		
146 		var compiled = Appcelerator.Compiler.StateMachine.buildConditions(conditions);
147 		
148 		if (initial)
149 		{
150 			//
151 			// go ahead and set the initial state
152 			// and invoke appropriate listeners 
153 			//
154 			element.value = initial;
155 			Appcelerator.Compiler.StateMachine.resetOnStateListeners();
156 			if (Appcelerator.Compiler.StateMachine.initialStateLoaders)
157 			{
158 				Appcelerator.Compiler.StateMachine.initialStateLoaders.push([id,initial]);
159 			}
160 		}
161 
162 		// compile when first accessed
163 		var codeFunction = null;
164 		
165         $MQL(compiled.types, function(type, data, datatype, direction){
166             try {
167                 if (!codeFunction) {
168                     codeFunction = compiled.code.toFunction();
169                     compiled = null;
170                 }
171                 
172                 var key = direction + ':' + type;
173                 var obj = {
174                     messagetype: key,
175                     type: type,
176                     datatype: datatype,
177                     direction: direction,
178                     data: data
179                 };
180                 var state = codeFunction.call(obj);
181                 
182                 if (state) {
183                     Appcelerator.Compiler.StateMachine.fireStateMachineChange(id, state, true);
184                 }
185                 else {
186                     state = Appcelerator.Compiler.StateMachine.getActiveState(id);
187                     
188                     if (state) {
189                         Appcelerator.Compiler.StateMachine.fireStateMachineChange(id, state, null);
190                     }
191                 }
192             } 
193             catch (e) {
194                 $E('Error processing message: ' + direction + ':' + type + ' - ' + Object.getExceptionDetail(e));
195             }
196         }, element.scope, element);
197 
198 		var stateListener = function(statemachine,state,on_off)
199 		{
200 			if (on_off)
201 			{
202 				element.value = state;
203 			}
204 		};
205 		Appcelerator.Compiler.StateMachine.registerStateListener(id,stateListener);
206 		Appcelerator.Compiler.StateMachine.fireOnStateListeners();
207 		
208 		Appcelerator.Compiler.addTrash(element, function()
209 		{
210 			if (stateListener)
211 			{
212 				Appcelerator.Compiler.StateMachine.unregisterStateListener(stateListener);
213 				stateListener = null;
214 			}
215 			Appcelerator.Util.ServiceBroker.removeListener(listener);
216 		});
217 	}
218 };
219 
220 Appcelerator.Widget.register('app:statemachine',Appcelerator.Widget.Statemachine);
221