channel:join + channel:leave plugin events
[KiwiIRC.git] / server / plugininterface.js
index 3a02e39f5a1a5c320ff4e71113173cebdae9393c..3810bc0fad80827e6f5b9f817a73e676615875cb 100644 (file)
  * 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 = [],
@@ -18,10 +135,10 @@ function EmitCall (event_name, event_data) {
     // 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();
@@ -83,11 +200,12 @@ function EmitCall (event_name, event_data) {
         completed = true;
 
         var funcs = prevented ? prevented_fn : completed_fn;
+        funcs = funcs || [];
 
         // Call the completed/prevented functions
-        (funcs || []).forEach(function (fn) {
-            if (typeof fn === 'function') fn();
-        });
+        for (var idx = 0; idx < funcs.length; idx++) {
+            if (typeof funcs[idx] === 'function') funcs[idx]();
+        }
     }
 
 
@@ -121,87 +239,17 @@ function EmitCall (event_name, event_data) {
 
     return {
         callListeners: callListeners,
-        done: addCompletedFunc,
-        prevented: addPreventedFunc
+        then: addCompletedFunc,
+        catch: addPreventedFunc
     };
-}
-
-
-
-
-
-
-function PluginInterface () {
-    // Holder for all the bound listeners by this module
-    this._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]);
-};
-
-
-
-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];
-            }
-        }
-    }
 };
 
 
 
-// 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;
-};
-
-
-module.exports = PluginInterface;
+// If running a node module, set the exports
+if (typeof module === 'object' && typeof module.exports !== 'undefined') {
+    module.exports = PluginInterface;
+}
 
 
 
@@ -216,7 +264,7 @@ var modules = new PluginInterface();
 
 
 // A plugin
-modules.on('client:command', function (event, data) {
+modules.on('irc message', function (event, data) {
     //event.wait = true;
     setTimeout(event.callback, 2000);
 });
@@ -230,8 +278,7 @@ var data = {
     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