varinitial=(typeofcfg.initial=='string')?{state:cfg.initial}:cfg.initial;// allow for a simple string, or an object with { state: 'foo', event: 'setup', defer: true|false }
varterminal=cfg.terminal||cfg['final'];
varfsm=target||cfg.target||{};
varevents=cfg.events||[];
varcallbacks=cfg.callbacks||{};
varmap={};
varadd=function(e){
varfrom=(e.frominstanceofArray)?e.from:(e.from?[e.from]:[StateMachine.WILDCARD]);// allow 'wildcard' transition if 'from' is not specified
map[e.name]=map[e.name]||{};
for(varn=0;n<from.length;n++)
map[e.name][from[n]]=e.to||from[n];// allow no-op transition if 'to' is not specified
fsm.error=cfg.error||function(name,from,to,args,error,msg,e){throwe||msg;};// default behavior when something unexpected happens is to throw an exception, but caller can override this behavior if desired (see github issue #3 and #17)
// prepare a transition method for use EITHER lower down, or by caller if they want an async transition (indicated by an ASYNC return value from leaveState)
varfsm=this;
this.transition=function(){
fsm.transition=null;// this method should only ever be called once
fsm.current=to;
StateMachine.enterState(fsm,name,from,to,args);
StateMachine.changeState(fsm,name,from,to,args);
StateMachine.afterEvent(fsm,name,from,to,args);
returnStateMachine.Result.SUCCEEDED;
};
this.transition.cancel=function(){// provide a way for caller to cancel async transition if desired (issue #22)