@irrelon/emitter 6.0.1 → 6.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/Emitter.js ADDED
@@ -0,0 +1,600 @@
1
+ export var ListenerReturnFlag;
2
+ (function (ListenerReturnFlag) {
3
+ ListenerReturnFlag["none"] = "!+_NONE";
4
+ ListenerReturnFlag["cancel"] = "!+_CANCEL";
5
+ })(ListenerReturnFlag || (ListenerReturnFlag = {}));
6
+ /**
7
+ * Creates a new class with the ability to emit events.
8
+ */
9
+ export class Emitter {
10
+ constructor(dispatchPrefix, shouldDispatchWindowEvents = false) {
11
+ this._eventsEmitting = false;
12
+ this._eventRemovalQueue = [];
13
+ this._eventListeners = {};
14
+ this._eventStaticEmitters = {};
15
+ this._eventsAllowDefer = false;
16
+ this._eventsDeferTimeouts = {};
17
+ this._dispatchWindowEventsEnabled = false;
18
+ this._dispatchPrefix = dispatchPrefix;
19
+ this._dispatchWindowEventsEnabled = shouldDispatchWindowEvents;
20
+ }
21
+ dispatchWindowEventsEnabled(shouldDispatchWindowEvents) {
22
+ this._dispatchWindowEventsEnabled = shouldDispatchWindowEvents;
23
+ }
24
+ /**
25
+ * Attach an event listener to the passed event only if the passed
26
+ * id matches the id for the event being fired.
27
+ * @param eventName The name of the event to listen for.
28
+ * @param id The id to match against.
29
+ * @param listener The method to call when the event is fired.
30
+ * @returns The emitter instance.
31
+ */
32
+ _on(eventName, id, listener) {
33
+ const generateTimeout = (emitter) => {
34
+ setTimeout(() => {
35
+ listener(...emitter.args);
36
+ }, 1);
37
+ };
38
+ this._eventListeners = this._eventListeners || {};
39
+ const nonNullableEventListeners = (this._eventListeners[eventName] = this._eventListeners[eventName] || {});
40
+ nonNullableEventListeners[id] = nonNullableEventListeners[id] || [];
41
+ nonNullableEventListeners[id].push(listener);
42
+ // Check for any static emitters, and fire the event if any exist
43
+ if (!this._eventStaticEmitters || !this._eventStaticEmitters[eventName] || !this._eventStaticEmitters[eventName].length)
44
+ return this;
45
+ // Emit events for each emitter
46
+ for (let i = 0; i < this._eventStaticEmitters[eventName].length; i++) {
47
+ const emitter = this._eventStaticEmitters[eventName][i];
48
+ if (id === "*" || emitter.id === id) {
49
+ // Call the listener out of process so that any code that expects a listener
50
+ // to be called at some point in the future rather than immediately on registration
51
+ // will not fail
52
+ generateTimeout(emitter);
53
+ }
54
+ }
55
+ return this;
56
+ }
57
+ /**
58
+ * Attach an event listener to the passed event only if the passed
59
+ * id matches the document id for the event being fired.
60
+ * @param eventName The name of the event to listen for.
61
+ * @param id The id to match against.
62
+ * @param listener The method to call when the event is fired.
63
+ * @returns The emitter instance.
64
+ */
65
+ _once(eventName, id, listener) {
66
+ let fired = false;
67
+ let originalReturnData;
68
+ const internalCallback = (...args) => {
69
+ if (fired)
70
+ return originalReturnData;
71
+ fired = true;
72
+ this.off(eventName, id, internalCallback);
73
+ originalReturnData = listener(...args);
74
+ return originalReturnData;
75
+ };
76
+ return this.on(eventName, id, internalCallback);
77
+ }
78
+ /**
79
+ * Cancels an event listener based on an event name, id and listener function.
80
+ * @param eventName The event to cancel listener for.
81
+ * @param id The ID of the event to cancel listening for.
82
+ * @param listener The event listener function used in the on()
83
+ * or once() call to cancel.
84
+ * @returns The emitter instance.
85
+ */
86
+ _off(eventName, id, listener) {
87
+ // If the event name doesn't have any listeners, exit early
88
+ if (!this._eventListeners || !this._eventListeners[eventName] || !this._eventListeners[eventName][id])
89
+ return this;
90
+ // If we are emitting events at the moment, don't remove this listener
91
+ // until the process has completed, so we queue for removal instead
92
+ if (this._eventsEmitting) {
93
+ this._eventRemovalQueue = this._eventRemovalQueue || [];
94
+ this._eventRemovalQueue.push(() => {
95
+ this.off(eventName, id, listener);
96
+ });
97
+ return this;
98
+ }
99
+ // Check if we have no specific listener... in this case
100
+ // we want to remove all listeners for an id
101
+ if (!listener) {
102
+ if (id === "*") {
103
+ // The id is "all" and no listener was provided so delete all
104
+ // event listeners for this event name
105
+ delete this._eventListeners[eventName];
106
+ return this;
107
+ }
108
+ // No listener provided, delete all listeners for this id
109
+ delete this._eventListeners[eventName][id];
110
+ return this;
111
+ }
112
+ const arr = this._eventListeners[eventName][id] || [];
113
+ const index = arr.indexOf(listener);
114
+ if (index > -1) {
115
+ arr.splice(index, 1);
116
+ }
117
+ return this;
118
+ }
119
+ /**
120
+ * Creates an event listener that listens for any and all events
121
+ * emitted.
122
+ */
123
+ onAny(listener) {
124
+ this.on("*", listener);
125
+ }
126
+ on(eventName, idOrListener, listener) {
127
+ if (typeof idOrListener === "string") {
128
+ return this._on(eventName, idOrListener, listener);
129
+ }
130
+ return this._on(eventName, "*", idOrListener);
131
+ }
132
+ once(eventName, ...rest) {
133
+ const restTypes = rest.map((arg) => typeof arg);
134
+ if (restTypes[0] === "function") {
135
+ return this._once(eventName, "*", rest[0]);
136
+ }
137
+ return this._once(eventName, rest[0], rest[1]);
138
+ }
139
+ overwrite(eventName, ...rest) {
140
+ const restTypes = rest.map((arg) => typeof arg);
141
+ if (restTypes[0] === "function") {
142
+ this.off(eventName);
143
+ return this._on(eventName, "*", rest[0]);
144
+ }
145
+ this.off(eventName, rest[0]);
146
+ return this._on(eventName, rest[0], rest[1]);
147
+ }
148
+ /**
149
+ * Removes an event listener that listens for any and all events
150
+ * emitted.
151
+ */
152
+ offAny(listener) {
153
+ this.off("*", listener);
154
+ }
155
+ off(eventName, ...rest) {
156
+ if (rest.length === 0) {
157
+ // Only event was provided, use * as the id to mean "any without"
158
+ // a specific id
159
+ return this._off(eventName, "*");
160
+ }
161
+ const restTypes = rest.map((arg) => typeof arg);
162
+ if (restTypes[0] === "function") {
163
+ // The first arg after the event name was a function (listener)
164
+ // so remove listening for events for this specific listener
165
+ return this._off(eventName, "*", rest[0]);
166
+ }
167
+ // Both id and listener were provided, remove for the specific id
168
+ return this._off(eventName, rest[0], rest[1]);
169
+ }
170
+ _emitToSingleListener(listener, data) {
171
+ return listener(...data);
172
+ }
173
+ _emitToArrayOfListeners(arr, data) {
174
+ const arrCount = arr.length;
175
+ const resultArr = [];
176
+ for (let arrIndex = 0; arrIndex < arrCount; arrIndex++) {
177
+ // Check we have a function to execute
178
+ const tmpFunc = arr[arrIndex];
179
+ if (typeof tmpFunc !== "function") {
180
+ continue;
181
+ }
182
+ const eventListenerResponse = tmpFunc(...data);
183
+ resultArr.push(eventListenerResponse);
184
+ if (eventListenerResponse === ListenerReturnFlag.cancel) {
185
+ // Cancel further event processing
186
+ break;
187
+ }
188
+ }
189
+ return resultArr;
190
+ }
191
+ /**
192
+ * Dispatches an event originating in our emitter to the browser's
193
+ * window object.
194
+ * @param eventName The name of the event to emit. This gets prefixed with the
195
+ * dispatch prefix if one is set.
196
+ * @param data
197
+ */
198
+ _emitToWindowDispatch(eventName, data) {
199
+ if (typeof window === "undefined")
200
+ return;
201
+ if (!this._dispatchWindowEventsEnabled) {
202
+ return;
203
+ }
204
+ const finalEventName = (this._dispatchPrefix ? `${this._dispatchPrefix}.${eventName}` : eventName);
205
+ window.dispatchEvent(new CustomEvent(finalEventName, { detail: data }));
206
+ }
207
+ /**
208
+ * Call an event listener by name. The `rpc()` function differs from `emit()` in
209
+ * that it will only call and return data from the first event listener for the
210
+ * event rather than all event listeners. If you have more than one event listener
211
+ * assigned to the event, all others except the first will be ignored and will
212
+ * not receive the event.
213
+ * @param eventName The name of the event to call the listener for.
214
+ * @param {...any} data The arguments to send to the listening method.
215
+ * If you are sending multiple arguments, separate them with a comma so
216
+ * that they are received by the function as separate arguments.
217
+ * @return {number}
218
+ * @example #Call the Event Listener
219
+ * // Emit the event named "hello"
220
+ * myEntity.emit('hello');
221
+ * @example #Call the Event Listener With Data Object
222
+ * // Emit the event named "hello"
223
+ * myEntity.emit('hello', {moo: true});
224
+ * @example #Call the Event Listener With Multiple Data Values
225
+ * // Emit the event named "hello"
226
+ * myEntity.emit('hello', {moo: true}, 'someString');
227
+ * @example #Register the Listener for Event Data
228
+ * // Set a listener to listen for the data (multiple values emitted
229
+ * // from an event are passed as function arguments)
230
+ * myEntity.on('hello', function (arg1, arg2) {
231
+ * console.log("Arguments:", arg1, arg2);
232
+ * return "foo";
233
+ * }
234
+ *
235
+ * // Emit the event named "hello"
236
+ * const result = myEntity.emit('hello', 'data1', 'data2');
237
+ * console.log("Result:", result);
238
+ *
239
+ * // The console output is:
240
+ * // Arguments: data1 data2
241
+ * // Result: "foo"
242
+ */
243
+ rpc(eventName, ...data) {
244
+ return this.rpcId(eventName, "*", ...data);
245
+ }
246
+ rpcId(eventName, id, ...data) {
247
+ if (!this._eventListeners || !this._eventListeners[eventName]) {
248
+ throw new Error("Cannot make an rpc call without at least one event listener and none were found");
249
+ }
250
+ let emitterResult;
251
+ this._eventsEmitting = true;
252
+ if (this._eventListeners[eventName][id]) {
253
+ // Handle id emit
254
+ const arr = this._eventListeners[eventName][id];
255
+ emitterResult = this._emitToSingleListener(arr[0], data);
256
+ }
257
+ else if (id !== "*" && this._eventListeners[eventName]["*"]) {
258
+ // Handle wildcard emit if the id passed wasn't already a wildcard (*) id
259
+ const arr = this._eventListeners[eventName]["*"];
260
+ emitterResult = this._emitToSingleListener(arr[0], data);
261
+ }
262
+ else {
263
+ if (id === "*") {
264
+ throw new Error(`Cannot make an rpc call to event "${eventName}" without at least one event listener and none were found, register a listener via on("${eventName}", () => { ...some listener code })`);
265
+ }
266
+ throw new Error(`Cannot make an rpc call to event "${eventName}" and id "${id}" without at least one event listener and none were found, register a listener via on("${eventName}", "${id}", () => { ...some listener code })`);
267
+ }
268
+ this._eventsEmitting = false;
269
+ this._processRemovalQueue();
270
+ return emitterResult;
271
+ }
272
+ /**
273
+ * Emit an event by name.
274
+ * @param eventName The name of the event to emit.
275
+ * @param {...any} data The arguments to send to any listening methods.
276
+ * If you are sending multiple arguments, separate them with a comma so
277
+ * that they are received by the function as separate arguments.
278
+ * @return {any[]} An array of all return values from all the listeners for the event.
279
+ * @example #Emit an Event
280
+ * // Emit the event named "hello"
281
+ * myEntity.emit('hello');
282
+ * @example #Emit an Event With Data Object
283
+ * // Emit the event named "hello"
284
+ * myEntity.emit('hello', {moo: true});
285
+ * @example #Emit an Event With Multiple Data Values
286
+ * // Emit the event named "hello"
287
+ * myEntity.emit('hello', {moo: true}, 'someString');
288
+ * @example #Listen for Event Data
289
+ * // Set a listener to listen for the data (multiple values emitted
290
+ * // from an event are passed as function arguments)
291
+ * myEntity.on('hello', function (arg1, arg2) {
292
+ * console.log("Arguments:", arg1, arg2);
293
+ * return "foo";
294
+ * }
295
+ *
296
+ * // Emit the event named "hello"
297
+ * // The result is returned as an array of all return values
298
+ * // from all the listeners for the event
299
+ * const result = myEntity.emit('hello', 'data1', 'data2');
300
+ * console.log("Result:", result);
301
+ *
302
+ * // The console output is:
303
+ * // Arguments: data1 data2
304
+ * // Result: ["foo"]
305
+ */
306
+ emit(eventName, ...data) {
307
+ this._emitToWindowDispatch(eventName, data);
308
+ return this.emitId(eventName, "*", ...data);
309
+ }
310
+ /**
311
+ * Emits an event by name and id.
312
+ * @param eventName The name of the event to emit.
313
+ * @param id The id of the event to emit.
314
+ * @param {...any} data The arguments to send to any listening methods.
315
+ * If you are sending multiple arguments, separate them with a comma so
316
+ * that they are received by the function as separate arguments.
317
+ * @return {any[]} An array of all return values from all the listeners for the event.
318
+ */
319
+ emitId(eventName, id, ...data) {
320
+ if (!this._eventListeners || (!this._eventListeners[eventName] && !this._eventListeners["*"])) {
321
+ return [];
322
+ }
323
+ let emitterResult = [];
324
+ this._eventsEmitting = true;
325
+ if (this._eventListeners[eventName]) {
326
+ // Handle id emit
327
+ if (this._eventListeners[eventName][id]) {
328
+ const arr = this._eventListeners[eventName][id];
329
+ emitterResult = emitterResult.concat(this._emitToArrayOfListeners(arr, data));
330
+ }
331
+ // Handle id wildcard emit if the id passed wasn't already a wildcard (*) id
332
+ if (id !== "*" && this._eventListeners[eventName]["*"]) {
333
+ const arr = this._eventListeners[eventName]["*"];
334
+ emitterResult = emitterResult.concat(this._emitToArrayOfListeners(arr, data));
335
+ }
336
+ }
337
+ if (this._eventListeners["*"]) {
338
+ const arr = this._eventListeners["*"]["*"];
339
+ emitterResult = emitterResult.concat(this._emitToArrayOfListeners(arr, [eventName, ...data]));
340
+ }
341
+ this._eventsEmitting = false;
342
+ this._processRemovalQueue();
343
+ return emitterResult;
344
+ }
345
+ /**
346
+ * Creates a persistent event. Once emitStatic() has been called, a
347
+ * persistent event is registered. Any existing event listeners will
348
+ * be called just like when you call emit(), however, any new
349
+ * listeners that are registered for this event via on() will also be
350
+ * called as soon as they are added.
351
+ * @param eventName The name of the event to emit.
352
+ * @param {...any} data Optional arguments to emit with the event.
353
+ * @returns The emitter instance.
354
+ * @private
355
+ */
356
+ emitStatic(eventName, ...data) {
357
+ const id = "*";
358
+ this._eventListeners = this._eventListeners || {};
359
+ this._eventsEmitting = true;
360
+ if (this._eventListeners[eventName] && this._eventListeners[eventName][id]) {
361
+ // Handle id wildcard emit
362
+ const arr = this._eventListeners[eventName][id];
363
+ const arrCount = arr.length;
364
+ for (let arrIndex = 0; arrIndex < arrCount; arrIndex++) {
365
+ // Check we have a function to execute
366
+ const tmpFunc = arr[arrIndex];
367
+ if (typeof tmpFunc === "function") {
368
+ tmpFunc.call(this, ...data);
369
+ }
370
+ }
371
+ }
372
+ this._eventsEmitting = false;
373
+ this._eventStaticEmitters = this._eventStaticEmitters || {};
374
+ this._eventStaticEmitters[eventName] = this._eventStaticEmitters[eventName] || [];
375
+ this._eventStaticEmitters[eventName].push({
376
+ id: "*",
377
+ args: data
378
+ });
379
+ this._processRemovalQueue();
380
+ return this;
381
+ }
382
+ /**
383
+ * Creates a persistent emitter record that will fire a listener if
384
+ * one is added for this event after the emitStatic() call has been
385
+ * made.
386
+ * @param eventName The name of the event to emit.
387
+ * @param id The id of the event to emit.
388
+ * @param {...any} data Optional arguments to emit with the event.
389
+ * @returns The emitter instance.
390
+ * @private
391
+ */
392
+ emitStaticId(eventName, id, ...data) {
393
+ if (!id)
394
+ throw new Error("Missing id from emitId call!");
395
+ this._eventListeners = this._eventListeners || {};
396
+ this._eventsEmitting = true;
397
+ if (this._eventListeners[eventName]) {
398
+ // Handle id emit
399
+ if (this._eventListeners[eventName][id]) {
400
+ const arr = this._eventListeners[eventName][id];
401
+ const arrCount = arr.length;
402
+ for (let arrIndex = 0; arrIndex < arrCount; arrIndex++) {
403
+ // Check we have a function to execute
404
+ const tmpFunc = arr[arrIndex];
405
+ if (typeof tmpFunc === "function") {
406
+ tmpFunc.call(this, ...data);
407
+ }
408
+ }
409
+ }
410
+ // Handle wildcard emit
411
+ if (this._eventListeners[eventName]["*"]) {
412
+ const arr = this._eventListeners[eventName]["*"];
413
+ const arrCount = arr.length;
414
+ for (let arrIndex = 0; arrIndex < arrCount; arrIndex++) {
415
+ // Check we have a function to execute
416
+ const tmpFunc = arr[arrIndex];
417
+ if (typeof tmpFunc === "function") {
418
+ tmpFunc.call(this, ...data);
419
+ }
420
+ }
421
+ }
422
+ }
423
+ this._eventsEmitting = false;
424
+ this._eventStaticEmitters = this._eventStaticEmitters || {};
425
+ this._eventStaticEmitters[eventName] = this._eventStaticEmitters[eventName] || [];
426
+ this._eventStaticEmitters[eventName].push({
427
+ id,
428
+ args: data
429
+ });
430
+ this._processRemovalQueue();
431
+ return this;
432
+ }
433
+ /**
434
+ * Handles removing emitters, is an internal method not called directly.
435
+ * @param eventName The event to remove static emitter for.
436
+ * @returns The emitter instance.
437
+ * @private
438
+ */
439
+ cancelStatic(eventName) {
440
+ this._eventStaticEmitters = this._eventStaticEmitters || {};
441
+ this._eventStaticEmitters[eventName] = [];
442
+ return this;
443
+ }
444
+ /**
445
+ * Checks if an event has any event listeners or not.
446
+ * @param eventName The name of the event to check for.
447
+ * @returns True if one or more event listeners are registered for
448
+ * the event. False if none are found.
449
+ */
450
+ willEmit(eventName) {
451
+ const id = "*";
452
+ if (!this._eventListeners || !this._eventListeners[eventName]) {
453
+ return false;
454
+ }
455
+ const arr = this._eventListeners[eventName][id];
456
+ const arrCount = arr.length;
457
+ for (let arrIndex = 0; arrIndex < arrCount; arrIndex++) {
458
+ // Check we have a function to execute
459
+ const tmpFunc = arr[arrIndex];
460
+ if (typeof tmpFunc === "function") {
461
+ return true;
462
+ }
463
+ }
464
+ return false;
465
+ }
466
+ /**
467
+ * Checks if an event has any event listeners or not based on the passed id.
468
+ * @param eventName The name of the event to check for.
469
+ * @param id The event ID to check for.
470
+ * @returns True if one or more event listeners are registered for
471
+ * the event. False if none are found.
472
+ */
473
+ willEmitId(eventName, id) {
474
+ if (!this._eventListeners || !this._eventListeners[eventName]) {
475
+ return false;
476
+ }
477
+ // Handle id emit
478
+ if (this._eventListeners[eventName][id]) {
479
+ const arr = this._eventListeners[eventName][id];
480
+ const arrCount = arr.length;
481
+ for (let arrIndex = 0; arrIndex < arrCount; arrIndex++) {
482
+ // Check we have a function to execute
483
+ const tmpFunc = arr[arrIndex];
484
+ if (typeof tmpFunc === "function") {
485
+ return true;
486
+ }
487
+ }
488
+ }
489
+ // Handle wildcard emit
490
+ if (this._eventListeners[eventName]["*"]) {
491
+ const arr = this._eventListeners[eventName]["*"];
492
+ const arrCount = arr.length;
493
+ for (let arrIndex = 0; arrIndex < arrCount; arrIndex++) {
494
+ // Check we have a function to execute
495
+ const tmpFunc = arr[arrIndex];
496
+ if (typeof tmpFunc === "function") {
497
+ return true;
498
+ }
499
+ }
500
+ }
501
+ return false;
502
+ }
503
+ /**
504
+ * Queues an event to be fired. This has automatic de-bouncing so that any
505
+ * events of the same type that occur within 100 milliseconds of a previous
506
+ * one will all be wrapped into a single emit rather than emitting tons of
507
+ * events for lots of chained inserts etc. Only the data from the last
508
+ * de-bounced event will be emitted.
509
+ * @param eventName The name of the event to emit.
510
+ * @param {...any} data Optional arguments to emit with the event.
511
+ * @returns The emitter instance.
512
+ */
513
+ deferEmit(eventName, ...data) {
514
+ if (!this._eventsAllowDefer) {
515
+ // Check for an existing timeout
516
+ this._eventsDeferTimeouts = this._eventsDeferTimeouts || {};
517
+ if (this._eventsDeferTimeouts[eventName]) {
518
+ clearTimeout(this._eventsDeferTimeouts[eventName]);
519
+ }
520
+ // Set a timeout
521
+ this._eventsDeferTimeouts[eventName] = setTimeout(() => {
522
+ void this.emit.call(this, eventName, ...data);
523
+ }, 1);
524
+ }
525
+ else {
526
+ void this.emit.call(this, eventName, ...data);
527
+ }
528
+ return this;
529
+ }
530
+ /**
531
+ * Returns true if the result from an emit() call passed as the first
532
+ * argument contains a cancellation flag.
533
+ * @param resultArr
534
+ */
535
+ didCancel(resultArr) {
536
+ return resultArr.findIndex((result) => result === ListenerReturnFlag.cancel) > -1;
537
+ }
538
+ /**
539
+ * If events are cleared with the off() method while the event emitter is
540
+ * actively processing any events then the off() calls get added to a
541
+ * queue to be executed after the event emitter is finished. This stops
542
+ * errors that might occur by potentially mutating the event listener array
543
+ * while the emitter is running through them. This method is called after
544
+ * the event emitter is finished processing.
545
+ * @private
546
+ */
547
+ _processRemovalQueue() {
548
+ if (!this._eventRemovalQueue || !this._eventRemovalQueue.length) {
549
+ return;
550
+ }
551
+ // Execute each removal call
552
+ for (let i = 0; i < this._eventRemovalQueue.length; i++) {
553
+ this._eventRemovalQueue[i]();
554
+ }
555
+ // Clear the removal queue
556
+ this._eventRemovalQueue = [];
557
+ }
558
+ }
559
+ export function makeEmitter(obj, prototypeMode) {
560
+ let operateOnObject;
561
+ if (obj === undefined && prototypeMode === undefined) {
562
+ obj = {};
563
+ prototypeMode = false;
564
+ }
565
+ if (typeof obj === "boolean" && prototypeMode === undefined) {
566
+ prototypeMode = obj;
567
+ obj = {};
568
+ }
569
+ if (prototypeMode === undefined) {
570
+ prototypeMode = true;
571
+ }
572
+ if (typeof obj !== "object" && typeof obj !== "function") {
573
+ throw new Error("Cannot operate on a non-object / non-function passed as first argument!");
574
+ }
575
+ if (prototypeMode) {
576
+ if (obj.prototype === undefined) {
577
+ throw new Error("Cannot modify prototype of passed object, it has no prototype property! Was it instantiated with the new operator correctly?");
578
+ }
579
+ operateOnObject = obj.prototype;
580
+ }
581
+ else {
582
+ operateOnObject = obj;
583
+ }
584
+ // Convert the object prototype to have eventing capability
585
+ operateOnObject.on = Emitter.prototype.on;
586
+ operateOnObject.onAny = Emitter.prototype.onAny;
587
+ operateOnObject.off = Emitter.prototype.off;
588
+ operateOnObject.offAny = Emitter.prototype.offAny;
589
+ operateOnObject.once = Emitter.prototype.once;
590
+ operateOnObject.emit = Emitter.prototype.emit;
591
+ operateOnObject.emitId = Emitter.prototype.emitId;
592
+ operateOnObject.emitStatic = Emitter.prototype.emitStatic;
593
+ operateOnObject.emitStaticId = Emitter.prototype.emitStaticId;
594
+ operateOnObject.cancelStatic = Emitter.prototype.cancelStatic;
595
+ operateOnObject.deferEmit = Emitter.prototype.deferEmit;
596
+ operateOnObject.willEmit = Emitter.prototype.willEmit;
597
+ operateOnObject.willEmitId = Emitter.prototype.willEmitId;
598
+ operateOnObject._processRemovalQueue = Emitter.prototype._processRemovalQueue;
599
+ return obj;
600
+ }