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