/** * * EventEmitter * @description Events emitter and handler with pre-cached and timed emitters * @author Fernando Costa * */ interface IEventEmitter{ listeners: any emitts: any[] emit(eventName: string, data: any): void timed(eventName: string, data, time: number): void registryListener(eventName: string, callback: ( data?: any) => void ): void on(eventName: string, callback: ( data?: any) => void , once: boolean): void once(eventName: string, callback: ( data?: any) => void ): void remove(eventName: string, callback: ( data?: any) => void ): void } /** * Class EventEmitter * @class */ class EventEmitter implements IEventEmitter{ /** * @description The events listeners * @type {Object} */ listeners: any = {} /** * @description Cached emitts * @type {array} */ emitts: any[] = [] /** * @description Emit and cache for future listeners * @param {stirng} eventName - The event indentifier * @param {mixin} data - Opitional data * @return {void} */ emit(eventName: string, data: any = false): void { if(typeof this.emitts[eventName] === 'undefined') this.emitts[eventName] = [] this.emitts[eventName].push(data); if(typeof this.listeners[eventName] !== 'undefined'){ let listenersLength = this.listeners[eventName].length; let count = 0; for(; count < listenersLength; ++count){ this.listeners[eventName][count].call(this, data ); } } } /** * @description Timed emitter * @param {string} eventName - The event indentifier * @param {mixin} data - Opitional data * @param {number} time - The time of delay * @return {void} */ timed(eventName: string, data = false, time: number): void { let _this = this; setTimeout(function(){ _this.emit(eventName, data); }, time) } /** * @description Register listener * @param {string} eventName - The event indentifier * @param {callback} callback - The callback handler * @return {void} */ registryListener(eventName: string, callback: ( data?: any) => void ): void { if(typeof this.listeners[eventName] === 'undefined') this.listeners[eventName] = []; this.listeners[eventName].push( callback ); } /** * @description Register listener * @param {string} eventName - The event indentifier * @param {callback} callback - The callback handler * @param {boolean} once - Check if is one-time execution * @return {void} */ on(eventName: string, callback: ( data?: any) => void , once: boolean = false): void { if(this.emitts.hasOwnProperty(eventName)){ let length = this.emitts[eventName].length; let count = 0; for(; count < length; ++count){ callback.call(this, this.emitts[eventName][count]); if(once) break; } if(!once) this.registryListener(eventName, callback); } else{ this.registryListener(eventName, callback); } } /** * @description One-time execution listener * @param {string} eventName - The event indentifier * @param {callback} callback - The callback handler * @return {void} */ once(eventName: string, callback: ( data?: any) => void ): void { this.on(eventName, function _once(data){ callback.call(this, data); this.remove(eventName, _once); }, true) } /** * @description Remove listener * @param {string} eventName - The event indentifier * @param {callback} callback - The callback handler * @return {void} */ remove(eventName: string, callback: ( data?: any) => void ): void { if(this.listeners.hasOwnProperty(eventName)){ let index = this.listeners[eventName].indexOf( callback ); if (index > -1) { this.listeners[eventName].splice(index, 1); } } } }