Skip to content

Instantly share code, notes, and snippets.

@thejefflarson
Last active December 17, 2015 11:19
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save thejefflarson/5601872 to your computer and use it in GitHub Desktop.
Save thejefflarson/5601872 to your computer and use it in GitHub Desktop.
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