172 lines
5.2 KiB
JavaScript
172 lines
5.2 KiB
JavaScript
/**
|
|
* BANE - Browser globals, AMD and Node Events
|
|
*
|
|
* https://github.com/busterjs/bane
|
|
*
|
|
* @version 1.0.0
|
|
*/
|
|
|
|
((typeof define === "function" && define.amd && function (m) { define("bane", m); }) ||
|
|
(typeof module === "object" && function (m) { module.exports = m(); }) ||
|
|
function (m) { this.bane = m(); }
|
|
)(function () {
|
|
"use strict";
|
|
var slice = Array.prototype.slice;
|
|
|
|
function handleError(event, error, errbacks) {
|
|
var i, l = errbacks.length;
|
|
if (l > 0) {
|
|
for (i = 0; i < l; ++i) { errbacks[i](event, error); }
|
|
return;
|
|
}
|
|
setTimeout(function () {
|
|
error.message = event + " listener threw error: " + error.message;
|
|
throw error;
|
|
}, 0);
|
|
}
|
|
|
|
function assertFunction(fn) {
|
|
if (typeof fn !== "function") {
|
|
throw new TypeError("Listener is not function");
|
|
}
|
|
return fn;
|
|
}
|
|
|
|
function supervisors(object) {
|
|
if (!object.supervisors) { object.supervisors = []; }
|
|
return object.supervisors;
|
|
}
|
|
|
|
function listeners(object, event) {
|
|
if (!object.listeners) { object.listeners = {}; }
|
|
if (event && !object.listeners[event]) { object.listeners[event] = []; }
|
|
return event ? object.listeners[event] : object.listeners;
|
|
}
|
|
|
|
function errbacks(object) {
|
|
if (!object.errbacks) { object.errbacks = []; }
|
|
return object.errbacks;
|
|
}
|
|
|
|
/**
|
|
* @signature var emitter = bane.createEmitter([object]);
|
|
*
|
|
* Create a new event emitter. If an object is passed, it will be modified
|
|
* by adding the event emitter methods (see below).
|
|
*/
|
|
function createEventEmitter(object) {
|
|
object = object || {};
|
|
|
|
function notifyListener(event, listener, args) {
|
|
try {
|
|
listener.listener.apply(listener.thisp || object, args);
|
|
} catch (e) {
|
|
handleError(event, e, errbacks(object));
|
|
}
|
|
}
|
|
|
|
object.on = function (event, listener, thisp) {
|
|
if (typeof event === "function") {
|
|
return supervisors(this).push({
|
|
listener: event,
|
|
thisp: listener
|
|
});
|
|
}
|
|
listeners(this, event).push({
|
|
listener: assertFunction(listener),
|
|
thisp: thisp
|
|
});
|
|
};
|
|
|
|
object.off = function (event, listener) {
|
|
var fns, events, i, l;
|
|
if (!event) {
|
|
fns = supervisors(this);
|
|
fns.splice(0, fns.length);
|
|
|
|
events = listeners(this);
|
|
for (i in events) {
|
|
if (events.hasOwnProperty(i)) {
|
|
fns = listeners(this, i);
|
|
fns.splice(0, fns.length);
|
|
}
|
|
}
|
|
|
|
fns = errbacks(this);
|
|
fns.splice(0, fns.length);
|
|
|
|
return;
|
|
}
|
|
if (typeof event === "function") {
|
|
fns = supervisors(this);
|
|
listener = event;
|
|
} else {
|
|
fns = listeners(this, event);
|
|
}
|
|
if (!listener) {
|
|
fns.splice(0, fns.length);
|
|
return;
|
|
}
|
|
for (i = 0, l = fns.length; i < l; ++i) {
|
|
if (fns[i].listener === listener) {
|
|
fns.splice(i, 1);
|
|
return;
|
|
}
|
|
}
|
|
};
|
|
|
|
object.once = function (event, listener, thisp) {
|
|
var wrapper = function () {
|
|
object.off(event, wrapper);
|
|
listener.apply(this, arguments);
|
|
};
|
|
|
|
object.on(event, wrapper, thisp);
|
|
};
|
|
|
|
object.bind = function (object, events) {
|
|
var prop, i, l;
|
|
if (!events) {
|
|
for (prop in object) {
|
|
if (typeof object[prop] === "function") {
|
|
this.on(prop, object[prop], object);
|
|
}
|
|
}
|
|
} else {
|
|
for (i = 0, l = events.length; i < l; ++i) {
|
|
if (typeof object[events[i]] === "function") {
|
|
this.on(events[i], object[events[i]], object);
|
|
} else {
|
|
throw new Error("No such method " + events[i]);
|
|
}
|
|
}
|
|
}
|
|
return object;
|
|
};
|
|
|
|
object.emit = function (event) {
|
|
var toNotify = supervisors(this);
|
|
var args = slice.call(arguments), i, l;
|
|
|
|
for (i = 0, l = toNotify.length; i < l; ++i) {
|
|
notifyListener(event, toNotify[i], args);
|
|
}
|
|
|
|
toNotify = listeners(this, event).slice();
|
|
args = slice.call(arguments, 1);
|
|
for (i = 0, l = toNotify.length; i < l; ++i) {
|
|
notifyListener(event, toNotify[i], args);
|
|
}
|
|
};
|
|
|
|
object.errback = function (listener) {
|
|
if (!this.errbacks) { this.errbacks = []; }
|
|
this.errbacks.push(assertFunction(listener));
|
|
};
|
|
|
|
return object;
|
|
}
|
|
|
|
return { createEventEmitter: createEventEmitter };
|
|
});
|