Home

Awesome

iFSM - a Flexible Finite and Hierarchical State Machine ( FSM / HSM ) for JQuery Objects

Designed to manage the complexity of graphic user interface behaviours with javascript, this jQuery package can animate and manage HTML elements with their dynamic behaviours using Finite State Machines.

It takes jQuery objects to define the states of the Web page elements and the events the page elements should react on.

Each state may be defined with the code that has to be executed when the element enters or leaves a state.

The state definition may also define what is the next state when a given event happens on that element, like for instance the user clicks on the element. All jQuery events are supported to trigger the change of state. An autobinding mecanism automatically binds the events defined in the states.

It also supports conditional processing of events and state changes using sub-machine states, as well creating new states and events dynamically.

The FSM has Push/Pop state capabilities and offers different useful features as:

Official website

http://www.intersel.fr/ifsm-jquery-plugin-demos.html with some live demos

The "Hello world" example

This example shows a really simple example implementing the following state diagram:

<!DOCTYPE html>
<html>
<head>
    <title>iFSM in action! a Finite State Machine for jQuery</title>
	<script type="text/javascript" src="extlib/jquery.min.js"></script>
	<script type="text/javascript" src="extlib/jquery.dotimeout.js"></script>
	<script type="text/javascript" src="extlib/jquery.attrchange.js"></script>
	<script type="text/javascript" src="iFSM.js"></script>

    <script type="text/javascript">
    	var aStateDefinition = {
		FirstState:
		{
		     enterState:
		    {
		        init_function: function(){alert("Hello! First State");}
		    },
		    click:   
		    {
		        next_state: 'NextState'
		    }
		},
		NextState:
		{
		    enterState:   
		    {
		        init_function: function(){alert("Please to meet you! Next State");}
		    },
		    click:   
		    {
		        next_state: 'FirstState'
		    }
		},
		DefaultState:
		{
		    start:
		    {
		        next_state: 'FirstState'
		    }
		}
	};
	$(document).ready(function() {
		$('#myButton').iFSM(aStateDefinition);
	});

    </script>
</head>
<body style="margin:100px;">
    <button id="myButton">Click Me</button>
</body>
</html>

Examples

See them live: http://www.intersel.fr/ifsm-jquery-plugin-demos.html#demolist

See some nice HTML5 animations done with specific machines made with iFSMAnimation:

.iFSM(aStateDefinition, [options])

Create a Finite State Machine from the "aStateDefinition" object to bind with the jQuery object.

Call Examples

  <button id="myButton">Button</button>
  <script>
  	aFSMDefinition = {
  		aState:{
  			click:{
  				init_function:function(){
  					alert(this.opts.inputFunction(this.opts.inputData));
  				}
  			}
  		}
  	};
	$('#myButton').iFSM(aFSMDefinition,{
		 initState:'aState'
		,inputData:'Hello World :-)'
		,inputFunction:function(aText){return aText;}
		,LogLevel:1
		});  
  </script>

.getFSM([aStateDefinition])

returns the array of FSMs bound to the jQuery object or the FSM if "aStateDefinition" is set.

Call Examples

  <script>
  myFSMs = $('#myButton').getFSM(); //get the linked FSM objects in an array
  </script>

Machine State Definition

The states are defined with a javascript object with the following organization:

