typed-event-target
Version:
EventTarget in the browser but with strong event typing.
72 lines (71 loc) • 2.74 kB
JavaScript
import { filterOutIndexes } from '@augment-vir/common/dist/augments/array/filter.js';
/**
* An EventTarget sub-class with typing for allowed events.
*
* @category Main
*/
export class TypedEventTarget extends EventTarget {
setupListeners = [];
/**
* Get a count of all currently attached listeners. If a listener is removed, it will no longer
* be counted.
*/
getListenerCount() {
return this.setupListeners.length;
}
/**
* Add an event listener. Has the same API as the built-in `EventTarget.addEventListener` method
* but with added event types.
*/
addEventListener(type, callback, options) {
super.addEventListener(type, callback, options);
if (callback) {
this.setupListeners.push({ type, callback, options });
}
}
/**
* Dispatch a typed event. Has the same API as the built-in `EventTarget.dispatchEvent` method
* but with added event types.
*/
dispatchEvent(event) {
return super.dispatchEvent(event);
}
/**
* Remove an already-added event listener. Has the same API as the built-in
* `EventTarget.removeEventListener` method but with added event types.
*/
removeEventListener(type, callback, options) {
super.removeEventListener(type, callback, options);
const previouslyAddedListenerIndex = this.setupListeners.findIndex((listener) => {
if (listener.type !== type) {
return false;
}
if (typeof options !== 'undefined' || typeof listener.options !== 'undefined') {
if (typeof options !== typeof listener.options) {
return false;
}
if ((typeof listener.options === 'boolean' &&
typeof options === 'boolean' &&
options !== listener.options) ||
(typeof listener.options === 'object' &&
typeof options === 'object' &&
options.capture !== listener.options.capture)) {
return false;
}
}
return listener.callback === callback;
});
this.setupListeners = filterOutIndexes(this.setupListeners, [previouslyAddedListenerIndex]);
}
/** Remove all currently attached event listeners. */
removeAllEventListeners() {
this.setupListeners.forEach((listenerSetup) => {
super.removeEventListener(listenerSetup.type, listenerSetup.callback, listenerSetup.options);
});
this.setupListeners = [];
}
/** Remove all internal state to free up resources. */
destroy() {
this.removeAllEventListeners();
}
}