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