1 | "use strict";
|
2 | var __assign = (this && this.__assign) || function () {
|
3 | __assign = Object.assign || function(t) {
|
4 | for (var s, i = 1, n = arguments.length; i < n; i++) {
|
5 | s = arguments[i];
|
6 | for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
7 | t[p] = s[p];
|
8 | }
|
9 | return t;
|
10 | };
|
11 | return __assign.apply(this, arguments);
|
12 | };
|
13 | Object.defineProperty(exports, "__esModule", { value: true });
|
14 | var xstream_1 = require("xstream");
|
15 | var ScopeChecker_1 = require("./ScopeChecker");
|
16 | var utils_1 = require("./utils");
|
17 | var ElementFinder_1 = require("./ElementFinder");
|
18 | var SymbolTree_1 = require("./SymbolTree");
|
19 | var PriorityQueue_1 = require("./PriorityQueue");
|
20 | var fromEvent_1 = require("./fromEvent");
|
21 | exports.eventTypesThatDontBubble = [
|
22 | "blur",
|
23 | "canplay",
|
24 | "canplaythrough",
|
25 | "durationchange",
|
26 | "emptied",
|
27 | "ended",
|
28 | "focus",
|
29 | "load",
|
30 | "loadeddata",
|
31 | "loadedmetadata",
|
32 | "mouseenter",
|
33 | "mouseleave",
|
34 | "pause",
|
35 | "play",
|
36 | "playing",
|
37 | "ratechange",
|
38 | "reset",
|
39 | "scroll",
|
40 | "seeked",
|
41 | "seeking",
|
42 | "stalled",
|
43 | "submit",
|
44 | "suspend",
|
45 | "timeupdate",
|
46 | "unload",
|
47 | "volumechange",
|
48 | "waiting",
|
49 | ];
|
50 |
|
51 |
|
52 |
|
53 |
|
54 |
|
55 |
|
56 |
|
57 |
|
58 |
|
59 | var EventDelegator = (function () {
|
60 | function EventDelegator(rootElement$, isolateModule) {
|
61 | var _this = this;
|
62 | this.rootElement$ = rootElement$;
|
63 | this.isolateModule = isolateModule;
|
64 | this.virtualListeners = new SymbolTree_1.default(function (x) { return x.scope; });
|
65 | this.nonBubblingListenersToAdd = new Set();
|
66 | this.virtualNonBubblingListener = [];
|
67 | this.isolateModule.setEventDelegator(this);
|
68 | this.domListeners = new Map();
|
69 | this.domListenersToAdd = new Map();
|
70 | this.nonBubblingListeners = new Map();
|
71 | rootElement$.addListener({
|
72 | next: function (el) {
|
73 | if (_this.origin !== el) {
|
74 | _this.origin = el;
|
75 | _this.resetEventListeners();
|
76 | _this.domListenersToAdd.forEach(function (passive, type) {
|
77 | return _this.setupDOMListener(type, passive);
|
78 | });
|
79 | _this.domListenersToAdd.clear();
|
80 | }
|
81 | _this.nonBubblingListenersToAdd.forEach(function (arr) {
|
82 | _this.setupNonBubblingListener(arr);
|
83 | });
|
84 | },
|
85 | });
|
86 | }
|
87 | EventDelegator.prototype.addEventListener = function (eventType, namespace, options, bubbles) {
|
88 | var subject = xstream_1.default.never();
|
89 | var dest;
|
90 | var scopeChecker = new ScopeChecker_1.ScopeChecker(namespace, this.isolateModule);
|
91 | var shouldBubble = bubbles === undefined
|
92 | ? exports.eventTypesThatDontBubble.indexOf(eventType) === -1
|
93 | : bubbles;
|
94 | if (shouldBubble) {
|
95 | if (!this.domListeners.has(eventType)) {
|
96 | this.setupDOMListener(eventType, !!options.passive);
|
97 | }
|
98 | dest = this.insertListener(subject, scopeChecker, eventType, options);
|
99 | return subject;
|
100 | }
|
101 | else {
|
102 | var setArray_1 = [];
|
103 | this.nonBubblingListenersToAdd.forEach(function (v) { return setArray_1.push(v); });
|
104 | var found = undefined, index = 0;
|
105 | var length_1 = setArray_1.length;
|
106 | var tester = function (x) {
|
107 | var _sub = x[0], et = x[1], ef = x[2], _ = x[3];
|
108 | return eventType === et && utils_1.isEqualNamespace(ef.namespace, namespace);
|
109 | };
|
110 | while (!found && index < length_1) {
|
111 | var item = setArray_1[index];
|
112 | found = tester(item) ? item : found;
|
113 | index++;
|
114 | }
|
115 | var input_1 = found;
|
116 | var nonBubbleSubject_1;
|
117 | if (!input_1) {
|
118 | var finder = new ElementFinder_1.ElementFinder(namespace, this.isolateModule);
|
119 | dest = this.insertListener(subject, scopeChecker, eventType, options);
|
120 | input_1 = [subject, eventType, finder, dest];
|
121 | nonBubbleSubject_1 = subject;
|
122 | this.nonBubblingListenersToAdd.add(input_1);
|
123 | this.setupNonBubblingListener(input_1);
|
124 | }
|
125 | else {
|
126 | var sub = input_1[0];
|
127 | nonBubbleSubject_1 = sub;
|
128 | }
|
129 | var self_1 = this;
|
130 | var subscription_1 = null;
|
131 | return xstream_1.default.create({
|
132 | start: function (listener) {
|
133 | subscription_1 = nonBubbleSubject_1.subscribe(listener);
|
134 | },
|
135 | stop: function () {
|
136 | var _s = input_1[0], et = input_1[1], ef = input_1[2], _d = input_1[3];
|
137 | var elements = ef.call();
|
138 | elements.forEach(function (element) {
|
139 | var subs = element.subs;
|
140 | if (subs && subs[et]) {
|
141 | subs[et].unsubscribe();
|
142 | delete subs[et];
|
143 | }
|
144 | });
|
145 | self_1.nonBubblingListenersToAdd.delete(input_1);
|
146 | subscription_1.unsubscribe();
|
147 | }
|
148 | });
|
149 | }
|
150 | };
|
151 | EventDelegator.prototype.removeElement = function (element, namespace) {
|
152 | if (namespace !== undefined) {
|
153 | this.virtualListeners.delete(namespace);
|
154 | }
|
155 | var toRemove = [];
|
156 | this.nonBubblingListeners.forEach(function (map, type) {
|
157 | if (map.has(element)) {
|
158 | toRemove.push([type, element]);
|
159 | var subs_1 = element.subs;
|
160 | if (subs_1) {
|
161 | Object.keys(subs_1).forEach(function (key) {
|
162 | subs_1[key].unsubscribe();
|
163 | });
|
164 | }
|
165 | }
|
166 | });
|
167 | for (var i = 0; i < toRemove.length; i++) {
|
168 | var map = this.nonBubblingListeners.get(toRemove[i][0]);
|
169 | if (!map) {
|
170 | continue;
|
171 | }
|
172 | map.delete(toRemove[i][1]);
|
173 | if (map.size === 0) {
|
174 | this.nonBubblingListeners.delete(toRemove[i][0]);
|
175 | }
|
176 | else {
|
177 | this.nonBubblingListeners.set(toRemove[i][0], map);
|
178 | }
|
179 | }
|
180 | };
|
181 | EventDelegator.prototype.insertListener = function (subject, scopeChecker, eventType, options) {
|
182 | var relevantSets = [];
|
183 | var n = scopeChecker._namespace;
|
184 | var max = n.length;
|
185 | do {
|
186 | relevantSets.push(this.getVirtualListeners(eventType, n, true, max));
|
187 | max--;
|
188 | } while (max >= 0 && n[max].type !== 'total');
|
189 | var destination = __assign({}, options, { scopeChecker: scopeChecker,
|
190 | subject: subject, bubbles: !!options.bubbles, useCapture: !!options.useCapture, passive: !!options.passive });
|
191 | for (var i = 0; i < relevantSets.length; i++) {
|
192 | relevantSets[i].add(destination, n.length);
|
193 | }
|
194 | return destination;
|
195 | };
|
196 | |
197 |
|
198 |
|
199 |
|
200 | EventDelegator.prototype.getVirtualListeners = function (eventType, namespace, exact, max) {
|
201 | if (exact === void 0) { exact = false; }
|
202 | var _max = max !== undefined ? max : namespace.length;
|
203 | if (!exact) {
|
204 | for (var i = _max - 1; i >= 0; i--) {
|
205 | if (namespace[i].type === 'total') {
|
206 | _max = i + 1;
|
207 | break;
|
208 | }
|
209 | _max = i;
|
210 | }
|
211 | }
|
212 | var map = this.virtualListeners.getDefault(namespace, function () { return new Map(); }, _max);
|
213 | if (!map.has(eventType)) {
|
214 | map.set(eventType, new PriorityQueue_1.default());
|
215 | }
|
216 | return map.get(eventType);
|
217 | };
|
218 | EventDelegator.prototype.setupDOMListener = function (eventType, passive) {
|
219 | var _this = this;
|
220 | if (this.origin) {
|
221 | var sub = fromEvent_1.fromEvent(this.origin, eventType, false, false, passive).subscribe({
|
222 | next: function (event) { return _this.onEvent(eventType, event, passive); },
|
223 | error: function () { },
|
224 | complete: function () { },
|
225 | });
|
226 | this.domListeners.set(eventType, { sub: sub, passive: passive });
|
227 | }
|
228 | else {
|
229 | this.domListenersToAdd.set(eventType, passive);
|
230 | }
|
231 | };
|
232 | EventDelegator.prototype.setupNonBubblingListener = function (input) {
|
233 | var _ = input[0], eventType = input[1], elementFinder = input[2], destination = input[3];
|
234 | if (!this.origin) {
|
235 | return;
|
236 | }
|
237 | var elements = elementFinder.call();
|
238 | if (elements.length) {
|
239 | var self_2 = this;
|
240 | elements.forEach(function (element) {
|
241 | var _a;
|
242 | var subs = element.subs;
|
243 | if (!subs || !subs[eventType]) {
|
244 | var sub = fromEvent_1.fromEvent(element, eventType, false, false, destination.passive).subscribe({
|
245 | next: function (ev) {
|
246 | return self_2.onEvent(eventType, ev, !!destination.passive, false);
|
247 | },
|
248 | error: function () { },
|
249 | complete: function () { },
|
250 | });
|
251 | if (!self_2.nonBubblingListeners.has(eventType)) {
|
252 | self_2.nonBubblingListeners.set(eventType, new Map());
|
253 | }
|
254 | var map = self_2.nonBubblingListeners.get(eventType);
|
255 | if (!map) {
|
256 | return;
|
257 | }
|
258 | map.set(element, { sub: sub, destination: destination });
|
259 | element.subs = __assign({}, subs, (_a = {}, _a[eventType] = sub, _a));
|
260 | }
|
261 | });
|
262 | }
|
263 | };
|
264 | EventDelegator.prototype.resetEventListeners = function () {
|
265 | var iter = this.domListeners.entries();
|
266 | var curr = iter.next();
|
267 | while (!curr.done) {
|
268 | var _a = curr.value, type = _a[0], _b = _a[1], sub = _b.sub, passive = _b.passive;
|
269 | sub.unsubscribe();
|
270 | this.setupDOMListener(type, passive);
|
271 | curr = iter.next();
|
272 | }
|
273 | };
|
274 | EventDelegator.prototype.putNonBubblingListener = function (eventType, elm, useCapture, passive) {
|
275 | var map = this.nonBubblingListeners.get(eventType);
|
276 | if (!map) {
|
277 | return;
|
278 | }
|
279 | var listener = map.get(elm);
|
280 | if (listener &&
|
281 | listener.destination.passive === passive &&
|
282 | listener.destination.useCapture === useCapture) {
|
283 | this.virtualNonBubblingListener[0] = listener.destination;
|
284 | }
|
285 | };
|
286 | EventDelegator.prototype.onEvent = function (eventType, event, passive, bubbles) {
|
287 | if (bubbles === void 0) { bubbles = true; }
|
288 | var cycleEvent = this.patchEvent(event);
|
289 | var rootElement = this.isolateModule.getRootElement(event.target);
|
290 | if (bubbles) {
|
291 | var namespace = this.isolateModule.getNamespace(event.target);
|
292 | if (!namespace) {
|
293 | return;
|
294 | }
|
295 | var listeners = this.getVirtualListeners(eventType, namespace);
|
296 | this.bubble(eventType, event.target, rootElement, cycleEvent, listeners, namespace, namespace.length - 1, true, passive);
|
297 | this.bubble(eventType, event.target, rootElement, cycleEvent, listeners, namespace, namespace.length - 1, false, passive);
|
298 | }
|
299 | else {
|
300 | this.putNonBubblingListener(eventType, event.target, true, passive);
|
301 | this.doBubbleStep(eventType, event.target, rootElement, cycleEvent, this.virtualNonBubblingListener, true, passive);
|
302 | this.putNonBubblingListener(eventType, event.target, false, passive);
|
303 | this.doBubbleStep(eventType, event.target, rootElement, cycleEvent, this.virtualNonBubblingListener, false, passive);
|
304 | event.stopPropagation();
|
305 | }
|
306 | };
|
307 | EventDelegator.prototype.bubble = function (eventType, elm, rootElement, event, listeners, namespace, index, useCapture, passive) {
|
308 | if (!useCapture && !event.propagationHasBeenStopped) {
|
309 | this.doBubbleStep(eventType, elm, rootElement, event, listeners, useCapture, passive);
|
310 | }
|
311 | var newRoot = rootElement;
|
312 | var newIndex = index;
|
313 | if (elm === rootElement) {
|
314 | if (index >= 0 && namespace[index].type === 'sibling') {
|
315 | newRoot = this.isolateModule.getElement(namespace, index);
|
316 | newIndex--;
|
317 | }
|
318 | else {
|
319 | return;
|
320 | }
|
321 | }
|
322 | if (elm.parentNode && newRoot) {
|
323 | this.bubble(eventType, elm.parentNode, newRoot, event, listeners, namespace, newIndex, useCapture, passive);
|
324 | }
|
325 | if (useCapture && !event.propagationHasBeenStopped) {
|
326 | this.doBubbleStep(eventType, elm, rootElement, event, listeners, useCapture, passive);
|
327 | }
|
328 | };
|
329 | EventDelegator.prototype.doBubbleStep = function (eventType, elm, rootElement, event, listeners, useCapture, passive) {
|
330 | if (!rootElement) {
|
331 | return;
|
332 | }
|
333 | this.mutateEventCurrentTarget(event, elm);
|
334 | listeners.forEach(function (dest) {
|
335 | if (dest.passive === passive && dest.useCapture === useCapture) {
|
336 | var sel = utils_1.getSelectors(dest.scopeChecker.namespace);
|
337 | if (!event.propagationHasBeenStopped &&
|
338 | dest.scopeChecker.isDirectlyInScope(elm) &&
|
339 | ((sel !== '' && elm.matches(sel)) ||
|
340 | (sel === '' && elm === rootElement))) {
|
341 | fromEvent_1.preventDefaultConditional(event, dest.preventDefault);
|
342 | dest.subject.shamefullySendNext(event);
|
343 | }
|
344 | }
|
345 | });
|
346 | };
|
347 | EventDelegator.prototype.patchEvent = function (event) {
|
348 | var pEvent = event;
|
349 | pEvent.propagationHasBeenStopped = false;
|
350 | var oldStopPropagation = pEvent.stopPropagation;
|
351 | pEvent.stopPropagation = function stopPropagation() {
|
352 | oldStopPropagation.call(this);
|
353 | this.propagationHasBeenStopped = true;
|
354 | };
|
355 | return pEvent;
|
356 | };
|
357 | EventDelegator.prototype.mutateEventCurrentTarget = function (event, currentTargetElement) {
|
358 | try {
|
359 | Object.defineProperty(event, "currentTarget", {
|
360 | value: currentTargetElement,
|
361 | configurable: true,
|
362 | });
|
363 | }
|
364 | catch (err) {
|
365 | console.log("please use event.ownerTarget");
|
366 | }
|
367 | event.ownerTarget = currentTargetElement;
|
368 | };
|
369 | return EventDelegator;
|
370 | }());
|
371 | exports.EventDelegator = EventDelegator;
|
372 |
|
\ | No newline at end of file |