* The same functionality as EventEmitter but with the inclusion of callbacks
*/
-/*
- * Promise style object to emit events to listeners
- */
-function EmitCall (event_name, event_data) {
+
+
+function PluginInterface () {
+ // Holder for all the bound listeners by this module
+ this._listeners = {};
+
+ // Event proxies
+ this._parent = null;
+ this._children = [];
+}
+
+
+
+PluginInterface.prototype.on = function (event_name, fn, scope) {
+ this._listeners[event_name] = this._listeners[event_name] || [];
+ this._listeners[event_name].push(['on', fn, scope]);
+};
+
+
+
+PluginInterface.prototype.once = function (event_name, fn, scope) {
+ this._listeners[event_name] = this._listeners[event_name] || [];
+ this._listeners[event_name].push(['once', fn, scope]);
+};
+
+
+
+PluginInterface.prototype.off = function (event_name, fn, scope) {
+ var idx;
+
+ if (typeof event_name === 'undefined') {
+ // Remove all listeners
+ this._listeners = {};
+
+ } else if (typeof fn === 'undefined') {
+ // Remove all of 1 event type
+ delete this._listeners[event_name];
+
+ } else if (typeof scope === 'undefined') {
+ // Remove a single event type + callback
+ for (idx in (this._listeners[event_name] || [])) {
+ if (this._listeners[event_name][idx][1] === fn) {
+ delete this._listeners[event_name][idx];
+ }
+ }
+ } else {
+ // Remove a single event type + callback + scope
+ for (idx in (this._listeners[event_name] || [])) {
+ if (this._listeners[event_name][idx][1] === fn && this._listeners[event_name][idx][2] === scope) {
+ delete this._listeners[event_name][idx];
+ }
+ }
+ }
+};
+
+
+
+PluginInterface.prototype.getListeners = function(event_name) {
+ return this._listeners[event_name] || [];
+};
+
+
+
+PluginInterface.prototype.createProxy = function() {
+ var proxy = new PluginInterface();
+ proxy._parent = this._parent || this;
+ proxy._parent._children.push(proxy);
+
+ return proxy;
+};
+
+
+
+PluginInterface.prototype.dispose = function() {
+ this.off();
+
+ if (this._parent) {
+ var idx = this._parent._children.indexOf(this);
+ if (idx > -1) {
+ this._parent._children.splice(idx, 1);
+ }
+ }
+};
+
+
+
+// Call all the listeners for a certain event, passing them some event data that may be changed
+PluginInterface.prototype.emit = function (event_name, event_data) {
+ var emitter = new this.EmitCall(event_name, event_data),
+ listeners = [],
+ child_idx;
+
+ // Get each childs event listeners in order of last created
+ for(child_idx=this._children.length-1; child_idx>=0; child_idx--) {
+ listeners = listeners.concat(this._children[child_idx].getListeners(event_name));
+ }
+
+ // Now include any listeners directly on this instance
+ listeners = listeners.concat(this.getListeners(event_name));
+
+ // Once emitted, remove any 'once' bound listeners
+ emitter.then(function () {
+ var len = listeners.length,
+ idx;
+
+ for(idx = 0; idx < len; idx++) {
+ if (listeners[idx][0] === 'once') {
+ listeners[idx] = undefined;
+ }
+ }
+ });
+
+ // Emit the event to the listeners and return
+ emitter.callListeners(listeners);
+ return emitter;
+};
+
+
+
+// Promise style object to emit events to listeners
+PluginInterface.prototype.EmitCall = function EmitCall (event_name, event_data) {
var that = this,
completed = false,
- completed_fn = [];
+ completed_fn = [],
+
+ // Has event.preventDefault() been called
+ prevented = false,
+ prevented_fn = [];
// Emit this event to an array of listeners
function callListeners(listeners) {
var current_event_idx = -1;
-
+
// Make sure we have some data to pass to the listeners
event_data = event_data || undefined;
-
+
// If no bound listeners for this event, leave now
if (listeners.length === 0) {
emitComplete();
// If wait is true, this callback must be called to continue running listeners
callback: function () {
// Invalidate this callback incase a listener decides to call it again
- callback = undefined;
+ event_obj.callback = undefined;
nextListener.apply(that);
+ },
+
+ // Prevents the default 'done' functions from executing
+ preventDefault: function () {
+ prevented = true;
}
};
function emitComplete() {
completed = true;
- // Call the completed functions
- (completed_fn || []).forEach(function (fn) {
- if (typeof fn === 'function') fn();
- });
+ var funcs = prevented ? prevented_fn : completed_fn;
+ funcs = funcs || [];
+
+ // Call the completed/prevented functions
+ for (var idx = 0; idx < funcs.length; idx++) {
+ if (typeof funcs[idx] === 'function') funcs[idx]();
+ }
}
- function done(fn) {
+ function addCompletedFunc(fn) {
// Only accept functions
if (typeof fn !== 'function') return false;
completed_fn.push(fn);
// If we have already completed the emits, call this now
- if (completed) fn();
- }
-
-
- return {
- callListeners: callListeners,
- done: done
- };
-}
-
-
-
-
+ if (completed && !prevented) fn();
-
-function PluginInterface () {
-}
-
-
-// Holder for all the bound listeners by this module
-PluginInterface.prototype._listeners = {};
-
-
-
-PluginInterface.prototype.on = function (event_name, fn, scope) {
- this._listeners[event_name] = this._listeners[event_name] || [];
- this._listeners[event_name].push(['on', fn, scope]);
-};
-
-
-
-PluginInterface.prototype.once = function (event_name, fn, scope) {
- this._listeners[event_name] = this._listeners[event_name] || [];
- this._listeners[event_name].push(['once', fn, scope]);
-};
+ return this;
+ }
-PluginInterface.prototype.off = function (event_name, fn, scope) {
- var idx;
+ function addPreventedFunc(fn) {
+ // Only accept functions
+ if (typeof fn !== 'function') return false;
- if (typeof event_name === 'undefined') {
- // Remove all listeners
- this._listeners = [];
+ prevented_fn.push(fn);
- } else if (typeof fn === 'undefined') {
- // Remove all of 1 event type
- delete this._listeners[event_name];
+ // If we have already completed the emits, call this now
+ if (completed && prevented) fn();
- } else if (typeof scope === 'undefined') {
- // Remove a single event type + callback
- for (idx in (this._listeners[event_name] || [])) {
- if (this._listeners[event_name][idx][1] === fn) {
- delete this._listeners[event_name][idx];
- }
- }
- } else {
- // Remove a single event type + callback + scope
- for (idx in (this._listeners[event_name] || [])) {
- if (this._listeners[event_name][idx][1] === fn && this._listeners[event_name][idx][2] === scope) {
- delete this._listeners[event_name][idx];
- }
- }
+ return this;
}
-};
-
-// Call all the listeners for a certain event, passing them some event data that may be changed
-PluginInterface.prototype.emit = function (event_name, event_data) {
- var emitter = new EmitCall(event_name, event_data);
- var listeners = this._listeners[event_name] || [];
-
- // Once emitted, remove any 'once' bound listeners
- emitter.done(function () {
- listeners.forEach(function (listener, idx) {
- if (listener[0] === 'once') {
- listeners[idx] = undefined;
- }
- });
- });
-
- // Emit the event to the listeners and return
- emitter.callListeners(listeners);
- return emitter;
+ return {
+ callListeners: callListeners,
+ then: addCompletedFunc,
+ catch: addPreventedFunc
+ };
};
-module.exports = PluginInterface;
+
+// If running a node module, set the exports
+if (typeof module === 'object' && typeof module.exports !== 'undefined') {
+ module.exports = PluginInterface;
+}
// A plugin
-modules.on('client:command', function (event, data) {
+modules.on('irc message', function (event, data) {
//event.wait = true;
setTimeout(event.callback, 2000);
});
command: '/dothis'
};
-
-modules.emit('client:command', data).done(function () {
+modules.emit('irc message', data).done(function () {
console.log('Your command is: ' + data.command);
});
*/
\ No newline at end of file