Skip to content

Commit

Permalink
Added guillermo's EventEmitter. Closes ladjs#16
Browse files Browse the repository at this point in the history
  • Loading branch information
tj committed Dec 22, 2011
1 parent e31089f commit b735dcb
Showing 1 changed file with 146 additions and 25 deletions.
171 changes: 146 additions & 25 deletions lib/events.js
@@ -1,55 +1,176 @@

/*!
* EventEmitter
* Copyright (c) 2011 TJ Holowaychuk <tj@vision-media.ca>
* MIT Licensed
/**
* Module exports.
*/

/**
* Check if `obj` is an array.
*/

// TODO: own library, since tons of my libs use this :D
function isArray(obj) {
return '[object Array]' == {}.toString.call(obj);
}

/**
* Slice reference.
* Event emitter constructor.
*
* @api public.
*/

var slice = [].slice;
function EventEmitter(){};

/**
* EventEmitter.
* Adds a listener.
*
* @api public
*/

function EventEmitter() {
this.callbacks = {};
EventEmitter.prototype.on = function (name, fn) {
if (!this.$events) {
this.$events = {};
}

if (!this.$events[name]) {
this.$events[name] = fn;
} else if (isArray(this.$events[name])) {
this.$events[name].push(fn);
} else {
this.$events[name] = [this.$events[name], fn];
}

return this;
};

EventEmitter.prototype.addListener = EventEmitter.prototype.on;

/**
* Listen on the given `event` with `fn`.
* Adds a volatile listener.
*
* @param {String} event
* @param {Function} fn
* @api public
*/

EventEmitter.prototype.on = function(event, fn){
(this.callbacks[event] = this.callbacks[event] || [])
.push(fn);
EventEmitter.prototype.once = function (name, fn) {
var self = this;

function on () {
self.removeListener(name, on);
fn.apply(this, arguments);
};

on.listener = fn;
this.on(name, on);

return this;
};

/**
* Emit `event` with the given args.
* Removes a listener.
*
* @param {String} event
* @param {Mixed} ...
* @api public
*/

EventEmitter.prototype.emit = function(event){
var args = slice.call(arguments, 1)
, callbacks = this.callbacks[event];
EventEmitter.prototype.removeListener = function (name, fn) {
if (this.$events && this.$events[name]) {
var list = this.$events[name];

if (callbacks) {
for (var i = 0, len = callbacks.length; i < len; ++i) {
callbacks[i].apply(this, args);
if (isArray(list)) {
var pos = -1;

for (var i = 0, l = list.length; i < l; i++) {
if (list[i] === fn || (list[i].listener && list[i].listener === fn)) {
pos = i;
break;
}
}

if (pos < 0) {
return this;
}

list.splice(pos, 1);

if (!list.length) {
delete this.$events[name];
}
} else if (list === fn || (list.listener && list.listener === fn)) {
delete this.$events[name];
}
}

return this;
};

/**
* Removes all listeners for an event.
*
* @api public
*/

EventEmitter.prototype.removeAllListeners = function (name) {
if (name === undefined) {
this.$events = {};
return this;
}

if (this.$events && this.$events[name]) {
this.$events[name] = null;
}

return this;
};

/**
* Gets all listeners for a certain event.
*
* @api publci
*/

EventEmitter.prototype.listeners = function (name) {
if (!this.$events) {
this.$events = {};
}

if (!this.$events[name]) {
this.$events[name] = [];
}

if (!isArray(this.$events[name])) {
this.$events[name] = [this.$events[name]];
}

return this.$events[name];
};

/**
* Emits an event.
*
* @api public
*/

EventEmitter.prototype.emit = function (name) {
if (!this.$events) {
return false;
}

var handler = this.$events[name];

if (!handler) {
return false;
}

var args = [].slice.call(arguments, 1);

if ('function' == typeof handler) {
handler.apply(this, args);
} else if (isArray(handler)) {
var listeners = handler.slice();

for (var i = 0, l = listeners.length; i < l; i++) {
listeners[i].apply(this, args);
}
} else {
return false;
}

return true;
};

0 comments on commit b735dcb

Please sign in to comment.