This repository has been archived by the owner on Dec 5, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 5
/
index.js
109 lines (93 loc) · 2.69 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import {defineProperty, findIndex, G, WeakMap} from './poorlyfills.js';
let EventTarget = G.EventTarget;
try {
new EventTarget;
} catch(e) {
EventTarget = (() => {
// used to relate instances to listeners
const wm = new WeakMap;
// get listeners or relate them once to the instance
const get = self => wm.get(self) || set(self);
const set = self => {
const dictionary = new Null;
wm.set(self, dictionary);
return dictionary;
};
// define values as configurable
const define = (where, what) => {
for (const key in what) {
defineProperty(where, key, {
configurable: true,
value: what[key]
});
}
};
// no need to transpile here, it's a very simple class
function EventTarget() {}
// EventTarget "class" definition
define(
EventTarget.prototype,
{
addEventListener,
dispatchEvent,
removeEventListener
}
);
// dispatch event for each listener
function dispatch(info) {
const options = info.options;
if (options && options.once) {
removeEventListener.call(
info.target,
this.type, info.listener, info.options
);
}
if (typeof info.listener === 'function') {
info.listener.call(info.target, this);
} else {
info.listener.handleEvent(this);
}
}
// search for a registered listener
function registered(info) {
return this === info.listener;
}
// public methods
function addEventListener(type, listener, options) {
const secret = get(this);
const listeners = secret[type] || (secret[type] = []);
if (findIndex.call(listeners, registered, listener) < 0) {
listeners.push({target: this, listener, options});
}
}
function dispatchEvent(event) {
const secret = get(this);
const listeners = secret[event.type];
if (listeners) {
define(event, {
currentTarget: this,
target: this
});
listeners.forEach(dispatch, event);
delete event.currentTarget;
delete event.target;
}
return true;
}
// used both as public and private method,
// to avoid method pollution/interception of private listeners
function removeEventListener(type, listener, options) {
const secret = get(this);
const listeners = secret[type];
if (listeners) {
const i = findIndex.call(listeners, registered, listener);
if (-1 < i) listeners.splice(i, 1);
}
}
// private "class"
function Null() {}
Null.prototype = Object.create(null);
return EventTarget;
})();
}
export default EventTarget;