a44fc7c8af84ef7dff529304518269fe5cb2f2df
2 * The same functionality as EventEmitter but with the inclusion of callbacks
6 * Promise style object to emit events to listeners
8 function EmitCall (event_name
, event_data
) {
14 // Emit this event to an array of listeners
15 function callListeners(listeners
) {
16 var current_event_idx
= -1;
18 // Make sure we have some data to pass to the listeners
19 event_data
= event_data
|| undefined;
21 // If no bound listeners for this event, leave now
22 if (listeners
.length
=== 0) {
28 // Call the next listener in our array
29 function nextListener() {
30 var listener
, event_obj
;
32 // We want the next listener
35 // If we've ran out of listeners end this emit call
36 if (!listeners
[current_event_idx
]) {
41 // Object the listener ammends to tell us what it's going to do
43 // If changed to true, expect this listener is going to callback
46 // If wait is true, this callback must be called to continue running listeners
47 callback: function () {
48 // Invalidate this callback incase a listener decides to call it again
51 nextListener
.apply(that
);
56 listener
= listeners
[current_event_idx
];
57 listener
[1].call(listener
[2] || that
, event_obj
, event_data
);
59 // If the listener hasn't signalled it's going to wait, proceed to next listener
60 if (!event_obj
.wait
) {
61 // Invalidate the callback just incase a listener decides to call it anyway
62 event_obj
.callback
= undefined;
73 function emitComplete() {
76 // Call the completed functions
77 (completed_fn
|| []).forEach(function (fn
) {
78 if (typeof fn
=== 'function') fn();
85 // Only accept functions
86 if (typeof fn
!== 'function') return false;
88 completed_fn
.push(fn
);
90 // If we have already completed the emits, call this now
96 callListeners
: callListeners
,
106 function PluginInterface () {
107 // Holder for all the bound listeners by this module
108 this._listeners
= {};
112 PluginInterface
.prototype.on = function (event_name
, fn
, scope
) {
113 this._listeners
[event_name
] = this._listeners
[event_name
] || [];
114 this._listeners
[event_name
].push(['on', fn
, scope
]);
119 PluginInterface
.prototype.once = function (event_name
, fn
, scope
) {
120 this._listeners
[event_name
] = this._listeners
[event_name
] || [];
121 this._listeners
[event_name
].push(['once', fn
, scope
]);
126 PluginInterface
.prototype.off = function (event_name
, fn
, scope
) {
129 if (typeof event_name
=== 'undefined') {
130 // Remove all listeners
131 this._listeners
= {};
133 } else if (typeof fn
=== 'undefined') {
134 // Remove all of 1 event type
135 delete this._listeners
[event_name
];
137 } else if (typeof scope
=== 'undefined') {
138 // Remove a single event type + callback
139 for (idx
in (this._listeners
[event_name
] || [])) {
140 if (this._listeners
[event_name
][idx
][1] === fn
) {
141 delete this._listeners
[event_name
][idx
];
145 // Remove a single event type + callback + scope
146 for (idx
in (this._listeners
[event_name
] || [])) {
147 if (this._listeners
[event_name
][idx
][1] === fn
&& this._listeners
[event_name
][idx
][2] === scope
) {
148 delete this._listeners
[event_name
][idx
];
156 // Call all the listeners for a certain event, passing them some event data that may be changed
157 PluginInterface
.prototype.emit = function (event_name
, event_data
) {
158 var emitter
= new EmitCall(event_name
, event_data
);
159 var listeners
= this._listeners
[event_name
] || [];
161 // Once emitted, remove any 'once' bound listeners
162 emitter
.done(function () {
163 listeners
.forEach(function (listener
, idx
) {
164 if (listener
[0] === 'once') {
165 listeners
[idx
] = undefined;
170 // Emit the event to the listeners and return
171 emitter
.callListeners(listeners
);
176 module
.exports
= PluginInterface
;
186 var modules = new PluginInterface();
191 modules.on('client:command', function (event, data) {
193 setTimeout(event.callback, 2000);
199 // Core code that is being extended by plugins
206 modules.emit('client:command', data).done(function () {
207 console.log('Your command is: ' + data.command);