This repository has been archived by the owner on Jul 20, 2023. It is now read-only.
/
EventTarget.ts
126 lines (79 loc) · 2.54 KB
/
EventTarget.ts
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import { Event } from "./Event";
import { EventListener } from "./EventListener";
import { EventListenerObject } from "./EventListenerObject";
/**
* An event target that can dispatch events to registered listeners.
*/
export class EventTarget {
/**
* A collection of event listener functions.
*/
protected listenerFunctions: Map<string, Set<EventListener>>;
/**
* A collection of event listener objects.
*/
protected listenerObjects: Map<string, Set<EventListenerObject>>;
/**
* Constructs a new event target.
*/
constructor() {
this.listenerFunctions = new Map<string, Set<EventListener>>();
this.listenerObjects = new Map<string, Set<EventListenerObject>>();
}
/**
* Registers an event handler of a specific event type on the event target.
*
* @param type - The event type to listen for.
* @param listener - An event listener or callback.
*/
addEventListener(type: string, listener: EventListener | EventListenerObject) {
const m: Map<string, Set<EventListener | EventListenerObject>> = (typeof listener === "function") ?
this.listenerFunctions : this.listenerObjects;
if(m.has(type)) {
m.get(type).add(listener);
} else {
m.set(type, new Set([listener]));
}
}
/**
* Removes an event handler of a specific event type from the event target.
*
* @param type - The event type to remove.
* @param listener - The event listener to remove.
*/
removeEventListener(type: string, listener: EventListener | EventListenerObject) {
const m: Map<string, Set<EventListener | EventListenerObject>> = (typeof listener === "function") ?
this.listenerFunctions : this.listenerObjects;
if(m.has(type)) {
const listeners = m.get(type);
listeners.delete(listener);
if(listeners.size === 0) {
m.delete(type);
}
}
}
/**
* Dispatches an event at the specified event target, invoking the affected
* event listeners in the appropriate order.
*
* @param event - The event to dispatch.
* @param target - An event target.
*/
dispatchEvent(event: Event, target: EventTarget = this): void {
const listenerFunctions = target.listenerFunctions;
const listenerObjects = target.listenerObjects;
event.target = target;
if(listenerFunctions.has(event.type)) {
const listeners = listenerFunctions.get(event.type);
for(const listener of listeners) {
listener.call(target, event);
}
}
if(listenerObjects.has(event.type)) {
const listeners = listenerObjects.get(event.type);
for(const listener of listeners) {
listener.handleEvent(event);
}
}
}
}