var aStateDefinition =
{
 <aStateName1>:
 {
 	delegate_machines	:
 	{
 		<aSubMachine name 1>:
 		{
 			submachine: <a State definition>,
 			no_reinitialisation: <boolean, default:false>
 		},			
 		<aSubMachine name i>:
 		{
 			submachine: <a State definition>
 		},			
 		...
 	},	  		
 	<aEventName1>:
 	{
		how_process_event: <immediate||push (default)||{delay:<adelay>,preventcancel:<false(default)|true>}>,
		init_function: <a function(parameters, event, data)>,
 		properties_init_function: <parameters for init_function>,
 		next_state: <aStateName>,
 		pushpop_state: <'PushState'||'PopState'>,
 		next_state_when: <a statement that returns boolean>,
 		next_state_on_target:
 		{
 			condition 			: <'||'||'&&'>
 			submachines			:
 			{
 				<submachineName1> 	:
 				{
 					condition	: <''(default)||'not'>
					target_list: [<targetState1>,...,<targetStaten>],
 				}
 				...
 				<submachineNamen> 	: ...
	 		}
 		}
 		next_state_if_error: <aStateName>,
 		pushpop_state_if_error: <'PushState'||'PopState'>,
 		propagate_event: <true||anEventName||[anEventName1,anEventName2,...]>
 		process_event_if: <a statement that returns boolean>,
 		propagate_event_on_refused: <anEventName>
 		out_function: <a function(parameters, event, data)>,
 		properties_out_function: <parameters for out_function>,
 		prevent_bubble: <true|false(default)>
 		propagate_event_on_localmachine: <true|false(default)>
 		process_on_UItarget: <true|false(default)>
 		UI_event_bubble: <true|false(default)>
 	},
 	<aEventName....>: <anOtherEventName>,
 	<aEventName....>:
 	{
 		....
 	},
 	enterState: ...
 	exitState:  ...
 },
 <aStateName...>: <anAnotherStateName>,
 <aStateName...>:
 {
 	....
 },
 DefaultState:
 {
 	start: //a default start event received at the FSM start
 	{
 	},
 	<aEventName....>:
 	{
 	},
 	catchEvent:
 	{
 	}
 }
}

The start of a machine or a sub-machine

When the machine starts, the starting state is 'DefaultState'.

A 'start' event is always triggered when the FSM is started.

The 'DefaultState' state may be used to define the default behaviours of some events...

There is no 'enterState' event triggered for this default state. This kind of event may be managed when 'start' event is received in order to initialize the machine.

The initial state of the FSM may be redefined with the option 'options.initState'.

Event Processing

When a event is received by the machine, it is first searched in the current state, and if not found, then searched in the 'DefaultState'.

When an event is not found, then it is dropped and nothing is done...

It is possible to trigger any event to a machine with the jquery trigger function. Examples:

  $('#myButton1').trigger('aEventName');
  $('#myButton1').trigger('aEventName',data);
  $('#myButton1').trigger('aEventName',{data1:adata1,data2:adata2});

In a state/event function, you can trigger event to the current machine:

   this.trigger('aEventName')

By default, when a machine receives a new event and is currently processing one, it will push it in its next event list to be processed... and gives back the hand...

This way, any function that triggers an event will have immediatly the hand back without changing the processing context. It prevents any uncontrolled effects that could arouse with the normal trigger mecanisms that process the (sub)events immediatly and may change/disturb the context of event processing.

Of course, if you want to have the event immediatly processed, you can ask it with the "immediate" option.

Or on the contrary, to have the event processed after a delay, you can use the "delay:[delay_value]" option.

Delayed Events

By default, any delayed event will be cancelled if the state of the machine change, as it is considered that the event has its context changed...

It is possible to keep it even though the state changed with the 'preventcancel' option but beware to side effects.

If a delayed event is sent again before a previous one on the same event was processed, the previous event is cancelled and the new one replaces it starting with the initial delay.

The "how_process_event" allows to define how the event should be processed by the machine.

SubMachines

A submachine is a autonomous FSM working in the scope of a state defined in its parent machine.

The public available variables

Within the call of FSM function, you can refer to the FSM by 'this':

LIBRARY DEPENDENCIES

To work properly, you need to include the following javascript library:

FAQ

If you have questions or unsolved problems, you can have a look on the our FAQs or leave a message on the Issue board.

Contact

If you have any ideas, feedback, requests or bug reports, you can reach me at github@intersel.org, or via my website: http://www.intersel.fr or https://www.livinweb.fr/