/** * This class allows to emit events like node.js. * Basically it's equivalent to node.js EventEmitter. * @constructor */ function EventEmitter() { this._listeners = {}; this._onces = {}; this._thisObjs = {}; } /** * Registers a listener. * @param event {String} - The name of the event. * @param listener {Function} - The function to be triggered. */ EventEmitter.prototype.on = function(event, listener, thisObj) { if(this._listeners[event] == null) { this._listeners[event] = []; } if(this._onces[event] == null) { this._onces[event] = []; } if(this._thisObjs[event] == null) { this._thisObjs[event] = []; } this._listeners[event].push(listener); this._thisObjs[event].push(thisObj); } /** * Registers a one-time listener. * The listener will be removed after being triggered once. * @param event {String} - The name of the event. * @param listener {Function} - The function to be triggered. */ EventEmitter.prototype.once = function(event, listener, thisObj) { this.on(event, listener, thisObj); this._onces[event].push(listener); } /** * Removes the listener. * @param event {String} - The name of the event. * @param listener {Function} - The function to be removed. */ EventEmitter.prototype.removeListener = function(event, listener) { if(this._listeners[event] == null) return; var idx = this._listeners[event].indexOf(listener); if(idx == -1) return; this._listeners[event].splice(idx, 1); this._thisObjs[event].splice(idx, 1); if(this._onces[event] == null) return; var idx = this._onces[event].indexOf(listener); if(idx == -1) return; this._onces[event].splice(idx, 1); } /** * Removes all the listener with specified event type. * If event parameter is not set, it will remove all the listener of all types. * @param [event] {String} - The name of the event. */ EventEmitter.prototype.removeAllListeners = function(event) { if(event) { this._listeners[event] = []; this._onces[event] = []; this._thisObjs[event] = []; } else { this._listeners = {}; this._onces = {}; this._thisObjs = {}; } } /** * Returns the array of listeners with specified event type. * @param event {String} - The name of the event. * @returns {Array} An array holding event listeners. */ EventEmitter.prototype.listeners = function(event) { var array = this._listeners[event]; if(!array) return []; return array; } /** * Emits the event. * This will trigger all the listener with that event type. * You can supply listener function's arguments by appending * arguments after the 'event' parameter. * @param event {String} - The name of the event. * @param args... - Arguments to supply to listeners. */ EventEmitter.prototype.emit = function(event) { var args = []; for(var i = 1; i < arguments.length; ++i) { args.push(arguments[i]); } var array = this._listeners[event]; var onceArray = this._onces[event]; var thisArray = this._thisObjs[event]; if(!array) return; for(var i = 0; i < array.length; ++i) { var entry = array[i]; entry.apply(thisArray[i], args); var onceIdx = onceArray.indexOf(entry); if(onceIdx != -1) { array.splice(i, 1); thisArray.splice(i, 1); onceArray.splice(onceIdx, 1); i --; } } } if(typeof module !== 'undefined') { module.exports = EventEmitter; }