Blame Raw
· · · 197 lines (5.0 KB)
0 contributors
1/* Polyfill indexOf. */
2var indexOf;
3
4if (typeof Array.prototype.indexOf === 'function') {
5 indexOf = function (haystack, needle) {
6 return haystack.indexOf(needle);
7 };
8} else {
9 indexOf = function (haystack, needle) {
10 var i = 0, length = haystack.length, idx = -1, found = false;
11
12 while (i < length && !found) {
13 if (haystack[i] === needle) {
14 idx = i;
15 found = true;
16 }
17
18 i++;
19 }
20
21 return idx;
22 };
23};
24
25
26/* Polyfill EventEmitter. */
27/**
28 * Creates an event emitter.
29 * @param {string[]} autoFireAfterEmit Auto-fire event names
30 */
31var EventEmitter = function (autoFireAfterEmit = []) {
32 this.events = {};
33 this.autoFireLastArgs = new Map();
34 this.autoFireAfterEmit = new Set(autoFireAfterEmit);
35};
36
37/**
38 * Adds a listener to an event.
39 * @param {string} event Event name
40 * @param {function} listener Event listener
41 * @returns
42 */
43EventEmitter.prototype.on = function (event, listener) {
44 // Unknown event used by external libraries?
45 if (event === undefined) {
46 console.trace('EventEmitter: Cannot listen to undefined event');
47 return;
48 }
49
50 if (typeof this.events[event] !== 'object') {
51 this.events[event] = [];
52 }
53
54 this.events[event].push(listener);
55
56 if (this.autoFireAfterEmit.has(event) && this.autoFireLastArgs.has(event)) {
57 listener.apply(this, this.autoFireLastArgs.get(event));
58 }
59};
60
61/**
62 * Makes the listener the last to be called when the event is emitted
63 * @param {string} event Event name
64 * @param {function} listener Event listener
65 */
66EventEmitter.prototype.makeLast = function (event, listener) {
67 if (typeof this.events[event] !== 'object') {
68 this.events[event] = [];
69 }
70
71 const events = this.events[event];
72 const idx = events.indexOf(listener);
73
74 if (idx > -1) {
75 events.splice(idx, 1);
76 }
77
78 events.push(listener);
79
80 if (this.autoFireAfterEmit.has(event) && this.autoFireLastArgs.has(event)) {
81 listener.apply(this, this.autoFireLastArgs.get(event));
82 }
83}
84
85/**
86 * Makes the listener the first to be called when the event is emitted
87 * @param {string} event Event name
88 * @param {function} listener Event listener
89 */
90EventEmitter.prototype.makeFirst = function (event, listener) {
91 if (typeof this.events[event] !== 'object') {
92 this.events[event] = [];
93 }
94
95 const events = this.events[event];
96 const idx = events.indexOf(listener);
97
98 if (idx > -1) {
99 events.splice(idx, 1);
100 }
101
102 events.unshift(listener);
103
104 if (this.autoFireAfterEmit.has(event) && this.autoFireLastArgs.has(event)) {
105 listener.apply(this, this.autoFireLastArgs.get(event));
106 }
107}
108
109/**
110 * Removes a listener from an event.
111 * @param {string} event Event name
112 * @param {function} listener Event listener
113 */
114EventEmitter.prototype.removeListener = function (event, listener) {
115 var idx;
116
117 if (typeof this.events[event] === 'object') {
118 idx = indexOf(this.events[event], listener);
119
120 if (idx > -1) {
121 this.events[event].splice(idx, 1);
122 }
123 }
124};
125
126/**
127 * Emits an event with optional arguments.
128 * @param {string} event Event name
129 */
130EventEmitter.prototype.emit = async function (event) {
131 let args = [].slice.call(arguments, 1);
132 if (localStorage.getItem('eventTracing') === 'true') {
133 console.trace('Event emitted: ' + event, args);
134 } else {
135 console.debug('Event emitted: ' + event);
136 }
137
138 let i, listeners, length;
139
140 if (typeof this.events[event] === 'object') {
141 listeners = this.events[event].slice();
142 length = listeners.length;
143
144 for (i = 0; i < length; i++) {
145 try {
146 await listeners[i].apply(this, args);
147 }
148 catch (err) {
149 console.error(err);
150 console.trace('Error in event listener');
151 }
152 }
153 }
154
155 if (this.autoFireAfterEmit.has(event)) {
156 this.autoFireLastArgs.set(event, args);
157 }
158};
159
160EventEmitter.prototype.emitAndWait = function (event) {
161 let args = [].slice.call(arguments, 1);
162 if (localStorage.getItem('eventTracing') === 'true') {
163 console.trace('Event emitted: ' + event, args);
164 } else {
165 console.debug('Event emitted: ' + event);
166 }
167
168 let i, listeners, length;
169
170 if (typeof this.events[event] === 'object') {
171 listeners = this.events[event].slice();
172 length = listeners.length;
173
174 for (i = 0; i < length; i++) {
175 try {
176 listeners[i].apply(this, args);
177 }
178 catch (err) {
179 console.error(err);
180 console.trace('Error in event listener');
181 }
182 }
183 }
184
185 if (this.autoFireAfterEmit.has(event)) {
186 this.autoFireLastArgs.set(event, args);
187 }
188};
189
190EventEmitter.prototype.once = function (event, listener) {
191 this.on(event, function g() {
192 this.removeListener(event, g);
193 listener.apply(this, arguments);
194 });
195};
196
197export { EventEmitter }