/////////////////////////////////////////////////////////////////////////////// // Copyright (C) 2002-2021, 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-2021 by Open Design Alliance. // All rights reserved. // // By use of this software, its documentation or related materials, you // acknowledge and accept the above terms. /////////////////////////////////////////////////////////////////////////////// import { IEvent, IEventEmitter } from "./IEventEmitter2"; /** * The minimal basic Event that can be emitted by a {@link EventEmitter2}. */ export interface Event extends IEvent { type: T; } /** * Event emitter for custom objects. */ export class EventEmitter2 = Record> implements IEventEmitter { private _listeners = undefined; /** * Registers a new listener for an 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: T, listener: (event: EventMap[T]) => void): this { if (this._listeners === undefined) this._listeners = {}; if (this._listeners[type] === undefined) this._listeners[type] = []; this._listeners[type].push(listener); return this; } /** * Removes the listener from an event type. * * @param type - The type of the listener that gets removed. * @param listener - The listener function that gets removed. */ removeEventListener(type: T, listener: (event: EventMap[T]) => void): this { if (this._listeners === undefined) return this; if (this._listeners[type] === undefined) return this; const listeners = this._listeners[type].filter((x) => x !== listener); this._listeners[type] = listeners.length === 0 ? undefined : listeners; return 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?: T): this { if (type) this._listeners[type] = undefined; else this._listeners = undefined; return 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: Event> & EventMap[T]): boolean { if (this._listeners === undefined) return false; if (this._listeners[event.type] === undefined) return false; const invoke = this._listeners[event.type].slice(); invoke.forEach((listener) => listener.call(this, event)); return true; } // Node.js style, to emit custom events /** * Alias to {@link EventEmitter2.addEventListener()} */ on(type: string, listener: (event: object) => void): this { return this.addEventListener(type as any, listener as any); } /** * Alias to {@link EventEmitter2.removeEventListener()}. */ off(type: string, listener: (event: object) => void): this { return this.removeEventListener(type as any, listener as any); } /** * Alias to {@link EventEmitter2.emitEvent()}. */ emit(event: string | object, ...args: any[]): boolean { if (typeof event === "string") return this.emitEvent({ type: event, args } as any); else if (typeof event === "object") return this.emitEvent(event as any); else return false; } }