ampersand-events
Version:
Module that can be mixed into any object to provide eventing. Heavily based on Backbone Events.
67 lines (60 loc) • 2.61 kB
JavaScript
var uniqueId = require('lodash/uniqueId');
var eventSplitter = /\s+/;
// A difficult-to-believe, but optimized internal dispatch function for
// triggering events. Tries to keep the usual cases speedy.
exports.triggerEvents = function triggerEvents(events, args) {
var ev;
var i = -1;
var l = events.length;
var a1 = args[0];
var a2 = args[1];
var a3 = args[2];
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, a1); return;
case 2: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2); return;
case 3: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2, a3); return;
default: while (++i < l) (ev = events[i]).callback.apply(ev.ctx, args); return;
}
};
// Implement fancy features of the Events API such as multiple event
// names `"change blur"` and jQuery-style event maps `{change: action}`
// in terms of the existing API.
exports.eventsApi = function eventsApi(obj, action, name, rest) {
if (!name) return true;
// Handle event maps.
if (typeof name === 'object') {
for (var key in name) {
obj[action].apply(obj, [key, name[key]].concat(rest));
}
return false;
}
// Handle space separated event names.
if (eventSplitter.test(name)) {
var names = name.split(eventSplitter);
for (var i = 0, l = names.length; i < l; i++) {
obj[action].apply(obj, [names[i]].concat(rest));
}
return false;
}
return true;
};
// Inversion-of-control versions of `on` and `once`. Tell *this* object to
// listen to an event in another object ... keeping track of what it's
// listening to.
exports.createListenMethod = function createListenMethod(implementation) {
return function listenMethod(obj, name, callback) {
if (!obj) {
throw new Error('Trying to listenTo event: \'' + name + '\' but the target object is undefined');
}
var listeningTo = this._listeningTo || (this._listeningTo = {});
var id = obj._listenId || (obj._listenId = uniqueId('l'));
listeningTo[id] = obj;
if (!callback && typeof name === 'object') callback = this;
if (typeof obj[implementation] !== 'function') {
throw new Error('Trying to listenTo event: \'' + name + '\' on object: ' + obj.toString() + ' but it does not have an \'on\' method so is unbindable');
}
obj[implementation](name, callback, this);
return this;
};
};