@irrelon/emitter 6.1.0 → 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.
@@ -26,857 +26,608 @@
26
26
 
27
27
  <section>
28
28
  <article>
29
- <pre class="prettyprint source linenums"><code>/*
30
- The MIT License (MIT)
31
-
32
- Copyright (c) 2014 Irrelon Software Limited
33
- http://www.irrelon.com
34
-
35
- Permission is hereby granted, free of charge, to any person obtaining a copy
36
- of this software and associated documentation files (the "Software"), to deal
37
- in the Software without restriction, including without limitation the rights
38
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
39
- copies of the Software, and to permit persons to whom the Software is
40
- furnished to do so, subject to the following conditions:
41
-
42
- The above copyright notice, url and this permission notice shall be included in
43
- all copies or substantial portions of the Software.
44
-
45
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
46
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
47
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
48
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
49
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
50
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
51
- THE SOFTWARE.
52
-
53
- Source: https://github.com/irrelon/emitter
54
-
55
- Changelog:
56
- Version 2.0.11:
57
- Added cancelStatic method to allow cancelling a static event
58
- Version 2.0.7:
59
- Fixed UMD module support
60
- Version 2.0.6:
61
- Added UMD module support
62
- Version 2.0.5:
63
- Added bower version number
64
- Version 2.0.4:
65
- Allow instantiation as independent instance, updated unit tests
66
- Version 2.0.3:
67
- Documentation updates, published to bower
68
- Version 2.0.2:
69
- Documentation updates
70
- Version 2.0.1:
71
- Bug fix in this._emitters usage
72
- Version 2.0.0:
73
- Big update to bring in line with latest developments in other projects. Event emitter can
74
- now use deferEmit(), emitId(), emitStatic(), emitStaticId(), willEmit(), willEmitId().
75
- Version 1.1.9:
76
- Updated changelog correctly
77
- Version 1.1.8:
78
- Removed tons of dependencies wrongly included in main dependencies, have moved to devDependencies section of package.json
79
- Version 1.1.0:
80
- Added support for overloaded methods
81
- Added support for events with ids
82
- Version 1.0.2:
83
- Removed AMD support, added browserify support
84
- Added package.json
85
- Added once() method
86
- Added hasListener() method
87
- Published to NPM as irrelon-emitter
88
- Version 1.0.1:
89
- Added ability to extend any object with eventing capability
90
- Added AMD / Require.js support
91
- Added Node.js support
92
- Version 1.0.0:
93
- First commit
94
- */
95
- "use strict";
96
-
97
- var Overload = require('irrelon-overload');
98
-
99
- var EventMethods = {
100
- on: new Overload({
101
- /**
102
- * Attach an event listener to the passed event.
103
- * @memberof Emitter
104
- * @method on
105
- * @param {String} event The name of the event to listen for.
106
- * @param {Function} listener The method to call when the event is fired.
107
- */
108
- 'string, function': function (event, listener) {
109
- return this.$main(event, '*', listener);
110
- },
111
-
112
- /**
113
- * Attach an event listener to the passed event only if the passed
114
- * id matches the document id for the event being fired.
115
- * @memberof Emitter
116
- * @method on
117
- * @param {String} event The name of the event to listen for.
118
- * @param {*} id The document id to match against.
119
- * @param {Function} listener The method to call when the event is fired.
120
- */
121
- 'string, *, function': function (event, id, listener) {
122
- return this.$main(event, id, listener);
123
- },
124
-
125
- /**
126
- * @param event
127
- * @param id
128
- * @param listener
129
- * @return {$main}
130
- * @private
131
- */
132
- '$main': function (event, id, listener) {
133
- var self = this,
134
- generateTimeout,
135
- emitter,
136
- i;
137
-
138
- generateTimeout = function (emitter) {
139
- setTimeout(function () {
140
- listener.apply(self, emitter.args);
141
- }, 1);
142
- };
143
-
144
- this._listeners = this._listeners || {};
145
- this._listeners[event] = this._listeners[event] || {};
146
- this._listeners[event][id] = this._listeners[event][id] || [];
147
- this._listeners[event][id].push(listener);
148
-
149
- // Check for any static emitters, and fire the event if any exist
150
- if (this._emitters &amp;&amp; this._emitters[event] &amp;&amp; this._emitters[event].length) {
151
- // Emit events for each emitter
152
- for (i = 0; i &lt; this._emitters[event].length; i++) {
153
- emitter = this._emitters[event];
154
-
155
- if (id === '*' || emitter.id === id) {
156
- // Call the listener out of process so that any code that expects a listener
157
- // to be called at some point in the future rather than immediately on registration
158
- // will not fail
159
- generateTimeout(emitter);
160
- }
161
- }
162
- }
163
-
164
- return this;
165
- }
166
- }),
167
-
168
- once: new Overload({
169
- /**
170
- * Attach an event listener to the passed event which will only fire once.
171
- * @memberof Emitter
172
- * @method once
173
- * @param {String} event The name of the event to listen for.
174
- * @param {Function} listener The method to call when the event is fired.
175
- */
176
- 'string, function': function (event, listener) {
177
- var self = this,
178
- fired = false,
179
- internalCallback = function () {
180
- if (!fired) {
181
- fired = true;
182
- self.off(event, internalCallback);
183
- listener.apply(self, arguments);
184
- }
185
- };
186
-
187
- return this.on(event, internalCallback);
188
- },
189
-
190
- /**
191
- * Attach an event listener to the passed event only if the passed
192
- * id matches the document id for the event being fired.
193
- * @memberof Emitter
194
- * @method once
195
- * @param {String} event The name of the event to listen for.
196
- * @param {*} id The document id to match against.
197
- * @param {Function} listener The method to call when the event is fired.
198
- */
199
- 'string, *, function': function (event, id, listener) {
200
- var self = this,
201
- fired = false,
202
- internalCallback = function () {
203
- if (!fired) {
204
- fired = true;
205
- self.off(event, id, internalCallback);
206
- listener.apply(self, arguments);
207
- }
208
- };
209
-
210
- return this.on(event, id, internalCallback);
211
- }
212
- }),
213
-
214
- off: new Overload({
215
- /**
216
- * Cancels all event listeners for the passed event.
217
- * @memberof Emitter
218
- * @method off
219
- * @param {String} event The name of the event.
220
- * @returns {*}
221
- */
222
- 'string': function (event) {
223
- var self = this;
224
-
225
- if (this._emitting) {
226
- this._eventRemovalQueue = this._eventRemovalQueue || [];
227
- this._eventRemovalQueue.push(function () {
228
- self.off(event);
229
- });
230
- } else {
231
- if (this._listeners &amp;&amp; this._listeners[event]) {
232
- delete this._listeners[event];
233
- }
234
- }
235
-
236
- return this;
237
- },
238
-
239
- /**
240
- * Cancels the event listener for the passed event and listener function.
241
- * @memberof Emitter
242
- * @method off
243
- * @param {String} event The event to cancel listener for.
244
- * @param {Function} listener The event listener function used in the on()
245
- * or once() call to cancel.
246
- * @returns {*}
247
- */
248
- 'string, function': function (event, listener) {
249
- var self = this,
250
- arr,
251
- index;
252
-
253
- if (this._emitting) {
254
- this._eventRemovalQueue = this._eventRemovalQueue || [];
255
- this._eventRemovalQueue.push(function () {
256
- self.off(event, listener);
257
- });
258
- } else {
259
- if (typeof(listener) === 'string') {
260
- if (this._listeners &amp;&amp; this._listeners[event] &amp;&amp; this._listeners[event][listener]) {
261
- delete this._listeners[event][listener];
262
- }
263
- } else {
264
- if (this._listeners &amp;&amp; this._listeners[event]) {
265
- arr = this._listeners[event]['*'];
266
- index = arr.indexOf(listener);
267
-
268
- if (index > -1) {
269
- arr.splice(index, 1);
270
- }
271
- }
272
- }
273
- }
274
-
275
- return this;
276
- },
277
-
278
- /**
279
- * Cancels an event listener based on an event name, id and listener function.
280
- * @memberof Emitter
281
- * @method off
282
- * @param {String} event The event to cancel listener for.
283
- * @param {String} id The ID of the event to cancel listening for.
284
- * @param {Function} listener The event listener function used in the on()
285
- * or once() call to cancel.
286
- */
287
- 'string, *, function': function (event, id, listener) {
288
- var self = this;
289
-
290
- if (this._emitting) {
291
- this._eventRemovalQueue = this._eventRemovalQueue || [];
292
- this._eventRemovalQueue.push(function () {
293
- self.off(event, id, listener);
294
- });
295
- } else {
296
- if (this._listeners &amp;&amp; this._listeners[event] &amp;&amp; this._listeners[event][id]) {
297
- var arr = this._listeners[event][id],
298
- index = arr.indexOf(listener);
299
-
300
- if (index > -1) {
301
- arr.splice(index, 1);
302
- }
303
- }
304
- }
305
- },
306
-
307
- /**
308
- * Cancels all listeners for an event based on the passed event name and id.
309
- * @memberof Emitter
310
- * @method off
311
- * @param {String} event The event name to cancel listeners for.
312
- * @param {*} id The ID to cancel all listeners for.
313
- */
314
- 'string, *': function (event, id) {
315
- var self = this;
316
-
317
- if (this._emitting) {
318
- this._eventRemovalQueue = this._eventRemovalQueue || [];
319
- this._eventRemovalQueue.push(function () {
320
- self.off(event, id);
321
- });
322
- } else {
323
- if (this._listeners &amp;&amp; this._listeners[event] &amp;&amp; this._listeners[event][id]) {
324
- // Kill all listeners for this event id
325
- delete this._listeners[event][id];
326
- }
327
- }
328
- }
329
- }),
330
-
331
- emit: new Overload({
332
- /**
333
- * Emit an event.
334
- * @memberof Emitter
335
- * @method emit
336
- * @param {String} event The event to emit.
337
- * @returns {*}
338
- */
339
- 'string': function (event) {
340
- // Fire global listeners
341
- return this.$main(event);
342
- },
343
-
344
- /**
345
- * Emit an event with data.
346
- * @memberof Emitter
347
- * @method emit
348
- * @param {String} event The event to emit.
349
- * @param {*} data Data to emit with the event.
350
- * @returns {*}
351
- */
352
- 'string, ...': function (event, data) {
353
- // Fire global listeners first
354
- this.$main.apply(this, arguments);
355
-
356
- return this;
357
- },
358
-
359
- /**
360
- * Handles emitting events, is an internal method not called directly.
361
- * @param {String} event The name of the event to emit.
362
- * @param {*} data The data to emit with the event.
363
- * @returns {*}
364
- * @private
365
- */
366
- '$main': function (event, data) {
367
- var id = '*';
368
- this._listeners = this._listeners || {};
369
- this._emitting = true;
370
-
371
- if (this._listeners[event]) {
372
- var arrIndex,
373
- arrCount,
374
- tmpFunc,
375
- arr;
376
-
377
- // Handle global emit
378
- if (this._listeners[event][id]) {
379
- arr = this._listeners[event][id];
380
- arrCount = arr.length;
381
-
382
- for (arrIndex = 0; arrIndex &lt; arrCount; arrIndex++) {
383
- // Check we have a function to execute
384
- tmpFunc = arr[arrIndex];
385
-
386
- if (typeof tmpFunc === 'function') {
387
- tmpFunc.apply(this, Array.prototype.slice.call(arguments, 1));
388
- }
389
- }
390
- }
391
- }
392
-
393
- this._emitting = false;
394
- this._processRemovalQueue();
395
-
396
- return this;
397
- }
398
- }),
399
-
400
- emitId: new Overload({
401
- 'string': function (event) {
402
- throw('Missing id from emitId call!');
403
- },
404
-
405
- 'string, *': function (event, id) {
406
- return this.$main(event, id);
407
- },
408
-
409
- 'string, *, ...': function (event, id) {
410
- // Fire global listeners first
411
- this.$main.apply(this, arguments);
412
-
413
- return this;
414
- },
415
-
416
- '$main': function (event, id, data) {
417
- this._listeners = this._listeners || {};
418
- this._emitting = true;
419
-
420
- if (this._listeners[event]) {
421
- var arrIndex,
422
- arrCount,
423
- tmpFunc,
424
- arr;
425
-
426
- // Handle global emit
427
- if (this._listeners[event]['*']) {
428
- arr = this._listeners[event]['*'];
429
- arrCount = arr.length;
430
-
431
- for (arrIndex = 0; arrIndex &lt; arrCount; arrIndex++) {
432
- // Check we have a function to execute
433
- tmpFunc = arr[arrIndex];
434
-
435
- if (typeof tmpFunc === 'function') {
436
- tmpFunc.apply(this, Array.prototype.slice.call(arguments, 2));
437
- }
438
- }
439
- }
440
-
441
- // Handle id emit
442
- if (this._listeners[event][id]) {
443
- arr = this._listeners[event][id];
444
- arrCount = arr.length;
445
-
446
- for (arrIndex = 0; arrIndex &lt; arrCount; arrIndex++) {
447
- // Check we have a function to execute
448
- tmpFunc = arr[arrIndex];
449
-
450
- if (typeof tmpFunc === 'function') {
451
- tmpFunc.apply(this, Array.prototype.slice.call(arguments, 2));
452
- }
453
- }
454
- }
455
- }
456
-
457
- this._emitting = false;
458
- this._processRemovalQueue();
459
-
460
- return this;
461
- }
462
- }),
463
-
464
- emitStatic: new Overload({
465
- /**
466
- * Emit an event that will fire on listeners even when the listener
467
- * is registered AFTER the event has been emitted.
468
- * @memberof Emitter
469
- * @method emitStatic
470
- * @param {String} event The event to emit.
471
- * @returns {*}
472
- */
473
- 'string': function (event) {
474
- // Fire global listeners
475
- return this.$main(event);
476
- },
477
-
478
- /**
479
- * Emit an event with data that will fire on listeners even when the listener
480
- * is registered AFTER the event has been emitted.
481
- * @memberof Emitter
482
- * @method emitStatic
483
- * @param {String} event The event to emit.
484
- * @param {*} data Data to emit with the event.
485
- * @returns {*}
486
- */
487
- 'string, ...': function (event, data) {
488
- // Fire global listeners first
489
- this.$main.apply(this, arguments);
490
-
491
- return this;
492
- },
493
-
494
- /**
495
- * Handles emitting events, is an internal method not called directly.
496
- * @param {String} event The name of the event to emit.
497
- * @param {*} data The data to emit with the event.
498
- * @returns {*}
499
- * @private
500
- */
501
- '$main': function (event, data) {
502
- var id = '*';
503
- this._listeners = this._listeners || {};
504
- this._emitting = true;
505
-
506
- if (this._listeners[event]) {
507
- var arrIndex,
508
- arrCount,
509
- tmpFunc,
510
- arr;
511
-
512
- // Handle global emit
513
- if (this._listeners[event][id]) {
514
- arr = this._listeners[event][id];
515
- arrCount = arr.length;
516
-
517
- for (arrIndex = 0; arrIndex &lt; arrCount; arrIndex++) {
518
- // Check we have a function to execute
519
- tmpFunc = arr[arrIndex];
520
-
521
- if (typeof tmpFunc === 'function') {
522
- tmpFunc.apply(this, Array.prototype.slice.call(arguments, 1));
523
- }
524
- }
525
- }
526
- }
527
-
528
- this._emitting = false;
529
-
530
- this._emitters = this._emitters || {};
531
- this._emitters[event] = this._emitters[event] || [];
532
- this._emitters[event].push({
533
- id: '*',
534
- args: Array.prototype.slice.call(arguments, 1)
535
- });
536
-
537
- this._processRemovalQueue();
538
-
539
- return this;
540
- }
541
- }),
542
-
543
- emitStaticId: new Overload({
544
- /**
545
- * Require an id to emit.
546
- * @memberof Emitter
547
- * @method emitStaticId
548
- * @param event
549
- */
550
- 'string': function (event) {
551
- throw('Missing id from emitId call!');
552
- },
553
-
554
- /**
555
- * Emit an event that will fire on listeners even when the listener
556
- * is registered AFTER the event has been emitted.
557
- * @memberof Emitter
558
- * @method emitStaticId
559
- * @param {String} event The event to emit.
560
- * @param {String} id The id of the event to emit.
561
- * @returns {*}
562
- */
563
- 'string, *': function (event, id) {
564
- return this.$main(event, id);
565
- },
566
-
567
- /**
568
- * Emit an event that will fire on listeners even when the listener
569
- * is registered AFTER the event has been emitted.
570
- * @memberof Emitter
571
- * @method emitStaticId
572
- * @param {String} event The event to emit.
573
- * @param {String} id The id of the event to emit.
574
- * @param {*=} data The data to emit with the event.
575
- * @returns {*}
576
- */
577
- 'string, *, ...': function (event, id, data) {
578
- // Fire global listeners first
579
- this.$main.apply(this, arguments);
580
-
581
- return this;
582
- },
583
-
584
- /**
585
- * Handles emitting events, is an internal method not called directly.
586
- * @param {String} event The name of the event to emit.
587
- * @param {String} id The id of the event to emit.
588
- * @param {*} data The data to emit with the event.
589
- * @returns {*}
590
- * @private
591
- */
592
- '$main': function (event, id, data) {
593
- this._listeners = this._listeners || {};
594
- this._emitting = true;
595
-
596
- if (this._listeners[event]) {
597
- var arrIndex,
598
- arrCount,
599
- tmpFunc,
600
- arr;
601
-
602
- // Handle global emit
603
- if (this._listeners[event]['*']) {
604
- arr = this._listeners[event]['*'];
605
- arrCount = arr.length;
606
-
607
- for (arrIndex = 0; arrIndex &lt; arrCount; arrIndex++) {
608
- // Check we have a function to execute
609
- tmpFunc = arr[arrIndex];
610
-
611
- if (typeof tmpFunc === 'function') {
612
- tmpFunc.apply(this, Array.prototype.slice.call(arguments, 2));
613
- }
614
- }
615
- }
616
-
617
- // Handle id emit
618
- if (this._listeners[event][id]) {
619
- arr = this._listeners[event][id];
620
- arrCount = arr.length;
621
-
622
- for (arrIndex = 0; arrIndex &lt; arrCount; arrIndex++) {
623
- // Check we have a function to execute
624
- tmpFunc = arr[arrIndex];
625
-
626
- if (typeof tmpFunc === 'function') {
627
- tmpFunc.apply(this, Array.prototype.slice.call(arguments, 2));
628
- }
629
- }
630
- }
631
- }
632
-
633
- this._emitting = false;
634
-
635
- this._emitters = this._emitters || {};
636
- this._emitters[event] = this._emitters[event] || [];
637
- this._emitters[event].push({
638
- id: id,
639
- args: Array.prototype.slice.call(arguments, 2)
640
- });
641
-
642
- this._processRemovalQueue();
643
-
644
- return this;
645
- }
646
- }),
647
-
648
- cancelStatic: new Overload({
649
- /**
650
- * Remove a static event emitter.
651
- * @memberof Emitter
652
- * @method emitStatic
653
- * @param {String} event The event to remove static emitter for.
654
- * @returns {*}
655
- */
656
- 'string': function (event) {
657
- // Fire global listeners
658
- return this.$main(event);
659
- },
660
-
661
- /**
662
- * Handles removing emitters, is an internal method not called directly.
663
- * @param {String} event The event to remove static emitter for.
664
- * @returns {*}
665
- * @private
666
- */
667
- '$main': function (event) {
668
- this._emitters = this._emitters || {};
669
- this._emitters[event] = [];
670
-
671
- return this;
672
- }
673
- }),
674
-
675
- /**
676
- * Checks if an event has any event listeners or not.
677
- * @memberof Emitter
678
- * @method willEmit
679
- * @param {String} event The name of the event to check for.
680
- * @returns {boolean} True if one or more event listeners are registered for
681
- * the event. False if none are found.
682
- */
683
- willEmit: function (event) {
684
- var id = '*';
685
-
686
- if (this._listeners &amp;&amp; this._listeners[event]) {
687
- var arrIndex,
688
- arrCount,
689
- tmpFunc,
690
- arr;
691
-
692
- // Handle global emit
693
- if (this._listeners[event][id]) {
694
- arr = this._listeners[event][id];
695
- arrCount = arr.length;
696
-
697
- for (arrIndex = 0; arrIndex &lt; arrCount; arrIndex++) {
698
- // Check we have a function to execute
699
- tmpFunc = arr[arrIndex];
700
-
701
- if (typeof tmpFunc === 'function') {
702
- return true;
703
- }
704
- }
705
- }
706
- }
707
-
708
- return false;
709
- },
710
-
711
- /**
712
- * Checks if an event has any event listeners or not based on the passed id.
713
- * @memberof Emitter
714
- * @method willEmitId
715
- * @param {String} event The name of the event to check for.
716
- * @param {String} id The event ID to check for.
717
- * @returns {boolean} True if one or more event listeners are registered for
718
- * the event. False if none are found.
719
- */
720
- willEmitId: function (event, id) {
721
- if (this._listeners &amp;&amp; this._listeners[event]) {
722
- var arrIndex,
723
- arrCount,
724
- tmpFunc,
725
- arr;
726
-
727
- // Handle global emit
728
- if (this._listeners[event]['*']) {
729
- arr = this._listeners[event]['*'];
730
- arrCount = arr.length;
731
-
732
- for (arrIndex = 0; arrIndex &lt; arrCount; arrIndex++) {
733
- // Check we have a function to execute
734
- tmpFunc = arr[arrIndex];
735
-
736
- if (typeof tmpFunc === 'function') {
737
- return true;
738
- }
739
- }
740
- }
741
-
742
- // Handle id emit
743
- if (this._listeners[event][id]) {
744
- arr = this._listeners[event][id];
745
- arrCount = arr.length;
746
-
747
- for (arrIndex = 0; arrIndex &lt; arrCount; arrIndex++) {
748
- // Check we have a function to execute
749
- tmpFunc = arr[arrIndex];
750
-
751
- if (typeof tmpFunc === 'function') {
752
- return true;
753
- }
754
- }
755
- }
756
- }
757
-
758
- return false;
759
- },
760
-
761
- /**
762
- * If events are cleared with the off() method while the event emitter is
763
- * actively processing any events then the off() calls get added to a
764
- * queue to be executed after the event emitter is finished. This stops
765
- * errors that might occur by potentially modifying the event queue while
766
- * the emitter is running through them. This method is called after the
767
- * event emitter is finished processing.
768
- * @private
769
- */
770
- _processRemovalQueue: function () {
771
- var i;
772
-
773
- if (this._eventRemovalQueue &amp;&amp; this._eventRemovalQueue.length) {
774
- // Execute each removal call
775
- for (i = 0; i &lt; this._eventRemovalQueue.length; i++) {
776
- this._eventRemovalQueue[i]();
777
- }
778
-
779
- // Clear the removal queue
780
- this._eventRemovalQueue = [];
781
- }
782
- },
783
-
784
- /**
785
- * Queues an event to be fired. This has automatic de-bouncing so that any
786
- * events of the same type that occur within 100 milliseconds of a previous
787
- * one will all be wrapped into a single emit rather than emitting tons of
788
- * events for lots of chained inserts etc. Only the data from the last
789
- * de-bounced event will be emitted.
790
- * @memberof Emitter
791
- * @method deferEmit
792
- * @param {String} eventName The name of the event to emit.
793
- * @param {*=} data Optional data to emit with the event.
794
- */
795
- deferEmit: function (eventName, data) {
796
- var self = this,
797
- args;
798
-
799
- if (!this._noEmitDefer &amp;&amp; (!this._db || (this._db &amp;&amp; !this._db._noEmitDefer))) {
800
- args = arguments;
801
-
802
- // Check for an existing timeout
803
- this._deferTimeout = this._deferTimeout || {};
804
- if (this._deferTimeout[eventName]) {
805
- clearTimeout(this._deferTimeout[eventName]);
806
- }
807
-
808
- // Set a timeout
809
- this._deferTimeout[eventName] = setTimeout(function () {
810
- self.emit.apply(self, args);
811
- }, 1);
812
- } else {
813
- this.emit.apply(this, arguments);
814
- }
815
-
816
- return this;
817
- }
818
- };
819
-
29
+ <pre class="prettyprint source linenums"><code>export var ListenerReturnFlag;
30
+ (function (ListenerReturnFlag) {
31
+ ListenerReturnFlag["none"] = "!+_NONE";
32
+ ListenerReturnFlag["cancel"] = "!+_CANCEL";
33
+ })(ListenerReturnFlag || (ListenerReturnFlag = {}));
820
34
  /**
821
- * @class Emitter
822
- * @param obj
823
- * @param {Boolean} prototypeMode Defaults to true. Set to true to add emitter
824
- * methods to the the passed object's prototype property e.g. obj.prototype.on
825
- * = emitter.on. Set to false to add emitter methods the object directly e.g.
826
- * obj.on = emitter.on.
827
- * @constructor
35
+ * Creates a new class with the ability to emit events.
828
36
  */
