/
MultiTargetEventListenerManager.ts
90 lines (80 loc) · 2.96 KB
/
MultiTargetEventListenerManager.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
import TargetEventListeners from './TargetEventListeners';
/**
* MultiTargetEventListenerManager allows you to add event listeners to multiple
* HTML elements (targets) with support for event types with namespace,
* allow removing events without having to pass a callback and makes it possible
* to remove all event lsiteners from all HTML elements in a much simpler avoiding
* leaving listeners behind which would result in memory leaks.
*
* @example
* Adding and removing event listeners
* ```javascript
* const eventListenerManager = new MultiTargetEventListenerManager()
* const element1 = document.getElementById('foo');
* const element2 = document.getElementById('bar');
* const mouseoverCallback = () => { };
* const mouseoutCallback = () => { };
* const dragCallback = () => { };
*
* eventListenerManager.addEventListener(element1, 'mouseover', mouseoverCallback);
* eventListenerManager.addEventListener(element1, 'mouseout', mouseoutCallback);
*
* eventListenerManager.addEventListener(element2, 'voi.mousemove', dragCallback);
* eventListenerManager.addEventListener(element2, 'voi.drag', dragCallback);
* eventListenerManager.addEventListener(element2, 'voi.mouseup', () => {
* // do not need to store a reference of this function
* }));
*
* // Removes a specific event listener from element2
* eventListenerManager.removeEventListener(element2, 'voi.mousemove', dragCallback)
*
* // Removes all "mouseup" event listeners added to "voi" namespace on element2
* eventListenerManager.removeEventListener(element2, 'voi.mouseup')
*
* // Removes all event listeners added to element1 and element2
* eventListenerManager.reset();
* ```
*/
class MultiTargetEventListenerManager {
private _targetsEventListeners = new Map<EventTarget, TargetEventListeners>();
public addEventListener(
target: EventTarget,
type: string,
callback: EventListener,
options?: AddEventListenerOptions
) {
let eventListeners = this._targetsEventListeners.get(target);
if (!eventListeners) {
eventListeners = new TargetEventListeners(target);
this._targetsEventListeners.set(target, eventListeners);
}
eventListeners.addEventListener(type, callback, options);
}
public removeEventListener(
target: EventTarget,
type: string,
callback?: EventListener,
options?: EventListenerOptions
) {
const eventListeners = this._targetsEventListeners.get(target);
if (!eventListeners) {
return;
}
eventListeners.removeEventListener(type, callback, options);
if (eventListeners.isEmpty) {
this._targetsEventListeners.delete(target);
}
}
public reset() {
Array.from(this._targetsEventListeners.entries()).forEach(
([target, targetEventListeners]) => {
targetEventListeners.reset();
this._targetsEventListeners.delete(target);
}
);
}
}
export {
MultiTargetEventListenerManager as default,
MultiTargetEventListenerManager,
};