simple state machine
(function(){ | |
var State = function(name) { | |
this.name = name; | |
}; | |
State.prototype.from = function(from) { | |
this.from_ = from; | |
return this; | |
}; | |
State.prototype.to = function(to) { | |
this.to_ = to; | |
}; | |
State.prototype.can = function(from, to){ | |
if(Array.isArray(this.from_)) { | |
return !!~this.from_.indexOf(from) && to === this.to_; | |
} else { | |
return from === this.from_ && to === this.to_; | |
} | |
}; | |
window.KeyMaster = { | |
events: {}, | |
_callbacks: {}, | |
add : function(evt){ | |
this.events[evt] = new State(evt); | |
this[evt] = function(){ | |
return this.transition.apply(this, arguments); | |
}.bind(this, evt); | |
return this.events[evt]; | |
}, | |
transition : function(evt) { | |
if(!this.current) | |
throw "not initialized"; | |
if(!this.events[evt].can(this.current, this.events[evt].to_)) | |
return this.current + " can't transition to " + this.events[evt].to_; | |
if(!this.events[evt]) | |
throw "unknown transition " + evt; | |
this._call.apply(this, arguments); | |
}, | |
on : function(e, fn){ | |
var callbacks = (this._callbacks[e] || (this._callbacks[e] = [])); | |
callbacks.push(fn); | |
}, | |
initial : function(key){ | |
if(this.current) throw "Already initialized"; | |
this.current = key; | |
}, | |
_call : function(evt){ | |
var before, after, args = [].slice.call(arguments, 1, arguments.length); | |
this._trigger.apply(this, ['before:' + evt, evt].concat(args)); | |
this.current = this.events[evt].to_; | |
this._trigger.apply(this, ['after:' + evt, evt].concat(args)); | |
}, | |
_trigger : function(e){ | |
var callbacks = this._callbacks[e]; | |
if(!callbacks) return; | |
for(var i = 0; i < callbacks.length; i++) | |
callbacks[i].apply(this, arguments); | |
} | |
}; | |
})(); | |
// tests | |
KeyMaster.add('warn').from('green').to('yellow'); | |
KeyMaster.add('panic').from('yellow').to('red'); | |
KeyMaster.add('calm').from('red').to('yellow'); | |
KeyMaster.add('clear').from('yellow').to('green'); | |
KeyMaster.initial('green'); | |
KeyMaster.warn(); | |
KeyMaster.panic(); | |
KeyMaster.calm(); | |
KeyMaster.clear(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment