synthetic-event
Version:
A collection of base classes for custom events and event targets.
132 lines (130 loc) • 3.94 kB
JavaScript
/**
* synthetic-event v2.0.0 build Sat Jan 10 2026
* https://github.com/vanruesc/synthetic-event
* Copyright 2026 Raoul van Rüschen
* @license Zlib
*/
// src/EventTarget.ts
var EventTarget = class {
/**
* A collection of event listener functions.
*/
listenerFunctions;
/**
* A collection of event listener objects.
*/
listenerObjects;
/**
* Constructs a new event target.
*/
constructor() {
this.listenerFunctions = /* @__PURE__ */ new Map();
this.listenerObjects = /* @__PURE__ */ new Map();
}
/**
* 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, listener) {
if (typeof listener === "function") {
if (this.listenerFunctions.has(type)) {
const listeners = this.listenerFunctions.get(type);
listeners.add(listener);
} else {
const listeners = /* @__PURE__ */ new Set([listener]);
this.listenerFunctions.set(type, listeners);
}
return;
}
if (this.listenerObjects.has(type)) {
const listeners = this.listenerObjects.get(type);
listeners.add(listener);
} else {
const listeners = /* @__PURE__ */ new Set([listener]);
this.listenerObjects.set(type, listeners);
}
}
/**
* 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.
*/
hasEventListener(type, listener) {
if (typeof listener === "function") {
if (!this.listenerFunctions.has(type)) {
return false;
}
const listeners2 = this.listenerFunctions.get(type);
return listeners2.has(listener);
}
if (!this.listenerObjects.has(type)) {
return false;
}
const listeners = this.listenerObjects.get(type);
return listeners.has(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, listener) {
if (typeof listener === "function") {
if (!this.listenerFunctions.has(type)) {
return;
}
const listeners2 = this.listenerFunctions.get(type);
if (listeners2.delete(listener) && listeners2.size === 0) {
this.listenerFunctions.delete(type);
}
return;
}
if (!this.listenerObjects.has(type)) {
return;
}
const listeners = this.listenerObjects.get(type);
if (listeners.delete(listener) && listeners.size === 0) {
this.listenerObjects.delete(type);
}
}
/**
* Dispatches an event at the specified event target, invoking the affected event listeners in the appropriate order.
*
* Event listeners can safely be added and removed while an event is being dispatched.
*
* @see https://262.ecma-international.org/#sec-map.prototype.foreach for more information on the iteration behavior.
* @param event - The event to dispatch.
* @param target - An event target.
*/
dispatchEvent(event, target = this) {
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);
}
}
}
/**
* Removes all listeners.
*/
clearEventListeners() {
this.listenerFunctions.clear();
this.listenerObjects.clear();
}
};
export {
EventTarget
};