176 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			176 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
 | 
						|
/**
 | 
						|
 * Expose `Emitter`.
 | 
						|
 */
 | 
						|
 | 
						|
if (typeof module !== 'undefined') {
 | 
						|
  module.exports = Emitter;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Initialize a new `Emitter`.
 | 
						|
 *
 | 
						|
 * @api public
 | 
						|
 */
 | 
						|
 | 
						|
function Emitter(obj) {
 | 
						|
  if (obj) return mixin(obj);
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
 * Mixin the emitter properties.
 | 
						|
 *
 | 
						|
 * @param {Object} obj
 | 
						|
 * @return {Object}
 | 
						|
 * @api private
 | 
						|
 */
 | 
						|
 | 
						|
function mixin(obj) {
 | 
						|
  for (var key in Emitter.prototype) {
 | 
						|
    obj[key] = Emitter.prototype[key];
 | 
						|
  }
 | 
						|
  return obj;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Listen on the given `event` with `fn`.
 | 
						|
 *
 | 
						|
 * @param {String} event
 | 
						|
 * @param {Function} fn
 | 
						|
 * @return {Emitter}
 | 
						|
 * @api public
 | 
						|
 */
 | 
						|
 | 
						|
Emitter.prototype.on =
 | 
						|
Emitter.prototype.addEventListener = function(event, fn){
 | 
						|
  this._callbacks = this._callbacks || {};
 | 
						|
  (this._callbacks['$' + event] = this._callbacks['$' + event] || [])
 | 
						|
    .push(fn);
 | 
						|
  return this;
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
 * Adds an `event` listener that will be invoked a single
 | 
						|
 * time then automatically removed.
 | 
						|
 *
 | 
						|
 * @param {String} event
 | 
						|
 * @param {Function} fn
 | 
						|
 * @return {Emitter}
 | 
						|
 * @api public
 | 
						|
 */
 | 
						|
 | 
						|
Emitter.prototype.once = function(event, fn){
 | 
						|
  function on() {
 | 
						|
    this.off(event, on);
 | 
						|
    fn.apply(this, arguments);
 | 
						|
  }
 | 
						|
 | 
						|
  on.fn = fn;
 | 
						|
  this.on(event, on);
 | 
						|
  return this;
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
 * Remove the given callback for `event` or all
 | 
						|
 * registered callbacks.
 | 
						|
 *
 | 
						|
 * @param {String} event
 | 
						|
 * @param {Function} fn
 | 
						|
 * @return {Emitter}
 | 
						|
 * @api public
 | 
						|
 */
 | 
						|
 | 
						|
Emitter.prototype.off =
 | 
						|
Emitter.prototype.removeListener =
 | 
						|
Emitter.prototype.removeAllListeners =
 | 
						|
Emitter.prototype.removeEventListener = function(event, fn){
 | 
						|
  this._callbacks = this._callbacks || {};
 | 
						|
 | 
						|
  // all
 | 
						|
  if (0 == arguments.length) {
 | 
						|
    this._callbacks = {};
 | 
						|
    return this;
 | 
						|
  }
 | 
						|
 | 
						|
  // specific event
 | 
						|
  var callbacks = this._callbacks['$' + event];
 | 
						|
  if (!callbacks) return this;
 | 
						|
 | 
						|
  // remove all handlers
 | 
						|
  if (1 == arguments.length) {
 | 
						|
    delete this._callbacks['$' + event];
 | 
						|
    return this;
 | 
						|
  }
 | 
						|
 | 
						|
  // remove specific handler
 | 
						|
  var cb;
 | 
						|
  for (var i = 0; i < callbacks.length; i++) {
 | 
						|
    cb = callbacks[i];
 | 
						|
    if (cb === fn || cb.fn === fn) {
 | 
						|
      callbacks.splice(i, 1);
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  // Remove event specific arrays for event types that no
 | 
						|
  // one is subscribed for to avoid memory leak.
 | 
						|
  if (callbacks.length === 0) {
 | 
						|
    delete this._callbacks['$' + event];
 | 
						|
  }
 | 
						|
 | 
						|
  return this;
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
 * Emit `event` with the given args.
 | 
						|
 *
 | 
						|
 * @param {String} event
 | 
						|
 * @param {Mixed} ...
 | 
						|
 * @return {Emitter}
 | 
						|
 */
 | 
						|
 | 
						|
Emitter.prototype.emit = function(event){
 | 
						|
  this._callbacks = this._callbacks || {};
 | 
						|
 | 
						|
  var args = new Array(arguments.length - 1)
 | 
						|
    , callbacks = this._callbacks['$' + event];
 | 
						|
 | 
						|
  for (var i = 1; i < arguments.length; i++) {
 | 
						|
    args[i - 1] = arguments[i];
 | 
						|
  }
 | 
						|
 | 
						|
  if (callbacks) {
 | 
						|
    callbacks = callbacks.slice(0);
 | 
						|
    for (var i = 0, len = callbacks.length; i < len; ++i) {
 | 
						|
      callbacks[i].apply(this, args);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return this;
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
 * Return array of callbacks for `event`.
 | 
						|
 *
 | 
						|
 * @param {String} event
 | 
						|
 * @return {Array}
 | 
						|
 * @api public
 | 
						|
 */
 | 
						|
 | 
						|
Emitter.prototype.listeners = function(event){
 | 
						|
  this._callbacks = this._callbacks || {};
 | 
						|
  return this._callbacks['$' + event] || [];
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
 * Check if this emitter has `event` handlers.
 | 
						|
 *
 | 
						|
 * @param {String} event
 | 
						|
 * @return {Boolean}
 | 
						|
 * @api public
 | 
						|
 */
 | 
						|
 | 
						|
Emitter.prototype.hasListeners = function(event){
 | 
						|
  return !! this.listeners(event).length;
 | 
						|
};
 |