UNPKG

2.27 kBJavaScriptView Raw
1const Event = require('./Event');
2
3const crawlUp = node =>
4 node.parentNode ||
5 (node.nodeType === node.DOCUMENT_NODE ? node.defaultView : null);
6
7const getHandler = (self, handler) =>
8 handler.handleEvent ?
9 e => handler.handleEvent(e) :
10 e => handler.call(self, e);
11
12const getOnce = (self, type, handler, options) =>
13 e => {
14 self.removeEventListener(type, handler, options);
15 getHandler(self, handler)(e);
16 };
17
18// interface EventTarget // https://dom.spec.whatwg.org/#eventtarget
19module.exports = class EventTarget {
20
21 static init(self) {
22 self._eventTarget = Object.create(null);
23 if (self instanceof EventTarget)
24 return;
25 const et = EventTarget.prototype;
26 self.addEventListener = et.addEventListener;
27 self.removeEventListener = et.removeEventListener;
28 self.dispatchEvent = et.dispatchEvent;
29 }
30
31 constructor() {
32 EventTarget.init(this);
33 }
34
35 addEventListener(type, handler, options) {
36 const listener = this._eventTarget[type] || (this._eventTarget[type] = {
37 handlers: [],
38 callbacks: []
39 });
40 const i = listener.handlers.indexOf(handler);
41 if (i < 0) {
42 listener.callbacks[listener.handlers.push(handler) - 1] =
43 options && options.once ?
44 getOnce(this, type, handler, options) :
45 getHandler(this, handler);
46 }
47 }
48
49 removeEventListener(type, handler, options) {
50 const listener = this._eventTarget[type];
51 if (listener) {
52 const i = listener.handlers.indexOf(handler);
53 if (-1 < i) {
54 listener.handlers.splice(i, 1);
55 listener.callbacks.splice(i, 1);
56 if (listener.handlers.length < 1) {
57 delete this._eventTarget[type];
58 }
59 }
60 }
61 }
62
63 dispatchEvent(event) {
64 const type = event.type;
65 let node = this;
66 if (!event.target) event.target = node;
67 if (!event.currentTarget) event.currentTarget = node;
68 event.eventPhase = Event.AT_TARGET;
69 do {
70 if (type in node._eventTarget) {
71 node._eventTarget[type].callbacks.some(
72 cb => (cb(event), event.cancelImmediateBubble)
73 );
74 }
75 event.eventPhase = Event.BUBBLING_PHASE;
76 } while (event.bubbles && !event.cancelBubble && (node = crawlUp(node)));
77 return !event.defaultPrevented;
78 }
79
80};