Created
July 28, 2013 19:06
-
-
Save couto/6099712 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
define([ | |
//<validation> | |
'mout/lang/isString', | |
'mout/lang/isFunction', | |
'mout/lang/isBoolean', | |
//</validation> | |
'mout/lang/toArray' | |
], function ( | |
//<validation> | |
isString, | |
isFunction, | |
isBoolean, | |
//</validation> | |
toArray | |
) { | |
'use strict'; | |
/** | |
* clear all events from the instance | |
* | |
* @api private | |
* @param {EventEmitter} instance | |
* @return {EventEmitter} | |
*/ | |
var clearAll = function (instance) { | |
instance.__events = {}; | |
return instance; | |
}, | |
/** | |
* clear all events with the given name, from the instance | |
* | |
* @api private | |
* @param {String} name event name | |
* @param {EventEmitter} instance | |
* @return {EventEmitter} | |
*/ | |
clearName = function (name, instance) { | |
instance.__events[name] = []; | |
return instance; | |
}; | |
/** | |
* EventEmitter | |
* | |
* var emitter = new EventEmiiter(); | |
* | |
* emitter.on(superAwesomeEvent, function () { | |
* destroyTheWorld('zombies'); | |
* }); | |
* | |
* emitter.emit('superAwesomeEvent', 42, 'meaning of life') | |
* | |
* @constructor | |
*/ | |
function EventEmitter() { | |
this.__events = {}; | |
} | |
EventEmitter.prototype = { | |
/** | |
* on | |
* Add an event listener. If the ctx argument is a boolean (true) | |
* the event will only be called once. | |
* | |
* emitter.on('firsTime', function () { | |
* console.log('Called!') | |
* }, true); | |
* | |
* emitter.emit('firstTime'); // Called! | |
* emitter.emit('firstTime'); // undefined | |
* | |
* @param {String} name event name | |
* @param {Function} fn function that will be called | |
* @param {Boolean} [once] if true, the event will be removed after being called once | |
* @chainable | |
*/ | |
on: function (name, fn, once) { | |
//<validation> | |
if (!isString(name)) { | |
throw new TypeError('EventEmitter#on requires first argument to be a string.'); | |
} | |
if (!isFunction(fn)) { | |
throw new TypeError('EventEmitter#on requires second argument to be a function.'); | |
} | |
if (once && !isBoolean(once)) { | |
throw new TypeError('EventEmitter#on requires third argument to be a boolean, if given.'); | |
} | |
//</validation> | |
// Create an array to save all handlers for that one. | |
this.__events[name] = this.__events[name] || []; | |
// Save the handler to the array | |
this.__events[name].push({ | |
fn: fn, | |
once: !!once | |
}); | |
return this; | |
}, | |
/** | |
* off | |
* Remove an event listener | |
* | |
* @param {[type]} name [description] | |
* @param {Function} fn [description] | |
* @chainable | |
*/ | |
off: function (name, fn) { | |
var current = this.__events[name], | |
i = 0; | |
//<validation> | |
if (name && !isString(name)) { | |
throw new TypeError('EventEmitter#off requires first argument to be a string, if present.'); | |
} | |
if (fn && !isFunction(fn)) { | |
throw new TypeError('EventEmitter#off requires second argument to be a function, is present.'); | |
} | |
if (name && !current) { | |
throw new ReferenceError('EventEmitter#off requires event to exist before trying to remove it'); | |
} | |
//</validation> | |
// if no arguments are given, clear all events | |
if (!toArray(arguments).length) { return clearAll(this); } | |
// If no function is given, remove all listeners for the | |
// given name | |
if (!fn) { return clearName(name, this); } | |
// Go through all handlers for the current | |
// event, and call them with the given arguments | |
i = current.length - 1; | |
for (i; i >= 0; i -= 1) { | |
if (current[i].fn === fn) { | |
current.splice(i, 1); | |
} | |
} | |
return this; | |
}, | |
/** | |
* emit | |
* | |
* @param {String} name event name | |
* @param {Mixed} [args]* | |
* @chainable | |
*/ | |
emit: function (name, args) { | |
var current = this.__events[name], | |
i = 0, | |
len = 0; | |
//<validation> | |
if (!isString(name)) { | |
throw new TypeError('EventEmitter#emit requires first argument to be a string.'); | |
} | |
//</validation> | |
// Get all arguments | |
args = [].slice.call(arguments, 1); | |
if (current) { | |
len = current.length; | |
for (i; i < len; i += 1) { | |
current[i].fn.apply(this, args); | |
// Check if this function was marked as a run once only | |
if (current[i].once) { | |
this.off(name, current[i].fn); | |
// Since we removed a handler | |
// we need to adapt our counter and length | |
i -= 1; | |
len = current.length; | |
} | |
} | |
} | |
return this; | |
} | |
}; | |
return EventEmitter; | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment