twojs-browserify
Version:
A browserified two-dimensional drawing api meant for modern browsers.
156 lines (137 loc) • 5.5 kB
JavaScript
/**
* The Events module pulled from [Backbone.js](http://backbonejs.org/)
* Stripped and modified to work with node.js and optimize types of calls
* for animation based events.
*/
var Backbone = Backbone || {};
(function() {
var array = [];
var slice = array.slice;
// Backbone.Events
// ---------------
// Regular expression used to split event strings.
var eventSplitter = /\s+/;
/**
* Events API deprecated because of additional calls and checks
* multiple times a frame tick in two.js
*/
// Optimized internal dispatch function for triggering events. Tries to
// keep the usual cases speedy (most Backbone events have 3 arguments).
var triggerEvents = function(obj, events, args) {
var ev, i = -1, l = events.length;
switch (args.length) {
case 0: while (++i < l) (ev = events[i]).callback.call(ev.ctx);
return;
case 1: while (++i < l) (ev = events[i]).callback.call(ev.ctx, args[0]);
return;
case 2: while (++i < l) (ev = events[i]).callback.call(ev.ctx, args[0], args[1]);
return;
case 3: while (++i < l) (ev = events[i]).callback.call(ev.ctx, args[0], args[1], args[2]);
return;
default: while (++i < l) (ev = events[i]).callback.apply(ev.ctx, args);
}
};
var Events = Backbone.Events = {
// Bind one or more space separated events, or an events map,
// to a `callback` function. Passing `"all"` will bind the callback to
// all events fired.
on: function(name, callback, context) {
// if (!(eventsApi(this, 'on', name, [callback, context]) && callback)) return this;
this._events || (this._events = {});
var list = this._events[name] || (this._events[name] = []);
list.push({callback: callback, context: context, ctx: context || this});
return this;
},
// Bind events to only be triggered a single time. After the first time
// the callback is invoked, it will be removed.
once: function(name, callback, context) {
// if (!(eventsApi(this, 'once', name, [callback, context]) && callback)) return this;
var self = this;
var once = _.once(function() {
self.off(name, once);
callback.apply(this, arguments);
});
once._callback = callback;
this.on(name, once, context);
return this;
},
// Remove one or many callbacks. If `context` is null, removes all
// callbacks with that function. If `callback` is null, removes all
// callbacks for the event. If `events` is null, removes all bound
// callbacks for all events.
off: function(name, callback, context) {
var list, ev, events, names, i, l, j, k;
if (!this._events/** || !eventsApi(this, 'off', name, [callback, context])**/) return this;
if (!name && !callback && !context) {
this._events = {};
return this;
}
names = name ? [name] : _.keys(this._events);
for (i = 0, l = names.length; i < l; i++) {
name = names[i];
if (list = this._events[name]) {
events = [];
if (callback || context) {
for (j = 0, k = list.length; j < k; j++) {
ev = list[j];
if ((callback && callback !== (ev.callback._callback || ev.callback)) ||
(context && context !== ev.context)) {
events.push(ev);
}
}
}
this._events[name] = events;
}
}
return this;
},
// Trigger one or many events, firing all bound callbacks. Callbacks are
// passed the same arguments as `trigger` is, apart from the event name
// (unless you're listening on `"all"`, which will cause your callback to
// receive the true name of the event as the first argument).
trigger: function(name) {
if (!this._events) return this;
var args = slice.call(arguments, 1);
// if (!eventsApi(this, 'trigger', name, args)) return this;
var events = this._events[name];
var allEvents = this._events.all;
if (events) triggerEvents(this, events, args);
if (allEvents) triggerEvents(this, allEvents, arguments);
return this;
},
// An inversion-of-control version of `on`. Tell *this* object to listen to
// an event in another object ... keeping track of what it's listening to.
listenTo: function(object, events, callback) {
var listeners = this._listeners || (this._listeners = {});
var id = object._listenerId || (object._listenerId = _.uniqueId('l'));
listeners[id] = object;
object.on(events, callback || this, this);
return this;
},
// Tell this object to stop listening to either specific events ... or
// to every object it's currently listening to.
stopListening: function(object, events, callback) {
var listeners = this._listeners;
if (!listeners) return;
if (object) {
object.off(events, callback, this);
if (!events && !callback) delete listeners[object._listenerId];
} else {
for (var id in listeners) {
listeners[id].off(null, null, this);
}
this._listeners = {};
}
return this;
}
};
// Aliases for backwards compatibility.
Events.bind = Events.on;
Events.unbind = Events.off;
if (typeof exports !== 'undefined') {
if (typeof module !== 'undefined' && module.exports) {
exports = module.exports = Events;
}
exports.Backbone = exports.Backbone || Backbone;
}
})();