back to devpro   download
var Listener = (function () {

    /*! (C) Andrea Giammarchi - Mit Style */

    /**
     * A basic module with all functionalities we need to create listeners.
     * @author Andrea Giammarchi
     * @license Mit Style
     * @url http://webreflection.blogspot.com/2010/05/event-driven-application-and-most-basic.html
     */

    // helpers

    /**
     * Return the named listener, if any, or create a new named stack.
     * @param Object the generic instance that is implementing a Listener.
     * @param String the listener name
     * @returns Array the named listener
     */
    function _get(self, name) {
        return self[_hash][name] || _set(self[_hash], name);
    }

    /**
     * Create an Array and associate it with a certain listener name.
     * Ensure that indexOf method is attached (as privileged).
     * @param Object the Listener object
     * @param String the missing listener name
     * @returns Array the new stack with a privileged indexOf method
     */
    function _set(listener, name) {
        (listener[name] = []).indexOf = indexOf;
        return listener[name];
    }

    var

        /**
         * Native Array.prototype.indexOf or an optimized fallback.
         * @type Function
         * @name indexOf
         * @private
         */
        indexOf = Array.prototype.indexOf || function (callback) {
            for (var i = this.length; i-- && this[i] !== callback;) {}
            return i;
        },

        /**
         * A unique hash to avoid name clashes when Listener is used as mixin.
         * @type String
         * @private
         */
        _hash = "_" + (Math.random() + "_Listener").slice(2),

        /**
         * Used to cache last indexOf result in order to easily
         * perform operations over the listener stack.
         * @type Number
         * @private
         */
        _index,

        /**
         * Used to cache last used listener access to easily
         * perform common stack operations.
         * @type Array
         * @private
         */
        _listener
    ;

    /**
     * @name Listener
     * @type Object
     * @public
     * @module
     */
    return {

        /**
         * Create the listener object if it's not there
         */
        initListener: function () {
            this[_hash] || (this[_hash] = {});
        },

        /**
         * Add a listener if not there already.
         * @param String a generic listener name
         * @param Function callback to add
         */
        addListener: function (name, callback) {
            if (!this.hasListener(name, callback)) {
                _listener.push(callback);
            }
        },

        /**
         * Fire registered callbacks for a specific listener
         * following the same DOM logic.
         * The firing order is FIFO.
         * If there is no callback, nothing will be fired.
         * If a listener with the same name is added,
         * this will be fire next time.
         * If a listener with the same name is removed,
         * this won't be fired.
         * @param String a generic listener name
         * @param Function callback to add
         */
        fireListener: function (name, event) {
            for (var
                listener = _get(this, name).slice(),
                i = 0, length = listener.length,
                index, fire;
                i < length; ++i
            ) {
                index = _listener.indexOf(fire = listener[i]);
                if (-1 < index && index <= i) {
                    fire.call(this, event);
                }
            }
        },

        /**
         * Verify a listener for a specific name.
         * @param String a generic listener name
         * @param Function callback to verify
         * @returns Boolean true if the listener has been added before.
         */
        hasListener: function (name, callback) {
            return -1 < (_index = (_listener = _get(this, name)).indexOf(callback));
        },

        /**
         * Remove a listener if added before.
         * @param String a generic listener name
         * @param Function callback to remove
         */
        removeListener: function (name, callback) {
            if (this.hasListener(name, callback)) {
                _listener.splice(_index, 1);
            }
        }
    };

}());
back to devpro   download
Creative Commons License