bitmovin-player-ui
Version:
Bitmovin Player UI Framework
77 lines (67 loc) • 2.28 kB
text/typescript
type Listeners = [Node, EventListenerOrEventListenerObject, boolean | AddEventListenerOptions][];
/**
* Allows to subscribe to Node events.
*/
export class NodeEventSubscriber {
private readonly attachedListeners: Map<keyof HTMLElementEventMap, Listeners>;
constructor() {
this.attachedListeners = new Map();
}
private getEventListenersOfType(type: keyof HTMLElementEventMap): Listeners {
if (!this.attachedListeners.has(type)) {
this.attachedListeners.set(type, []);
}
return this.attachedListeners.get(type);
}
/**
* Adds the given event listener to the node.
*
* @param node The node to remove the event listener from
* @param type The event to listen to
* @param listener The listener to remove
* @param options The event listener options
*/
public on(
node: Node,
type: keyof HTMLElementEventMap,
listener: EventListenerOrEventListenerObject,
options?: boolean | AddEventListenerOptions,
): void {
node.addEventListener(type, listener, options);
this.getEventListenersOfType(type).push([node, listener, options]);
}
/**
* Removes the given event listener from the node.
*
* @param node The node to attach the event listener to
* @param type The event to listen to
* @param listener The listener to add
* @param options The event listener options
*/
public off(
node: Node,
type: keyof HTMLElementEventMap,
listener: EventListenerOrEventListenerObject,
options?: boolean | AddEventListenerOptions,
): void {
const listenersOfType = this.getEventListenersOfType(type);
const listenerIndex = listenersOfType.findIndex(([otherNode, otherListener, otherOptions]) => {
return otherNode === node && otherListener === listener && otherOptions === options;
});
node.removeEventListener(type, listener, options);
if (listenerIndex > -1) {
listenersOfType.splice(listenerIndex, 1);
}
}
/**
* Removes all attached event listeners.
*/
public release(): void {
this.attachedListeners.forEach((listenersOfType, type) => {
listenersOfType.forEach(([element, listener, options]) => {
this.off(element, type, listener, options);
});
});
this.attachedListeners.clear();
}
}