UNPKG

8.5 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3const _ = require("lodash");
4const eventSplitter = /\s+/;
5function eventsApi(iteratee, events, name, callback, options) {
6 let i = 0, names;
7 if (name && typeof name === 'object') {
8 if (callback !== void 0 && 'context' in options && options['context'] === void 0) {
9 options['context'] = callback;
10 }
11 for (names = _.keys(name); i < names.length; i++) {
12 events = eventsApi(iteratee, events, names[i], name[names[i]], options);
13 }
14 }
15 else if (name && typeof name === 'string' && eventSplitter.test(name)) {
16 for (names = name.split(eventSplitter); i < names.length; i++) {
17 events = iteratee(events, names[i], callback, options);
18 }
19 }
20 else {
21 events = iteratee(events, name, callback, options);
22 }
23 return events;
24}
25function onApi(events, name, callback, options) {
26 if (callback) {
27 const handlers = events[name] || (events[name] = []);
28 const context = options.context, ctx = options.ctx, listening = options.listening, priority = options.priority;
29 if (listening) {
30 listening.count++;
31 }
32 handlers.push({
33 callback: callback,
34 context: context,
35 ctx: context || ctx,
36 listening: listening,
37 priority: priority
38 });
39 handlers.sort((a, b) => b.priority - a.priority);
40 }
41 return events;
42}
43function offApi(events, name, callback, options) {
44 if (!events) {
45 return;
46 }
47 let i = 0, listening;
48 const context = options.context, listeners = options.listeners;
49 if (!name && !callback && !context) {
50 const ids = _.keys(listeners);
51 for (; i < ids.length; i++) {
52 listening = listeners[ids[i]];
53 delete listeners[listening.id];
54 delete listening.listeningTo[listening.objId];
55 }
56 return;
57 }
58 const names = name ? [name] : _.keys(events);
59 for (; i < names.length; i++) {
60 name = names[i];
61 const handlers = events[name];
62 if (!handlers) {
63 break;
64 }
65 const remaining = [];
66 for (let j = 0; j < handlers.length; j++) {
67 const handler = handlers[j];
68 if (callback && callback !== handler.callback &&
69 callback !== handler.callback._callback ||
70 context && context !== handler.context) {
71 remaining.push(handler);
72 }
73 else {
74 listening = handler.listening;
75 if (listening && --listening.count === 0) {
76 delete listeners[listening.id];
77 delete listening.listeningTo[listening.objId];
78 }
79 }
80 }
81 if (remaining.length) {
82 events[name] = remaining;
83 }
84 else {
85 delete events[name];
86 }
87 }
88 if (_.size(events)) {
89 return events;
90 }
91}
92function onceMap(map, name, callback, offer) {
93 if (callback) {
94 const once = map[name] = _.once(function () {
95 offer(name, once);
96 callback.apply(this, arguments);
97 });
98 once._callback = callback;
99 }
100 return map;
101}
102function triggerApi(objEvents, name, callback, args, triggerer = triggerEvents) {
103 if (objEvents) {
104 const events = objEvents[name];
105 let allEvents = objEvents['all'];
106 if (events && allEvents) {
107 allEvents = allEvents.slice();
108 }
109 if (events) {
110 triggerer(events, args);
111 }
112 if (allEvents) {
113 triggerer(allEvents, [name].concat(args));
114 }
115 }
116 return objEvents;
117}
118function triggerEvents(events, args) {
119 let ev, i = -1, l = events.length, a1 = args[0], a2 = args[1], a3 = args[2];
120 switch (args.length) {
121 case 0:
122 while (++i < l) {
123 (ev = events[i]).callback.call(ev.ctx);
124 }
125 return;
126 case 1:
127 while (++i < l) {
128 (ev = events[i]).callback.call(ev.ctx, a1);
129 }
130 return;
131 case 2:
132 while (++i < l) {
133 (ev = events[i]).callback.call(ev.ctx, a1, a2);
134 }
135 return;
136 case 3:
137 while (++i < l) {
138 (ev = events[i]).callback.call(ev.ctx, a1, a2, a3);
139 }
140 return;
141 default:
142 while (++i < l) {
143 (ev = events[i]).callback.apply(ev.ctx, args);
144 }
145 return;
146 }
147}
148class Event {
149 constructor(name) {
150 this._isPropagationStopped = false;
151 this._isDefaultPrevented = false;
152 this._name = name;
153 }
154 stopPropagation() {
155 this._isPropagationStopped = true;
156 }
157 preventDefault() {
158 this._isDefaultPrevented = true;
159 }
160 get name() {
161 return this._name;
162 }
163 get isPropagationStopped() {
164 return this._isPropagationStopped;
165 }
166 get isDefaultPrevented() {
167 return this._isDefaultPrevented;
168 }
169}
170exports.Event = Event;
171class EventDispatcher {
172 get _listenId() {
173 return this._savedListenId || (this._savedListenId = _.uniqueId('l'));
174 }
175 on(nameOrMap, callback, context, priority) {
176 this.internalOn(nameOrMap, callback, context, priority);
177 return this;
178 }
179 internalOn(name, callback, context, priority = 0, listening) {
180 this._events = eventsApi(onApi, this._events || {}, name, callback, {
181 context: context,
182 ctx: this,
183 listening: listening,
184 priority: priority
185 });
186 if (listening) {
187 const listeners = this._listeners || (this._listeners = {});
188 listeners[listening.id] = listening;
189 }
190 }
191 once(name, callback, context, priority) {
192 const events = eventsApi(onceMap, {}, name, callback, _.bind(this.off, this));
193 return this.on(events, void 0, context, priority);
194 }
195 off(name, callback, context) {
196 if (!this._events) {
197 return this;
198 }
199 this._events = eventsApi(offApi, this._events, name, callback, {
200 context: context,
201 listeners: this._listeners
202 });
203 return this;
204 }
205 listenTo(obj, name, callback, priority) {
206 if (!obj) {
207 return this;
208 }
209 const id = obj._listenId;
210 const listeningTo = this._listeningTo || (this._listeningTo = {});
211 let listening = listeningTo[id];
212 if (!listening) {
213 const thisId = this._listenId;
214 listening = listeningTo[id] = {
215 obj: obj,
216 objId: id,
217 id: thisId,
218 listeningTo: listeningTo,
219 count: 0
220 };
221 }
222 obj.internalOn(name, callback, this, priority, listening);
223 return this;
224 }
225 listenToOnce(obj, name, callback, priority) {
226 const events = eventsApi(onceMap, {}, name, callback, _.bind(this.stopListening, this, obj));
227 return this.listenTo(obj, events, void 0, priority);
228 }
229 stopListening(obj, name, callback) {
230 const listeningTo = this._listeningTo;
231 if (!listeningTo) {
232 return this;
233 }
234 const ids = obj ? [obj._listenId] : _.keys(listeningTo);
235 for (let i = 0; i < ids.length; i++) {
236 const listening = listeningTo[ids[i]];
237 if (!listening) {
238 break;
239 }
240 listening.obj.off(name, callback, this);
241 }
242 if (_.isEmpty(listeningTo)) {
243 this._listeningTo = void 0;
244 }
245 return this;
246 }
247 trigger(name, ...args) {
248 if (!this._events) {
249 return this;
250 }
251 if (name instanceof Event) {
252 triggerApi(this._events, name.name, void 0, [name], (events, args) => {
253 let ev, i = -1, l = events.length;
254 while (++i < l) {
255 if (name.isPropagationStopped) {
256 return;
257 }
258 ev = events[i];
259 ev.callback.apply(ev.ctx, args);
260 }
261 });
262 }
263 else {
264 eventsApi(triggerApi, this._events, name, void 0, args);
265 }
266 return this;
267 }
268}
269exports.EventDispatcher = EventDispatcher;
270//# sourceMappingURL=events.js.map
\No newline at end of file