File:EventDispatcher.js
/**
* @module cloudkid
*/
(function(global, undefined){
"use strict";
/**
* The EventDispatcher mirrors the functionality of AS3 and CreateJS's EventDispatcher,
* but is more robust in terms of inputs for the `on()` and `off()` methods.
*
* @class EventDispatcher
* @constructor
*/
var EventDispatcher = function(){},
// Reference to the prototype
p = EventDispatcher.prototype;
/**
* The collection of listeners
* @property {Array} _listeners
* @private
*/
p._listeners = [];
/**
* Dispatch an event
* @method trigger
* @param {String} type The event string name,
* @param {*} params Additional parameters
*/
p.trigger = function(type, params)
{
if (this._listeners[type] !== undefined)
{
var listeners = this._listeners[type];
for(var i = 0; i < listeners.length; i++)
{
listeners[i](params);
}
}
};
/**
* Add an event listener
*
* @method on
* @param {String|object} name The type of event (can be multiple events separated by spaces),
* or a map of events to handlers
* @param {Function|Array*} callback The callback function when event is fired or an array of callbacks.
* @return {EventDispatcher} Return this EventDispatcher
*/
p.on = function(name, callback)
{
// Callbacks map
if (type(name) === 'object')
{
for (var key in name)
{
if (name.hasOwnProperty(key))
{
this.on(key, name[key]);
}
}
}
// Callback
else if (type(callback) === 'function')
{
var names = name.split(' '), n = null;
for (var i = 0, nl = names.length; i < nl; i++)
{
n = names[i];
this._listeners[n] = this._listeners[n] || [];
if (this._callbackIndex(n, callback) === -1)
{
this._listeners[n].push(callback);
}
}
}
// Callbacks array
else if (type(callback) === 'array')
{
for (var f = 0, fl = callback.length; f < fl; f++)
{
this.on(name, callback[f]);
}
}
return this;
};
/**
* Remove the event listener
*
* @method off
* @param {String*} name The type of event string separated by spaces, if no name is specifed remove all listeners.
* @param {function|Array*} callback The listener function or collection of callback functions
*/
p.off = function(name, callback)
{
// remove all
if (name === undefined)
{
this._listeners = [];
}
// remove multiple callbacks
else if (type(callback) === 'array')
{
for (var f = 0, fl = callback.length; f < fl; f++)
{
this.off(name, callback[f]);
}
}
else
{
var names = name.split(' '), n = null;
for (var i = 0, nl = names.length; i < nl; i++)
{
n = names[i];
this._listeners[n] = this._listeners[n] || [];
// remove all by time
if (callback === undefined)
{
this._listeners[n].length = 0;
}
else
{
var index = this._callbackIndex(n, callback);
if (index !== -1)
{
this._listeners[name].splice(index, 1);
}
}
}
}
return this;
};
/**
* Return type of the value.
*
* @private
* @method type
* @param {*} value
* @return {String} The type
*/
function type(value)
{
if (value === null)
{
return String(value);
}
if (typeof value === 'object' || typeof value === 'function')
{
return Object.prototype.toString.call(value).match(/\s([a-z]+)/i)[1].toLowerCase() || 'object';
}
return typeof value;
}
/**
* Returns callback array index.
*
* @method _callbackIndex
* @private
* @param {String} name Event name.
* @param {Function} callback Function
* @return {Int} Callback array index, or -1 if isn't registered.
*/
p._callbackIndex = function(name, callback)
{
for (var i = 0, l = this._listeners[name].length; i < l; i++)
{
if (this._listeners[name][i] === callback)
{
return i;
}
}
return -1;
};
// Assign to the global spacing
namespace('cloudkid').EventDispatcher = EventDispatcher;
}(window));