API Docs for: v0.1.0
Show:

File: src\utils\EventEmitter.js

/**
 * Event emitter mixin. This will add emitter properties to an object so that
 * it can emit events, and have others listen for them. Based on
 * [node.js event emitter](https://github.com/joyent/node/blob/master/lib/events.js)
 *
 * @class EventEmitter
 * @constructor
 */
var EventEmitter = function() {
    this._events = this._events || {};

    /**
     * Registers a listener function to be run on an event occurance
     *
     * @method on
     * @param type {String} The event name to listen for
     * @param listener {Function} The function to execute when the event happens
     * @return {mixed} Returns itself.
     * @chainable
     */
    this.addEventListener = this.on = function(type, listener) {
        if(typeof listener !== 'function')
            throw new TypeError('listener must be a function');

        if(!this._events)
            this._events = {};

        // Optimize the case of one listener. Don't need the extra array object.
        if (!this._events[type])
            this._events[type] = listener;
        // If we've already got an array, just append.
        else if (typeof this._events[type] === 'object')
            this._events[type].push(listener);
        // Adding the second element, need to change to array.
        else
            this._events[type] = [this._events[type], listener];

        return this;
    };

    /**
     * Emits an event which will run all registered listeners for the event type
     *
     * @method emit
     * @param type {String} The event name to emit
     * @param data {mixed} Any data you want passed along with the event
     * @return {mixed} Returns itself.
     * @chainable
     */
    this.dispatchEvent = this.emit = function(type) {
        var handler, len, args, i, listeners;

        if(!this._events)
            this._events = {};

        handler = this._events[type];

        if(typeof handler === 'undefined')
            return false;

        if(typeof handler === 'function') {
            switch(arguments.length) {
                // fast cases
                case 1:
                    handler.call(this);
                    break;
                case 2:
                    handler.call(this, arguments[1]);
                    break;
                case 3:
                    handler.call(this, arguments[1], arguments[2]);
                    break;
                // slower
                default:
                    len = arguments.length;
                    args = new Array(len - 1);
                    for (i = 1; i < len; i++)
                        args[i - 1] = arguments[i];

                    handler.apply(this, args);
                    break;
            }
        } else if (typeof handler === 'object') {
            len = arguments.length;
            args = new Array(len - 1);
            for (i = 1; i < len; i++)
                args[i - 1] = arguments[i];

            listeners = handler.slice();
            len = listeners.length;
            for (i = 0; i < len; i++)
                listeners[i].apply(this, args);
        }

        return this;
    };

    /**
     * Removes a listener function for an event type
     *
     * @method off
     * @param type {String} The event name to emit
     * @param listener {Function} The function to remove
     * @return {mixed} Returns itself.
     * @chainable
     */
    this.removeEventListener = this.off = function(type, listener) {
        var list, position, length, i;

        if(typeof listener !== 'function')
            throw new TypeError('listener must be a function');

        if(!this._events[type])
            return this;

        list = this._events[type];
        length = list.length;
        position = -1;

        if(list === listener || (typeof list.listener === 'function' && list.listener === listener)) {
            this._events[type] = undefined;

        } else if(typeof list === 'object') {
            for(i = length; i-- > 0;) {
                if(list[i] === listener || (list[i].listener && list[i].listener === listener)) {
                    position = i;
                    break;
                }
            }

            if(position < 0)
                return this;

            if(list.length === 1) {
                list.length = 0;
                this._events[type] = undefined;
            } else {
                list.splice(position, 1);
            }
        }

        return this;
    };

    /**
     * Registers a one-time callback for an event
     *
     * @method once
     * @param type {String} The event name to listen for
     * @param listener {Function} the callback to call when the event occurs
     * @return {mixed} Returns itself.
     * @chainable
     */
    this.once = function(type, listener) {
        if(typeof listener !== 'function')
            throw new TypeError('listener must be a function');

        function g() {
            this.off(type, g);
            listener.apply(this, arguments);
        }

        g.listener = listener;
        this.on(type, g);

        return this;
    };
};

module.exports = EventEmitter;