# Yahoo! UI Library

### Event Utility

Yahoo! UI Library > event > EventProvider.js (source view)

    /**
     * EventProvider is designed to be used with YAHOO.augment to wrap
     * CustomEvents in an interface that allows events to be subscribed to
     * and fired by name.  This makes it possible for implementing code to
     * subscribe to an event that either has not been created yet, or will
     * not be created at all.
     *
     * @Class EventProvider
     */
    YAHOO.util.EventProvider = function() { };

    YAHOO.util.EventProvider.prototype = {

        /**
         * Private storage of custom events
         * @property __yui_events
         * @type Object[]
         * @private
         */
        __yui_events: null,

        /**
         * Private storage of custom event subscribers
         * @property __yui_subscribers
         * @type Object[]
         * @private
         */
        __yui_subscribers: null,

        /**
         * Subscribe to a CustomEvent by event type
         *
         * @method subscribe
         * @param p_type     {string}   the type, or name of the event
         * @param p_fn       {function} the function to exectute when the event fires
         * @param p_obj
         * @param p_obj      {Object}   An object to be passed along when the event
         *                              fires
         * @param p_override {boolean}  If true, the obj passed in becomes the
         *                              execution scope of the listener
         */
        subscribe: function(p_type, p_fn, p_obj, p_override) {

            this.__yui_events = this.__yui_events || {};
            var ce = this.__yui_events[p_type];

            if (ce) {
                ce.subscribe(p_fn, p_obj, p_override);
            } else {
                this.__yui_subscribers = this.__yui_subscribers || {};
                var subs = this.__yui_subscribers;
                if (!subs[p_type]) {
                    subs[p_type] = [];
                }
                subs[p_type].push(
                    { fn: p_fn, obj: p_obj, override: p_override } );
            }
        },

        /**
         * Unsubscribes the from the specified event
         * @method unsubscribe
         * @param p_type {string}   The type, or name of the event
         * @param p_fn   {Function} The function to execute
         * @param p_obj  {Object}   The custom object passed to subscribe (optional)
         * @return {boolean} true if the subscriber was found and detached.
         */
        unsubscribe: function(p_type, p_fn, p_obj) {
            this.__yui_events = this.__yui_events || {};
            var ce = this.__yui_events[p_type];
            if (ce) {
                return ce.unsubscribe(p_fn, p_obj);
            } else {
                return false;
            }
        },

        /**
         * Creates a new custom event of the specified type.  If a custom event
         * by that name already exists, it will not be re-created.  In either
         * case the custom event is returned.
         *
         * @method createEvent
         *
         * @param p_type {string} the type, or name of the event
         * @param p_config {object} optional config params.  Valid properties are:
         *
         *  <ul>
         *    <li>
         *      scope: defines the default execution scope.  If not defined
         *      the default scope will be this instance.
         *    </li>
         *    <li>
         *      silent: if true, the custom event will not generate log messages.
         *      This is false by default.
         *    </li>
         *    <li>
         *      onSubscribeCallback: specifies a callback to execute when the
         *      event has a new subscriber.  This will fire immediately for
         *      each queued subscriber if any exist prior to the creation of
         *      the event.
         *    </li>
         *  </ul>
         *
         *  @return {CustomEvent} the custom event
         *
         */
        createEvent: function(p_type, p_config) {

            this.__yui_events = this.__yui_events || {};
            var opts = p_config || {};
            var events = this.__yui_events;

            if (events[p_type]) {
                YAHOO.log("EventProvider: error, event already exists");
            } else {

                var scope  = opts.scope  || this;
                var silent = opts.silent || null;

                var ce = new YAHOO.util.CustomEvent(p_type, scope, silent,
                        YAHOO.util.CustomEvent.FLAT);
                events[p_type] = ce;

                if (opts.onSubscribeCallback) {
                    ce.subscribeEvent.subscribe(opts.onSubscribeCallback);
                }

                this.__yui_subscribers = this.__yui_subscribers || {};
                var qs = this.__yui_subscribers[p_type];

                if (qs) {
                    for (var i=0; i<qs.length; ++i) {
                        ce.subscribe(qs[i].fn, qs[i].obj, qs[i].override);
                    }
                }
            }

            return events[p_type];
        },

       /**
         * Fire a custom event by name.  The callback functions will be executed
         * from the scope specified when the event was created, and with the
         * following parameters:
         *   <ul>
         *   <li>The first argument fire() was executed with</li>
         *   <li>The custom object (if any) that was passed into the subscribe()
         *       method</li>
         *   </ul>
         * @method fireEvent
         * @param p_type    {string}  the type, or name of the event
         * @param arguments {Object*} an arbitrary set of parameters to pass to
         *                            the handler.
         * @return {boolean} the return value from CustomEvent.fire, or null if
         *                   the custom event does not exist.
         */
        fireEvent: function(p_type, arg1, arg2, etc) {

            this.__yui_events = this.__yui_events || {};
            var ce = this.__yui_events[p_type];

            if (ce) {
                var args = [];
                for (var i=1; i<arguments.length; ++i) {
                    args.push(arguments[i]);
                }
                return ce.fire.apply(ce, args);
            } else {
                YAHOO.log("EventProvider.fire could not find event: " + p_type);
                return null;
            }
        },

        /**
         * Returns true if the custom event of the provided type has been created
         * with createEvent.
         * @method hasEvent
         * @param type {string} the type, or name of the event
         */
        hasEvent: function(type) {
            if (this.__yui_events) {
                if (this.__yui_events[type]) {
                    return true;
                }
            }
            return false;
        }

    };

Copyright © 2006 Yahoo! Inc. All rights reserved.