Skip to content

Instantly share code, notes, and snippets.

@cqfd
Created February 10, 2012 06:22
Show Gist options
  • Save cqfd/1787158 to your computer and use it in GitHub Desktop.
Save cqfd/1787158 to your computer and use it in GitHub Desktop.
SM = function(options) {
console.log(options);
options || (options = {});
this.current = (options['start'] || this.current || 'start');
this._transitions = {};
this._leaves = {};
this._enters = {};
this._allowed = {};
};
_.extend(SM.prototype, Backbone.Events, {
transitionRegExp: /transition\|\|(\w+)\|\|(\w+)/,
leaveRegExp: /leave\|\|(\w+)/,
enterRegExp: /enter\|\|(\w+)/,
isAllowed: function(from) {
var args = Array.prototype.slice.call(arguments);
this._allowed[from] || (this._allowed[from] = []);
if (this._allowed[from].length === 0) {
return false;
} else {
var to = args[1];
var available = this._allowed[from];
if (to) {
return _.any(available, function(t) {
return t === to;
});
} else {
return this._allowed[from].length > 0;
}
}
},
toTransitionString: function(from, to) {
return "transition||" + from + "||" + to;
},
toLeaveString: function(from) {
return "leave||" + from;
},
toEnterString: function(to) {
return "to||" + to;
},
ontransition: function(from, to, cb) {
this.on(this.toTransitionString(from, to), cb);
return this;
},
_transition: function(to) {
var from = this.current;
if (this.isAllowed(from, to)) {
var args = Array.prototype.slice.call(arguments, 1);
this._leave(from, args);
var evt = this.toTransitionString(from, to);
args.unshift(evt);
this.trigger.apply(this, args);
this._enter(to, args);
return this;
} else {
console.log("ERROR! Invalid transition:", from, to);
}
},
onleave: function(from, cb) {
this.on(this.toLeaveString(from), cb);
return this;
},
_leave: function(from, args) {
var args = _.clone(args);
var evt = this.toLeaveString(from);
args.unshift(evt);
this.trigger.apply(this, args);
return this;
},
onenter: function(to, cb) {
this.on(this.toEnterString(to), cb);
return this;
},
enter: function(to) {
var from = this.current;
if (this.isAllowed(from, to)) {
this._transition(to);
this.current = to;
return this;
} else {
console.log("ERROR! Unable to enter '" + to + "' state from '" + from + "'.");
}
},
_enter: function(from, args) {
var args = _.clone(args);
var evt = this.toEnterString(from);
args.unshift(evt);
this.trigger.apply(this, args);
return this;
},
addTransition: function(from, to) {
if (from && to) {
this._allowed[from] || (this._allowed[from] = []);
this._allowed[from].push(to);
return this;
} else {
console.log("ERROR! Transitions need to have a from state and a to state.");
}
}
});
SM.extend = Backbone.Model.extend;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment