Skip to content

Instantly share code, notes, and snippets.

@ryanflorence
Created September 16, 2012 22:16
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save ryanflorence/3734609 to your computer and use it in GitHub Desktop.
Save ryanflorence/3734609 to your computer and use it in GitHub Desktop.
TJ's EventEmitter in CoffeeScript
###
Initialize a new `Emitter`.
@api public
###
module.exports = Emitter = (obj) ->
return mixin(obj) if obj
@_callbacks = {}
###
Mixin the emitter properties.
@param {Object} obj
@return {Object}
@api private
###
mixin = (obj) ->
obj._callbacks = {}
for key of Emitter.prototype
obj[key] = Emitter::[key]
obj
###
Listen on the given `event` with `fn`.
@param {String} event
@param {Function} fn
@return {Emitter}
@api public
###
Emitter::on = (event, fn) ->
(@_callbacks[event] or= []).push fn
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::once = (event, fn) ->
once = =>
@off event, once
fn.apply this, arguments
fn._off = once
@on event, once
###
Remove the given callback for `event` or all
registered callbacks.
@param {String} event
@param {Function} fn
@return {Emitter}
@api public
###
Emitter::off = (event, fn) ->
callbacks = @_callbacks[event]
return this unless callbacks
# remove all handlers
if 1 is arguments.length
delete @_callbacks[event]
return this
# remove specific handler
i = callbacks.indexOf(fn._off or fn)
callbacks.splice i, 1 if ~i
this
###
Emit `event` with the given args.
@param {String} event
@param {Mixed} ...
@return {Emitter}
###
Emitter::emit = (event, args...) ->
callbacks = @_callbacks[event]
if callbacks
for callback in callbacks.slice 0
callback.apply(this, args)
this
###
Return array of callbacks for `event`.
@param {String} event
@return {Array}
@api public
###
Emitter::listeners = (event) ->
@_callbacks[event] or []
###
Check if this emitter has `event` handlers.
@param {String} event
@return {Boolean}
@api public
###
Emitter::hasListeners = (event) ->
!! @listeners(event).length
/**
* Expose `Emitter`.
*/
module.exports = Emitter;
/**
* Initialize a new `Emitter`.
*
* @api public
*/
function Emitter(obj) {
if (obj) return mixin(obj);
this._callbacks = {};
};
/**
* Mixin the emitter properties.
*
* @param {Object} obj
* @return {Object}
* @api private
*/
function mixin(obj) {
obj._callbacks = {};
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 = function(event, fn){
(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){
var self = this;
function on() {
self.off(event, on);
fn.apply(this, arguments);
}
fn._off = on;
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 = function(event, fn){
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 i = callbacks.indexOf(fn._off || fn);
if (~i) callbacks.splice(i, 1);
return this;
};
/**
* Emit `event` with the given args.
*
* @param {String} event
* @param {Mixed} ...
* @return {Emitter}
*/
Emitter.prototype.emit = function(event){
var args = [].slice.call(arguments, 1)
, callbacks = this._callbacks[event];
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){
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;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment