typed-event-target
Version:
EventTarget in the browser but with strong event typing.
71 lines (70 loc) • 2.72 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 ||
((typeof options !== 'undefined' || typeof listener.options !== 'undefined') &&
(typeof options !== typeof listener.options ||
(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();
}
}