Source: EventEmitter.js

Source: EventEmitter.js

/**
 * 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;
}