UNPKG

@inweb/eventemitter2

Version:

JavaScript event emitter

155 lines (136 loc) 5.34 kB
/////////////////////////////////////////////////////////////////////////////// // Copyright (C) 2002-2025, Open Design Alliance (the "Alliance"). // All rights reserved. // // This software and its documentation and related materials are owned by // the Alliance. The software may only be incorporated into application // programs owned by members of the Alliance, subject to a signed // Membership Agreement and Supplemental Software License Agreement with the // Alliance. The structure and organization of this software are the valuable // trade secrets of the Alliance and its suppliers. The software is also // protected by copyright law and international treaty provisions. Application // programs incorporating this software must include the following statement // with their copyright notices: // // This application incorporates Open Design Alliance software pursuant to a // license agreement with Open Design Alliance. // Open Design Alliance Copyright (C) 2002-2025 by Open Design Alliance. // All rights reserved. // // By use of this software, its documentation or related materials, you // acknowledge and accept the above terms. /////////////////////////////////////////////////////////////////////////////// /** * The event interface for {@link IEventEmitter}. */ export interface IEvent { /** * Event type. */ type: string; } /** * Event emitter interface. */ export interface IEventEmitter { /** * Registers a new listener for the event type. * * @param type - The type of event to listen to. * @param listener - The function that gets called when the event is fired. */ addEventListener(type: string, listener: (event: IEvent) => void): this; /** * Removes the listener for the event type. * * @param type - The type of the event that gets removed. * @param listener - The listener function that gets removed. */ removeEventListener(type: string, listener: (event: IEvent) => void): this; /** * If `type` is specified, removes all registered listeners for type, otherwise removes all registered * listeners. * * @param type - The type of the listener that gets removed. */ removeAllListeners(type?: string): this; /** * Fires the event. Calls each of the listeners registered for the event type `event.type`, in the * order they were registered. * * @param event - The event that gets fired. */ emitEvent(event: IEvent): boolean; // Node.js style, to emit custom eventsg /** * Registers a new listener for the event type. Alias to {@link addEventListener | addEventListener()} * * @param type - The type of event to listen to. * @param listener - The function that gets called when the event is fired. */ on(type: string, listener: (event: any) => void): this; /** * Removes the listener from an event type. Alias to * {@link removeEventListener | removeEventListener()}. * * @param type - The type of the event that gets removed. * @param listener - The listener function that gets removed. */ off(type: string, listener: (event: any) => void): this; /** * Fires the event. Alias to {@link emitEvent | emitEvent()}. * * @param type - The type of event that gets fired. * @param args - The event properties. */ emit(type: string | object, ...args: any[]): boolean; } /** * The minimal basic event that can be emitted by a {@link EventEmitter2}. */ export interface Event<T extends string = string> extends IEvent { /** * Event type. */ type: T; } /** * Event emitter for custom objects. */ export class EventEmitter2<EventMap extends Record<string, any> = Record<string, any>> implements IEventEmitter { private _listeners: Record<any, any[]> = {}; addEventListener<T extends keyof EventMap>(type: T, listener: (event: EventMap[T]) => void): this { if (this._listeners[type] === undefined) this._listeners[type] = []; this._listeners[type].push(listener); return this; } removeEventListener<T extends keyof EventMap>(type: T, listener: (event: EventMap[T]) => void): this { if (this._listeners[type] === undefined) return this; const listeners = this._listeners[type].filter((x: any) => x !== listener); if (listeners.length !== 0) this._listeners[type] = listeners; else delete this._listeners[type]; return this; } removeAllListeners<T extends keyof EventMap>(type?: T): this { if (type) delete this._listeners[type]; else this._listeners = {}; return this; } emitEvent<T extends keyof EventMap>(event: Event<Extract<T, string>> & EventMap[T]): boolean { if (this._listeners[event.type] === undefined) return false; const invoke = this._listeners[event.type].slice(); invoke.forEach((listener: any) => listener.call(this, event)); return true; } on(type: string, listener: (event: any) => void): this { return this.addEventListener(type as any, listener as any); } off(type: string, listener: (event: any) => void): this { return this.removeEventListener(type as any, listener as any); } emit(type: string | object, ...args: any[]): boolean { if (typeof type === "string") return this.emitEvent({ type, args } as any); else if (typeof type === "object") return this.emitEvent(type as any); else return false; } }