Skip to content

Instantly share code, notes, and snippets.

@carlosascari
Last active January 24, 2016 23:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save carlosascari/74d5e6e63b18896d0b16 to your computer and use it in GitHub Desktop.
Save carlosascari/74d5e6e63b18896d0b16 to your computer and use it in GitHub Desktop.
Function that allows any object to function as a synchronous Event Emitter.
/**
* Provides an EventEmitter Trait
*
* USAGE @example
*
* function YourClass(){
* EventEmitterTrait(this) // or any object
* }
*
* var yourObject = new YourClass()
*
* ### Exposes the following properties:
*
* <yourObject> yourObject.on(String, Function)
* Add an event handler
*
* <yourObject> yourObject.off(String, [Function])
* Remove an event handler, or all handlers if the callback is
* not specified.
*
* <yourObject> yourObject.one(String, Function)
* Add an event handler that will remove itself upon executing.
*
* <yourObject> yourObject.emit(String, ...)
* Emit an event, all registered callbacks will be executed in sync
* with the handlers registered first, being executed first. Any argument
* after the eventName (first argument) is passed to the event handler(s).
*
* <yourObject> yourObject.clearEvents()
* Remove all event handlers
*
* <Object> yourObject.__events__
* All registered events
*
* @module Traits
* @submodule EventEmitterTrait
*/
var EventEmitterTrait = (function () {
/**
* @private
* @method isArray
* @param object {Mixed}
* @return Boolean
*/
function isArray (object)
{
return object && Object.prototype.toString.call(object) === '[object Array]'
}
/**
* @method EventEmitterTrait
* @param instance {Object}
* @return Object
*/
function EventEmitterTrait (instance) {
/**
* @private
* @property events
* @type Object
*/
var events = {}
/**
* @method on
* @param eventName {String}
* @param callback {Function}
* @return this
*/
Object.defineProperty(instance, 'on', {
configurable: false, enumerable: true,
value: function EventEmitterTrait__on (eventName, callback) {
if (typeof callback !== 'function')
{
throw new Error('callback must be a Function')
}
if (isArray(events[eventName]))
{
events[eventName].push(callback)
}
else
{
events[eventName] = [callback]
}
return instance
}
})
/**
* @method off
* @param eventName {String}
* @param [callback] {Function}
* @return this
*/
Object.defineProperty(instance, 'off', {
configurable: false, enumerable: true,
value: function EventEmitterTrait__off (eventName, callback) {
if (events[eventName] && events[eventName].length)
{
if (typeof callback === 'function')
{
var index = events[eventName].indexOf(callback)
if (index !== -1)
{
events[eventName].splice(index, 1)
}
}
else
{
events[eventName] = []
}
}
return instance
}
})
/**
* @method one
* @param eventName {String}
* @param callback {Function}
* @return this
*/
Object.defineProperty(instance, 'one', {
configurable: false, enumerable: true,
value: function EventEmitterTrait__one (eventName, callback) {
function _on (){
callback.apply(callback, arguments)
setTimeout(_off, 0)
}
function _off (){
instance.off(eventName, _on)
}
instance.on(eventName, _on)
return instance
}
})
/**
* @method emit
* @param eventName {String}
* @param [...] {Mixed}
* @return this
*/
Object.defineProperty(instance, 'emit', {
configurable: false, enumerable: true,
value: function EventEmitterTrait__emit (eventName) {
if (events[eventName] && events[eventName].length)
{
var args = Array.prototype.slice.call(arguments, 1)
var count = events[eventName].length
for (var i = 0; i < count; i++)
{
if (events[eventName][i])
{
events[eventName][i].apply(instance, args)
}
}
}
return instance
}
})
/**
* @method clearEvents
* @return this
*/
Object.defineProperty(instance, 'clearEvents', {
configurable: false, enumerable: true,
value: function EventEmitterTrait__clearEvents () {
var eventNames = Object.keys(events)
for (var i = 0, l = eventNames.length; i < l; i++)
{
instance.off(eventNames[i])
}
return instance
}
})
Object.defineProperty(instance, '__events__', {
configurable: false, enumerable: false,
get: function EventEmitterTrait__get___events__ () {
return events
}
})
}
return EventEmitterTrait
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment