2 * The same functionality as EventEmitter but with the inclusion of callbacks
7 function PluginInterface () {
8 // Holder for all the bound listeners by this module
18 PluginInterface
.prototype.on = function (event_name
, fn
, scope
) {
19 this._listeners
[event_name
] = this._listeners
[event_name
] || [];
20 this._listeners
[event_name
].push(['on', fn
, scope
]);
25 PluginInterface
.prototype.once = function (event_name
, fn
, scope
) {
26 this._listeners
[event_name
] = this._listeners
[event_name
] || [];
27 this._listeners
[event_name
].push(['once', fn
, scope
]);
32 PluginInterface
.prototype.off = function (event_name
, fn
, scope
) {
35 if (typeof event_name
=== 'undefined') {
36 // Remove all listeners
39 } else if (typeof fn
=== 'undefined') {
40 // Remove all of 1 event type
41 delete this._listeners
[event_name
];
43 } else if (typeof scope
=== 'undefined') {
44 // Remove a single event type + callback
45 for (idx
in (this._listeners
[event_name
] || [])) {
46 if (this._listeners
[event_name
][idx
][1] === fn
) {
47 delete this._listeners
[event_name
][idx
];
51 // Remove a single event type + callback + scope
52 for (idx
in (this._listeners
[event_name
] || [])) {
53 if (this._listeners
[event_name
][idx
][1] === fn
&& this._listeners
[event_name
][idx
][2] === scope
) {
54 delete this._listeners
[event_name
][idx
];
62 PluginInterface
.prototype.getListeners = function(event_name
) {
63 return this._listeners
[event_name
] || [];
68 PluginInterface
.prototype.createProxy = function() {
69 var proxy
= new PluginInterface();
70 proxy
._parent
= this._parent
|| this;
71 proxy
._parent
._children
.push(proxy
);
78 PluginInterface
.prototype.dispose = function() {
82 var idx
= this._parent
._children
.indexOf(this);
84 this._parent
._children
.splice(idx
, 1);
91 // Call all the listeners for a certain event, passing them some event data that may be changed
92 PluginInterface
.prototype.emit = function (event_name
, event_data
) {
93 var emitter
= new this.EmitCall(event_name
, event_data
),
97 // Get each childs event listeners in order of last created
98 for(child_idx
=this._children
.length
-1; child_idx
>=0; child_idx
--) {
99 listeners
= listeners
.concat(this._children
[child_idx
].getListeners(event_name
));
102 // Now include any listeners directly on this instance
103 listeners
= listeners
.concat(this.getListeners(event_name
));
105 // Once emitted, remove any 'once' bound listeners
106 emitter
.then(function () {
107 var len
= listeners
.length
,
110 for(idx
= 0; idx
< len
; idx
++) {
111 if (listeners
[idx
][0] === 'once') {
112 listeners
[idx
] = undefined;
117 // Emit the event to the listeners and return
118 emitter
.callListeners(listeners
);
124 // Promise style object to emit events to listeners
125 PluginInterface
.prototype.EmitCall
= function EmitCall (event_name
, event_data
) {
130 // Has event.preventDefault() been called
135 // Emit this event to an array of listeners
136 function callListeners(listeners
) {
137 var current_event_idx
= -1;
139 // Make sure we have some data to pass to the listeners
140 event_data
= event_data
|| undefined;
142 // If no bound listeners for this event, leave now
143 if (listeners
.length
=== 0) {
149 // Call the next listener in our array
150 function nextListener() {
151 var listener
, event_obj
;
153 // We want the next listener
156 // If we've ran out of listeners end this emit call
157 if (!listeners
[current_event_idx
]) {
162 // Object the listener ammends to tell us what it's going to do
164 // If changed to true, expect this listener is going to callback
167 // If wait is true, this callback must be called to continue running listeners
168 callback: function () {
169 // Invalidate this callback incase a listener decides to call it again
170 event_obj
.callback
= undefined;
172 nextListener
.apply(that
);
175 // Prevents the default 'done' functions from executing
176 preventDefault: function () {
182 listener
= listeners
[current_event_idx
];
183 listener
[1].call(listener
[2] || that
, event_obj
, event_data
);
185 // If the listener hasn't signalled it's going to wait, proceed to next listener
186 if (!event_obj
.wait
) {
187 // Invalidate the callback just incase a listener decides to call it anyway
188 event_obj
.callback
= undefined;
199 function emitComplete() {
202 var funcs
= prevented
? prevented_fn
: completed_fn
;
205 // Call the completed/prevented functions
206 for (var idx
= 0; idx
< funcs
.length
; idx
++) {
207 if (typeof funcs
[idx
] === 'function') funcs
[idx
]();
213 function addCompletedFunc(fn
) {
214 // Only accept functions
215 if (typeof fn
!== 'function') return false;
217 completed_fn
.push(fn
);
219 // If we have already completed the emits, call this now
220 if (completed
&& !prevented
) fn();
227 function addPreventedFunc(fn
) {
228 // Only accept functions
229 if (typeof fn
!== 'function') return false;
231 prevented_fn
.push(fn
);
233 // If we have already completed the emits, call this now
234 if (completed
&& prevented
) fn();
241 callListeners
: callListeners
,
242 then
: addCompletedFunc
,
243 catch: addPreventedFunc
249 // If running a node module, set the exports
250 if (typeof module
=== 'object' && typeof module
.exports
!== 'undefined') {
251 module
.exports
= PluginInterface
;
262 var modules = new PluginInterface();
267 modules.on('irc message', function (event, data) {
269 setTimeout(event.callback, 2000);
275 // Core code that is being extended by plugins
281 modules.emit('irc message', data).done(function () {
282 console.log('Your command is: ' + data.command);