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
) {
13 // Has event.preventDefault() been called
18 // Emit this event to an array of listeners
19 function callListeners(listeners
) {
20 var current_event_idx
= -1;
22 // Make sure we have some data to pass to the listeners
23 event_data
= event_data
|| undefined;
25 // If no bound listeners for this event, leave now
26 if (listeners
.length
=== 0) {
32 // Call the next listener in our array
33 function nextListener() {
34 var listener
, event_obj
;
36 // We want the next listener
39 // If we've ran out of listeners end this emit call
40 if (!listeners
[current_event_idx
]) {
45 // Object the listener ammends to tell us what it's going to do
47 // If changed to true, expect this listener is going to callback
50 // If wait is true, this callback must be called to continue running listeners
51 callback: function () {
52 // Invalidate this callback incase a listener decides to call it again
53 event_obj
.callback
= undefined;
55 nextListener
.apply(that
);
58 // Prevents the default 'done' functions from executing
59 preventDefault: function () {
65 listener
= listeners
[current_event_idx
];
66 listener
[1].call(listener
[2] || that
, event_obj
, event_data
);
68 // If the listener hasn't signalled it's going to wait, proceed to next listener
69 if (!event_obj
.wait
) {
70 // Invalidate the callback just incase a listener decides to call it anyway
71 event_obj
.callback
= undefined;
82 function emitComplete() {
85 var funcs
= prevented
? prevented_fn
: completed_fn
;
87 // Call the completed/prevented functions
88 (funcs
|| []).forEach(function (fn
) {
89 if (typeof fn
=== 'function') fn();
95 function addCompletedFunc(fn
) {
96 // Only accept functions
97 if (typeof fn
!== 'function') return false;
99 completed_fn
.push(fn
);
101 // If we have already completed the emits, call this now
102 if (completed
&& !prevented
) fn();
109 function addPreventedFunc(fn
) {
110 // Only accept functions
111 if (typeof fn
!== 'function') return false;
113 prevented_fn
.push(fn
);
115 // If we have already completed the emits, call this now
116 if (completed
&& prevented
) fn();
123 callListeners
: callListeners
,
124 done
: addCompletedFunc
,
125 prevented
: addPreventedFunc
134 function PluginInterface () {
135 // Holder for all the bound listeners by this module
136 this._listeners
= {};
140 PluginInterface
.prototype.on = function (event_name
, fn
, scope
) {
141 this._listeners
[event_name
] = this._listeners
[event_name
] || [];
142 this._listeners
[event_name
].push(['on', fn
, scope
]);
147 PluginInterface
.prototype.once = function (event_name
, fn
, scope
) {
148 this._listeners
[event_name
] = this._listeners
[event_name
] || [];
149 this._listeners
[event_name
].push(['once', fn
, scope
]);
154 PluginInterface
.prototype.off = function (event_name
, fn
, scope
) {
157 if (typeof event_name
=== 'undefined') {
158 // Remove all listeners
159 this._listeners
= {};
161 } else if (typeof fn
=== 'undefined') {
162 // Remove all of 1 event type
163 delete this._listeners
[event_name
];
165 } else if (typeof scope
=== 'undefined') {
166 // Remove a single event type + callback
167 for (idx
in (this._listeners
[event_name
] || [])) {
168 if (this._listeners
[event_name
][idx
][1] === fn
) {
169 delete this._listeners
[event_name
][idx
];
173 // Remove a single event type + callback + scope
174 for (idx
in (this._listeners
[event_name
] || [])) {
175 if (this._listeners
[event_name
][idx
][1] === fn
&& this._listeners
[event_name
][idx
][2] === scope
) {
176 delete this._listeners
[event_name
][idx
];
184 // Call all the listeners for a certain event, passing them some event data that may be changed
185 PluginInterface
.prototype.emit = function (event_name
, event_data
) {
186 var emitter
= new EmitCall(event_name
, event_data
);
187 var listeners
= this._listeners
[event_name
] || [];
189 // Once emitted, remove any 'once' bound listeners
190 emitter
.done(function () {
191 listeners
.forEach(function (listener
, idx
) {
192 if (listener
[0] === 'once') {
193 listeners
[idx
] = undefined;
198 // Emit the event to the listeners and return
199 emitter
.callListeners(listeners
);
204 module
.exports
= PluginInterface
;
214 var modules = new PluginInterface();
219 modules.on('client:command', function (event, data) {
221 setTimeout(event.callback, 2000);
227 // Core code that is being extended by plugins
234 modules.emit('client:command', data).done(function () {
235 console.log('Your command is: ' + data.command);