/**
1. Used for 2-ways data-binding: bind(),on(),trigger(),unbind()
Events._callbacks = {
'create': [callback1, callback2...],
'change:tab': [func1, func2, func3],
'user.update': [function(){}]
}
2. Usage:
var Tasks = Object.create(Events);
Tasks.bind("create", function(foo, bar){ console.log(foo,bar); });
Tasks.trigger("create", "some", "data");
Tasks.bind('update change:tab user.update', function(data) {
return this.trigger('create', data);
});
Tasks.trigger("change:tab", "some", "data");
*/
var Events = {
bind: function (ev, callback) {
//csv: "create change:tab user.update"
var evs = ev.split(/\s+/);
//like a pub/sub: http://benalman.com
var calls = (this.hasOwnProperty('_callbacks') && this._callbacks) || (this._callbacks = {});
//register callback to calls{}
for (var i = 0, len = evs.length; i < len; i = i + 1) {
(calls[evs[i]] || (calls[evs[i]] = [])).push(callback);
}
return this;
},
trigger: function () {
var args = makeArray(arguments);
var ev = args.shift();
// calls is a {}, not a [], calls[ev] is a [], not a ''.
var list, calls, i, len;
if (!(calls = (this.hasOwnProperty('_callbacks') && this._callbacks))) return false;
// one event can be multi-callbacks
if (!(list = calls[ev])) return false;
for (i = 0, len = list.length; i < len; i = i + 1) {
if (list[i].apply(this, args) === false) return false;
}
return true;
},
unbind: function (ev, callback) {
if (!ev) {
this._callbacks = {};
return this;
}
var list, calls, i, len;
if (!(calls = this._callbacks)) return this;
if (!(list = calls[ev])) return this;
if (!callback) {
delete this._callback[ev];
return this;
}
for (i = 0, len = list.length; i < len; i++) {
if (callback === list[i]) {
list = list.slice();
list.splice(i, 1);
calls[ev] = list;
break;
}
return this;
}
}
};
//create reference
Events.on = Events.bind;
//return array of arguments.
var makeArray = function (args) {
// array.slice(start, end):
var slice = Array.prototype.slice; //slice=[].slice;
return slice.call(args, 0); //.apply(arguments, [0]);
};