829
- var Emitter = function (obj, prototypeMode) {
830
- var operateOnObject;
831
-
832
- if (obj === undefined &amp;&amp; prototypeMode === undefined) {
833
- obj = {};
834
- prototypeMode = false;
835
- }
836
-
837
- if (typeof obj === 'boolean' &amp;&amp; prototypeMode === undefined) {
838
- prototypeMode = obj;
839
- obj = {};
840
- }
841
-
842
- if (prototypeMode === undefined) {
843
- prototypeMode = true;
844
- }
845
-
846
- if (typeof obj !== 'object' &amp;&amp; typeof obj !== 'function') {
847
- throw new Error('Cannot operate on a non-object / non-function passed as first argument!');
848
- }
849
-
850
- if (prototypeMode) {
851
- if (obj.prototype === undefined) {
852
- throw new Error('Cannot modify prototype of passed object, it has no prototype property! Was it instantiated with the new operator correctly?');
853
- }
854
-
855
- operateOnObject = obj.prototype;
856
- } else {
857
- operateOnObject = obj;
858
- }
859
-
860
- // Convert the object prototype to have eventing capability
861
- operateOnObject.on = EventMethods.on;
862
- operateOnObject.off = EventMethods.off;
863
- operateOnObject.once = EventMethods.once;
864
- operateOnObject.emit = EventMethods.emit;
865
- operateOnObject.emitId = EventMethods.emitId;
866
- operateOnObject.emitStatic = EventMethods.emitStatic;
867
- operateOnObject.emitStaticId = EventMethods.emitStaticId;
868
- operateOnObject.cancelStatic = EventMethods.cancelStatic;
869
- operateOnObject.deferEmit = EventMethods.deferEmit;
870
- operateOnObject.willEmit = EventMethods.willEmit;
871
- operateOnObject.willEmitId = EventMethods.willEmitId;
872
- operateOnObject._processRemovalQueue = EventMethods._processRemovalQueue;
873
-
874
- return obj;
875
- };
876
-
877
- Emitter.prototype = EventMethods;
878
-
879
- module.exports = Emitter;</code></pre>
37
+ export class Emitter {
38
+ _eventsEmitting = false;
39
+ _eventRemovalQueue = [];
40
+ _eventListeners = {};
41
+ _eventStaticEmitters = {};
42
+ _eventsAllowDefer = false;
43
+ _eventsDeferTimeouts = {};
44
+ _dispatchWindowEventsEnabled = false;
45
+ _dispatchPrefix;
46
+ constructor(dispatchPrefix, shouldDispatchWindowEvents = false) {
47
+ this._dispatchPrefix = dispatchPrefix;
48
+ this._dispatchWindowEventsEnabled = shouldDispatchWindowEvents;
49
+ }
50
+ dispatchWindowEventsEnabled(shouldDispatchWindowEvents) {
51
+ this._dispatchWindowEventsEnabled = shouldDispatchWindowEvents;
52
+ }
53
+ /**
54
+ * Attach an event listener to the passed event only if the passed
55
+ * id matches the id for the event being fired.
56
+ * @param eventName The name of the event to listen for.
57
+ * @param id The id to match against.
58
+ * @param listener The method to call when the event is fired.
59
+ * @returns The emitter instance.
60
+ */
61
+ _on(eventName, id, listener) {
62
+ const generateTimeout = (emitter) => {
63
+ setTimeout(() => {
64
+ listener(...emitter.args);
65
+ }, 1);
66
+ };
67
+ this._eventListeners = this._eventListeners || {};
68
+ const nonNullableEventListeners = (this._eventListeners[eventName] = this._eventListeners[eventName] || {});
69
+ nonNullableEventListeners[id] = nonNullableEventListeners[id] || [];
70
+ nonNullableEventListeners[id].push(listener);
71
+ // Check for any static emitters, and fire the event if any exist
72
+ if (!this._eventStaticEmitters || !this._eventStaticEmitters[eventName] || !this._eventStaticEmitters[eventName].length)
73
+ return this;
74
+ // Emit events for each emitter
75
+ for (let i = 0; i &lt; this._eventStaticEmitters[eventName].length; i++) {
76
+ const emitter = this._eventStaticEmitters[eventName][i];
77
+ if (id === "*" || emitter.id === id) {
78
+ // Call the listener out of process so that any code that expects a listener
79
+ // to be called at some point in the future rather than immediately on registration
80
+ // will not fail
81
+ generateTimeout(emitter);
82
+ }
83
+ }
84
+ return this;
85
+ }
86
+ /**
87
+ * Attach an event listener to the passed event only if the passed
88
+ * id matches the document id for the event being fired.
89
+ * @param eventName The name of the event to listen for.
90
+ * @param id The id to match against.
91
+ * @param listener The method to call when the event is fired.
92
+ * @returns The emitter instance.
93
+ */
94
+ _once(eventName, id, listener) {
95
+ let fired = false;
96
+ let originalReturnData;
97
+ const internalCallback = (...args) => {
98
+ if (fired)
99
+ return originalReturnData;
100
+ fired = true;
101
+ this.off(eventName, id, internalCallback);
102
+ originalReturnData = listener(...args);
103
+ return originalReturnData;
104
+ };
105
+ return this.on(eventName, id, internalCallback);
106
+ }
107
+ /**
108
+ * Cancels an event listener based on an event name, id and listener function.
109
+ * @param eventName The event to cancel listener for.
110
+ * @param id The ID of the event to cancel listening for.
111
+ * @param listener The event listener function used in the on()
112
+ * or once() call to cancel.
113
+ * @returns The emitter instance.
114
+ */
115
+ _off(eventName, id, listener) {
116
+ // If the event name doesn't have any listeners, exit early
117
+ if (!this._eventListeners || !this._eventListeners[eventName] || !this._eventListeners[eventName][id])
118
+ return this;
119
+ // If we are emitting events at the moment, don't remove this listener
120
+ // until the process has completed, so we queue for removal instead
121
+ if (this._eventsEmitting) {
122
+ this._eventRemovalQueue = this._eventRemovalQueue || [];
123
+ this._eventRemovalQueue.push(() => {
124
+ this.off(eventName, id, listener);
125
+ });
126
+ return this;
127
+ }
128
+ // Check if we have no specific listener... in this case
129
+ // we want to remove all listeners for an id
130
+ if (!listener) {
131
+ if (id === "*") {
132
+ // The id is "all" and no listener was provided so delete all
133
+ // event listeners for this event name
134
+ delete this._eventListeners[eventName];
135
+ return this;
136
+ }
137
+ // No listener provided, delete all listeners for this id
138
+ delete this._eventListeners[eventName][id];
139
+ return this;
140
+ }
141
+ const arr = this._eventListeners[eventName][id] || [];
142
+ const index = arr.indexOf(listener);
143
+ if (index > -1) {
144
+ arr.splice(index, 1);
145
+ }
146
+ return this;
147
+ }
148
+ /**
149
+ * Creates an event listener that listens for any and all events
150
+ * emitted.
151
+ */
152
+ onAny(listener) {
153
+ this.on("*", listener);
154
+ }
155
+ on(eventName, idOrListener, listener) {
156
+ if (typeof idOrListener === "string") {
157
+ return this._on(eventName, idOrListener, listener);
158
+ }
159
+ return this._on(eventName, "*", idOrListener);
160
+ }
161
+ once(eventName, ...rest) {
162
+ const restTypes = rest.map((arg) => typeof arg);
163
+ if (restTypes[0] === "function") {
164
+ return this._once(eventName, "*", rest[0]);
165
+ }
166
+ return this._once(eventName, rest[0], rest[1]);
167
+ }
168
+ overwrite(eventName, ...rest) {
169
+ const restTypes = rest.map((arg) => typeof arg);
170
+ if (restTypes[0] === "function") {
171
+ this.off(eventName);
172
+ return this._on(eventName, "*", rest[0]);
173
+ }
174
+ this.off(eventName, rest[0]);
175
+ return this._on(eventName, rest[0], rest[1]);
176
+ }
177
+ /**
178
+ * Removes an event listener that listens for any and all events
179
+ * emitted.
180
+ */
181
+ offAny(listener) {
182
+ this.off("*", listener);
183
+ }
184
+ off(eventName, ...rest) {
185
+ if (rest.length === 0) {
186
+ // Only event was provided, use * as the id to mean "any without"
187
+ // a specific id
188
+ return this._off(eventName, "*");
189
+ }
190
+ const restTypes = rest.map((arg) => typeof arg);
191
+ if (restTypes[0] === "function") {
192
+ // The first arg after the event name was a function (listener)
193
+ // so remove listening for events for this specific listener
194
+ return this._off(eventName, "*", rest[0]);
195
+ }
196
+ // Both id and listener were provided, remove for the specific id
197
+ return this._off(eventName, rest[0], rest[1]);
198
+ }
199
+ _emitToSingleListener(listener, data) {
200
+ return listener(...data);
201
+ }
202
+ _emitToArrayOfListeners(arr, data) {
203
+ const arrCount = arr.length;
204
+ const resultArr = [];
205
+ for (let arrIndex = 0; arrIndex &lt; arrCount; arrIndex++) {
206
+ // Check we have a function to execute
207
+ const tmpFunc = arr[arrIndex];
208
+ if (typeof tmpFunc !== "function") {
209
+ continue;
210
+ }
211
+ const eventListenerResponse = tmpFunc(...data);
212
+ resultArr.push(eventListenerResponse);
213
+ if (eventListenerResponse === ListenerReturnFlag.cancel) {
214
+ // Cancel further event processing
215
+ break;
216
+ }
217
+ }
218
+ return resultArr;
219
+ }
220
+ /**
221
+ * Dispatches an event originating in our emitter to the browser's
222
+ * window object.
223
+ * @param eventName The name of the event to emit. This gets prefixed with the
224
+ * dispatch prefix if one is set.
225
+ * @param data
226
+ */
227
+ _emitToWindowDispatch(eventName, data) {
228
+ if (typeof window === "undefined")
229
+ return;
230
+ if (!this._dispatchWindowEventsEnabled) {
231
+ return;
232
+ }
233
+ const finalEventName = (this._dispatchPrefix ? `${this._dispatchPrefix}.${eventName}` : eventName);
234
+ window.dispatchEvent(new CustomEvent(finalEventName, { detail: data }));
235
+ }
236
+ /**
237
+ * Call an event listener by name. The `rpc()` function differs from `emit()` in
238
+ * that it will only call and return data from the first event listener for the
239
+ * event rather than all event listeners. If you have more than one event listener
240
+ * assigned to the event, all others except the first will be ignored and will
241
+ * not receive the event.
242
+ * @param eventName The name of the event to call the listener for.
243
+ * @param {...any} data The arguments to send to the listening method.
244
+ * If you are sending multiple arguments, separate them with a comma so
245
+ * that they are received by the function as separate arguments.
246
+ * @return {number}
247
+ * @example #Call the Event Listener
248
+ * // Emit the event named "hello"
249
+ * myEntity.emit('hello');
250
+ * @example #Call the Event Listener With Data Object
251
+ * // Emit the event named "hello"
252
+ * myEntity.emit('hello', {moo: true});
253
+ * @example #Call the Event Listener With Multiple Data Values
254
+ * // Emit the event named "hello"
255
+ * myEntity.emit('hello', {moo: true}, 'someString');
256
+ * @example #Register the Listener for Event Data
257
+ * // Set a listener to listen for the data (multiple values emitted
258
+ * // from an event are passed as function arguments)
259
+ * myEntity.on('hello', function (arg1, arg2) {
260
+ * console.log("Arguments:", arg1, arg2);
261
+ * return "foo";
262
+ * }
263
+ *
264
+ * // Emit the event named "hello"
265
+ * const result = myEntity.emit('hello', 'data1', 'data2');
266
+ * console.log("Result:", result);
267
+ *
268
+ * // The console output is:
269
+ * // Arguments: data1 data2
270
+ * // Result: "foo"
271
+ */
272
+ rpc(eventName, ...data) {
273
+ return this.rpcId(eventName, "*", ...data);
274
+ }
275
+ rpcId(eventName, id, ...data) {
276
+ if (!this._eventListeners || !this._eventListeners[eventName]) {
277
+ throw new Error("Cannot make an rpc call without at least one event listener and none were found");
278
+ }
279
+ let emitterResult;
280
+ this._eventsEmitting = true;
281
+ if (this._eventListeners[eventName][id]) {
282
+ // Handle id emit
283
+ const arr = this._eventListeners[eventName][id];
284
+ emitterResult = this._emitToSingleListener(arr[0], data);
285
+ }
286
+ else if (id !== "*" &amp;&amp; this._eventListeners[eventName]["*"]) {
287
+ // Handle wildcard emit if the id passed wasn't already a wildcard (*) id
288
+ const arr = this._eventListeners[eventName]["*"];
289
+ emitterResult = this._emitToSingleListener(arr[0], data);
290
+ }
291
+ else {
292
+ if (id === "*") {
293
+ 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 })`);
294
+ }
295
+ 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 })`);
296
+ }
297
+ this._eventsEmitting = false;
298
+ this._processRemovalQueue();
299
+ return emitterResult;
300
+ }
301
+ /**
302
+ * Emit an event by name.
303
+ * @param eventName The name of the event to emit.
304
+ * @param {...any} data The arguments to send to any listening methods.
305
+ * If you are sending multiple arguments, separate them with a comma so
306
+ * that they are received by the function as separate arguments.
307
+ * @return {any[]} An array of all return values from all the listeners for the event.
308
+ * @example #Emit an Event
309
+ * // Emit the event named "hello"
310
+ * myEntity.emit('hello');
311
+ * @example #Emit an Event With Data Object
312
+ * // Emit the event named "hello"
313
+ * myEntity.emit('hello', {moo: true});
314
+ * @example #Emit an Event With Multiple Data Values
315
+ * // Emit the event named "hello"
316
+ * myEntity.emit('hello', {moo: true}, 'someString');
317
+ * @example #Listen for Event Data
318
+ * // Set a listener to listen for the data (multiple values emitted
319
+ * // from an event are passed as function arguments)
320
+ * myEntity.on('hello', function (arg1, arg2) {
321
+ * console.log("Arguments:", arg1, arg2);
322
+ * return "foo";
323
+ * }
324
+ *
325
+ * // Emit the event named "hello"
326
+ * // The result is returned as an array of all return values
327
+ * // from all the listeners for the event
328
+ * const result = myEntity.emit('hello', 'data1', 'data2');
329
+ * console.log("Result:", result);
330
+ *
331
+ * // The console output is:
332
+ * // Arguments: data1 data2
333
+ * // Result: ["foo"]
334
+ */
335
+ emit(eventName, ...data) {
336
+ this._emitToWindowDispatch(eventName, data);
337
+ return this.emitId(eventName, "*", ...data);
338
+ }
339
+ /**
340
+ * Emits an event by name and id.
341
+ * @param eventName The name of the event to emit.
342
+ * @param id The id of the event to emit.
343
+ * @param {...any} data The arguments to send to any listening methods.
344
+ * If you are sending multiple arguments, separate them with a comma so
345
+ * that they are received by the function as separate arguments.
346
+ * @return {any[]} An array of all return values from all the listeners for the event.
347
+ */
348
+ emitId(eventName, id, ...data) {
349
+ if (!this._eventListeners || (!this._eventListeners[eventName] &amp;&amp; !this._eventListeners["*"])) {
350
+ return [];
351
+ }
352
+ let emitterResult = [];
353
+ this._eventsEmitting = true;
354
+ if (this._eventListeners[eventName]) {
355
+ // Handle id emit
356
+ if (this._eventListeners[eventName][id]) {
357
+ const arr = this._eventListeners[eventName][id];
358
+ emitterResult = emitterResult.concat(this._emitToArrayOfListeners(arr, data));
359
+ }
360
+ // Handle id wildcard emit if the id passed wasn't already a wildcard (*) id
361
+ if (id !== "*" &amp;&amp; this._eventListeners[eventName]["*"]) {
362
+ const arr = this._eventListeners[eventName]["*"];
363
+ emitterResult = emitterResult.concat(this._emitToArrayOfListeners(arr, data));
364
+ }
365
+ }
366
+ if (this._eventListeners["*"]) {
367
+ const arr = this._eventListeners["*"]["*"];
368
+ emitterResult = emitterResult.concat(this._emitToArrayOfListeners(arr, [eventName, ...data]));
369
+ }
370
+ this._eventsEmitting = false;
371
+ this._processRemovalQueue();
372
+ return emitterResult;
373
+ }
374
+ /**
375
+ * Creates a persistent event. Once emitStatic() has been called, a
376
+ * persistent event is registered. Any existing event listeners will
377
+ * be called just like when you call emit(), however, any new
378
+ * listeners that are registered for this event via on() will also be
379
+ * called as soon as they are added.
380
+ * @param eventName The name of the event to emit.
381
+ * @param {...any} data Optional arguments to emit with the event.
382
+ * @returns The emitter instance.
383
+ * @private
384
+ */
385
+ emitStatic(eventName, ...data) {
386
+ const id = "*";
387
+ this._eventListeners = this._eventListeners || {};
388
+ this._eventsEmitting = true;
389
+ if (this._eventListeners[eventName] &amp;&amp; this._eventListeners[eventName][id]) {
390
+ // Handle id wildcard emit
391
+ const arr = this._eventListeners[eventName][id];
392
+ const arrCount = arr.length;
393
+ for (let arrIndex = 0; arrIndex &lt; arrCount; arrIndex++) {
394
+ // Check we have a function to execute
395
+ const tmpFunc = arr[arrIndex];
396
+ if (typeof tmpFunc === "function") {
397
+ tmpFunc.call(this, ...data);
398
+ }
399
+ }
400
+ }
401
+ this._eventsEmitting = false;
402
+ this._eventStaticEmitters = this._eventStaticEmitters || {};
403
+ this._eventStaticEmitters[eventName] = this._eventStaticEmitters[eventName] || [];
404
+ this._eventStaticEmitters[eventName].push({
405
+ id: "*",
406
+ args: data
407
+ });
408
+ this._processRemovalQueue();
409
+ return this;
410
+ }
411
+ /**
412
+ * Creates a persistent emitter record that will fire a listener if
413
+ * one is added for this event after the emitStatic() call has been
414
+ * made.
415
+ * @param eventName The name of the event to emit.
416
+ * @param id The id of the event to emit.
417
+ * @param {...any} data Optional arguments to emit with the event.
418
+ * @returns The emitter instance.
419
+ * @private
420
+ */
421
+ emitStaticId(eventName, id, ...data) {
422
+ if (!id)
423
+ throw new Error("Missing id from emitId call!");
424
+ this._eventListeners = this._eventListeners || {};
425
+ this._eventsEmitting = true;
426
+ if (this._eventListeners[eventName]) {
427
+ // Handle id emit
428
+ if (this._eventListeners[eventName][id]) {
429
+ const arr = this._eventListeners[eventName][id];
430
+ const arrCount = arr.length;
431
+ for (let arrIndex = 0; arrIndex &lt; arrCount; arrIndex++) {
432
+ // Check we have a function to execute
433
+ const tmpFunc = arr[arrIndex];
434
+ if (typeof tmpFunc === "function") {
435
+ tmpFunc.call(this, ...data);
436
+ }
437
+ }
438
+ }
439
+ // Handle wildcard emit
440
+ if (this._eventListeners[eventName]["*"]) {
441
+ const arr = this._eventListeners[eventName]["*"];
442
+ const arrCount = arr.length;
443
+ for (let arrIndex = 0; arrIndex &lt; arrCount; arrIndex++) {
444
+ // Check we have a function to execute
445
+ const tmpFunc = arr[arrIndex];
446
+ if (typeof tmpFunc === "function") {
447
+ tmpFunc.call(this, ...data);
448
+ }
449
+ }
450
+ }
451
+ }
452
+ this._eventsEmitting = false;
453
+ this._eventStaticEmitters = this._eventStaticEmitters || {};
454
+ this._eventStaticEmitters[eventName] = this._eventStaticEmitters[eventName] || [];
455
+ this._eventStaticEmitters[eventName].push({
456
+ id,
457
+ args: data
458
+ });
459
+ this._processRemovalQueue();
460
+ return this;
461
+ }
462
+ /**
463
+ * Handles removing emitters, is an internal method not called directly.
464
+ * @param eventName The event to remove static emitter for.
465
+ * @returns The emitter instance.
466
+ * @private
467
+ */
468
+ cancelStatic(eventName) {
469
+ this._eventStaticEmitters = this._eventStaticEmitters || {};
470
+ this._eventStaticEmitters[eventName] = [];
471
+ return this;
472
+ }
473
+ /**
474
+ * Checks if an event has any event listeners or not.
475
+ * @param eventName The name of the event to check for.
476
+ * @returns True if one or more event listeners are registered for
477
+ * the event. False if none are found.
478
+ */
479
+ willEmit(eventName) {
480
+ const id = "*";
481
+ if (!this._eventListeners || !this._eventListeners[eventName]) {
482
+ return false;
483
+ }
484
+ const arr = this._eventListeners[eventName][id];
485
+ const arrCount = arr.length;
486
+ for (let arrIndex = 0; arrIndex &lt; arrCount; arrIndex++) {
487
+ // Check we have a function to execute
488
+ const tmpFunc = arr[arrIndex];
489
+ if (typeof tmpFunc === "function") {
490
+ return true;
491
+ }
492
+ }
493
+ return false;
494
+ }
495
+ /**
496
+ * Checks if an event has any event listeners or not based on the passed id.
497
+ * @param eventName The name of the event to check for.
498
+ * @param id The event ID to check for.
499
+ * @returns True if one or more event listeners are registered for
500
+ * the event. False if none are found.
501
+ */
502
+ willEmitId(eventName, id) {
503
+ if (!this._eventListeners || !this._eventListeners[eventName]) {
504
+ return false;
505
+ }
506
+ // Handle id emit
507
+ if (this._eventListeners[eventName][id]) {
508
+ const arr = this._eventListeners[eventName][id];
509
+ const arrCount = arr.length;
510
+ for (let arrIndex = 0; arrIndex &lt; arrCount; arrIndex++) {
511
+ // Check we have a function to execute
512
+ const tmpFunc = arr[arrIndex];
513
+ if (typeof tmpFunc === "function") {
514
+ return true;
515
+ }
516
+ }
517
+ }
518
+ // Handle wildcard emit
519
+ if (this._eventListeners[eventName]["*"]) {
520
+ const arr = this._eventListeners[eventName]["*"];
521
+ const arrCount = arr.length;
522
+ for (let arrIndex = 0; arrIndex &lt; arrCount; arrIndex++) {
523
+ // Check we have a function to execute
524
+ const tmpFunc = arr[arrIndex];
525
+ if (typeof tmpFunc === "function") {
526
+ return true;
527
+ }
528
+ }
529
+ }
530
+ return false;
531
+ }
532
+ /**
533
+ * Queues an event to be fired. This has automatic de-bouncing so that any
534
+ * events of the same type that occur within 100 milliseconds of a previous
535
+ * one will all be wrapped into a single emit rather than emitting tons of
536
+ * events for lots of chained inserts etc. Only the data from the last
537
+ * de-bounced event will be emitted.
538
+ * @param eventName The name of the event to emit.
539
+ * @param {...any} data Optional arguments to emit with the event.
540
+ * @returns The emitter instance.
541
+ */
542
+ deferEmit(eventName, ...data) {
543
+ if (!this._eventsAllowDefer) {
544
+ // Check for an existing timeout
545
+ this._eventsDeferTimeouts = this._eventsDeferTimeouts || {};
546
+ if (this._eventsDeferTimeouts[eventName]) {
547
+ clearTimeout(this._eventsDeferTimeouts[eventName]);
548
+ }
549
+ // Set a timeout
550
+ this._eventsDeferTimeouts[eventName] = setTimeout(() => {
551
+ void this.emit.call(this, eventName, ...data);
552
+ }, 1);
553
+ }
554
+ else {
555
+ void this.emit.call(this, eventName, ...data);
556
+ }
557
+ return this;
558
+ }
559
+ /**
560
+ * Returns true if the result from an emit() call passed as the first
561
+ * argument contains a cancellation flag.
562
+ * @param resultArr
563
+ */
564
+ didCancel(resultArr) {
565
+ return resultArr.findIndex((result) => result === ListenerReturnFlag.cancel) > -1;
566
+ }
567
+ /**
568
+ * If events are cleared with the off() method while the event emitter is
569
+ * actively processing any events then the off() calls get added to a
570
+ * queue to be executed after the event emitter is finished. This stops
571
+ * errors that might occur by potentially mutating the event listener array
572
+ * while the emitter is running through them. This method is called after
573
+ * the event emitter is finished processing.
574
+ * @private
575
+ */
576
+ _processRemovalQueue() {
577
+ if (!this._eventRemovalQueue || !this._eventRemovalQueue.length) {
578
+ return;
579
+ }
580
+ // Execute each removal call
581
+ for (let i = 0; i &lt; this._eventRemovalQueue.length; i++) {
582
+ this._eventRemovalQueue[i]();
583
+ }
584
+ // Clear the removal queue
585
+ this._eventRemovalQueue = [];
586
+ }
587
+ }
588
+ export function makeEmitter(obj, prototypeMode) {
589
+ let operateOnObject;
590
+ if (obj === undefined &amp;&amp; prototypeMode === undefined) {
591
+ obj = {};
592
+ prototypeMode = false;
593
+ }
594
+ if (typeof obj === "boolean" &amp;&amp; prototypeMode === undefined) {
595
+ prototypeMode = obj;
596
+ obj = {};
597
+ }
598
+ if (prototypeMode === undefined) {
599
+ prototypeMode = true;
600
+ }
601
+ if (typeof obj !== "object" &amp;&amp; typeof obj !== "function") {
602
+ throw new Error("Cannot operate on a non-object / non-function passed as first argument!");
603
+ }
604
+ if (prototypeMode) {
605
+ if (obj.prototype === undefined) {
606
+ throw new Error("Cannot modify prototype of passed object, it has no prototype property! Was it instantiated with the new operator correctly?");
607
+ }
608
+ operateOnObject = obj.prototype;
609
+ }
610
+ else {
611
+ operateOnObject = obj;
612
+ }
613
+ // Convert the object prototype to have eventing capability
614
+ operateOnObject.on = Emitter.prototype.on;
615
+ operateOnObject.onAny = Emitter.prototype.onAny;
616
+ operateOnObject.off = Emitter.prototype.off;
617
+ operateOnObject.offAny = Emitter.prototype.offAny;
618
+ operateOnObject.once = Emitter.prototype.once;
619
+ operateOnObject.emit = Emitter.prototype.emit;
620
+ operateOnObject.emitId = Emitter.prototype.emitId;
621
+ operateOnObject.emitStatic = Emitter.prototype.emitStatic;
622
+ operateOnObject.emitStaticId = Emitter.prototype.emitStaticId;
623
+ operateOnObject.cancelStatic = Emitter.prototype.cancelStatic;
624
+ operateOnObject.deferEmit = Emitter.prototype.deferEmit;
625
+ operateOnObject.willEmit = Emitter.prototype.willEmit;
626
+ operateOnObject.willEmitId = Emitter.prototype.willEmitId;
627
+ operateOnObject._processRemovalQueue = Emitter.prototype._processRemovalQueue;
628
+ return obj;
629
+ }
630
+ </code></pre>
880
631
  </article>
881
632
  </section>
882
633
 
@@ -892,7 +643,7 @@ module.exports = Emitter;</code></pre>
892
643
  <br class="clear">
893
644
 
894
645
  <footer>
895
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Tue Jan 22 2019 14:10:25 GMT+0000 (GMT)
646
+ Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Tue Sep 23 2025 16:47:15 GMT+0100 (Western European Summer Time)
896
647
  </footer>
897
648
 
898
649
  <script> prettyPrint(); </script>