Show:
                            /**
                             * Support for Widget UI Events (Custom Events fired by the widget, which wrap the underlying DOM events - e.g. widget:click, widget:mousedown)
                             *
                             * @module widget
                             * @submodule widget-uievents
                             */
                            
                            var BOUNDING_BOX = "boundingBox",
                                Widget = Y.Widget,
                                RENDER = "render",
                                L = Y.Lang,
                                EVENT_PREFIX_DELIMITER = ":",
                            
                                //  Map of Node instances serving as a delegation containers for a specific
                                //  event type to Widget instances using that delegation container.
                                _uievts = Y.Widget._uievts = Y.Widget._uievts || {};
                            
                            Y.mix(Widget.prototype, {
                            
                                /**
                                 * Destructor logic for UI event infrastructure,
                                 * invoked during Widget destruction.
                                 *
                                 * @method _destroyUIEvents
                                 * @for Widget
                                 * @private
                                 */
                                _destroyUIEvents: function() {
                            
                                    var widgetGuid = Y.stamp(this, true);
                            
                                    Y.each(_uievts, function (info, key) {
                                        if (info.instances[widgetGuid]) {
                                            //  Unregister this Widget instance as needing this delegated
                                            //  event listener.
                                            delete info.instances[widgetGuid];
                            
                                            //  There are no more Widget instances using this delegated
                                            //  event listener, so detach it.
                            
                                            if (Y.Object.isEmpty(info.instances)) {
                                                info.handle.detach();
                            
                                                if (_uievts[key]) {
                                                    delete _uievts[key];
                                                }
                                            }
                                        }
                                    });
                                },
                            
                                /**
                                 * Map of DOM events that should be fired as Custom Events by the
                                 * Widget instance.
                                 *
                                 * @property UI_EVENTS
                                 * @for Widget
                                 * @type Object
                                 */
                                UI_EVENTS: Y.Node.DOM_EVENTS,
                            
                                /**
                                 * Returns the node on which to bind delegate listeners.
                                 *
                                 * @method _getUIEventNode
                                 * @for Widget
                                 * @protected
                                 */
                                _getUIEventNode: function () {
                                    return this.get(BOUNDING_BOX);
                                },
                            
                                /**
                                 * Binds a delegated DOM event listener of the specified type to the
                                 * Widget's outtermost DOM element to facilitate the firing of a Custom
                                 * Event of the same type for the Widget instance.
                                 *
                                 * @method _createUIEvent
                                 * @for Widget
                                 * @param type {String} String representing the name of the event
                                 * @private
                                 */
                                _createUIEvent: function (type) {
                            
                                    var uiEvtNode = this._getUIEventNode(),
                                        key = (Y.stamp(uiEvtNode) + type),
                                        info = _uievts[key],
                                        handle;
                            
                                    //  For each Node instance: Ensure that there is only one delegated
                                    //  event listener used to fire Widget UI events.
                            
                                    if (!info) {
                            
                                        handle = uiEvtNode.delegate(type, function (evt) {
                            
                                            var widget = Widget.getByNode(this);
                            
                                            // Widget could be null if node instance belongs to
                                            // another Y instance.
                            
                                            if (widget) {
                                                if (widget._filterUIEvent(evt)) {
                                                    widget.fire(evt.type, { domEvent: evt });
                                                }
                                            }
                            
                                        }, "." + Y.Widget.getClassName());
                            
                                        _uievts[key] = info = { instances: {}, handle: handle };
                                    }
                            
                                    //  Register this Widget as using this Node as a delegation container.
                                    info.instances[Y.stamp(this)] = 1;
                                },
                            
                                /**
                                 * This method is used to determine if we should fire
                                 * the UI Event or not. The default implementation makes sure
                                 * that for nested delegates (nested unrelated widgets), we don't
                                 * fire the UI event listener more than once at each level.
                                 *
                                 * <p>For example, without the additional filter, if you have nested
                                 * widgets, each widget will have a delegate listener. If you
                                 * click on the inner widget, the inner delegate listener's
                                 * filter will match once, but the outer will match twice
                                 * (based on delegate's design) - once for the inner widget,
                                 * and once for the outer.</p>
                                 *
                                 * @method _filterUIEvent
                                 * @for Widget
                                 * @param {DOMEventFacade} evt
                                 * @return {boolean} true if it's OK to fire the custom UI event, false if not.
                                 * @private
                                 *
                                 */
                                _filterUIEvent: function(evt) {
                                    // Either it's hitting this widget's delegate container (and not some other widget's),
                                    // or the container it's hitting is handling this widget's ui events.
                                    return (evt.currentTarget.compareTo(evt.container) || evt.container.compareTo(this._getUIEventNode()));
                                },
                            
                                /**
                                 * Determines if the specified event is a UI event.
                                 *
                                 * @private
                                 * @method _isUIEvent
                                 * @for Widget
                                 * @param type {String} String representing the name of the event
                                 * @return {String} Event Returns the name of the UI Event, otherwise
                                 * undefined.
                                 */
                                _getUIEvent: function (type) {
                            
                                    if (L.isString(type)) {
                                        var sType = this.parseType(type)[1],
                                            iDelim,
                                            returnVal;
                            
                                        if (sType) {
                                            // TODO: Get delimiter from ET, or have ET support this.
                                            iDelim = sType.indexOf(EVENT_PREFIX_DELIMITER);
                                            if (iDelim > -1) {
                                                sType = sType.substring(iDelim + EVENT_PREFIX_DELIMITER.length);
                                            }
                            
                                            if (this.UI_EVENTS[sType]) {
                                                returnVal = sType;
                                            }
                                        }
                            
                                        return returnVal;
                                    }
                                },
                            
                                /**
                                 * Sets up infrastructure required to fire a UI event.
                                 *
                                 * @private
                                 * @method _initUIEvent
                                 * @for Widget
                                 * @param type {String} String representing the name of the event
                                 * @return {String}
                                 */
                                _initUIEvent: function (type) {
                                    var sType = this._getUIEvent(type),
                                        queue = this._uiEvtsInitQueue || {};
                            
                                    if (sType && !queue[sType]) {
                                        Y.log("Deferring creation of " + type + " delegate until render.", "info", "widget");
                            
                                        this._uiEvtsInitQueue = queue[sType] = 1;
                            
                                        this.after(RENDER, function() {
                                            this._createUIEvent(sType);
                                            delete this._uiEvtsInitQueue[sType];
                                        });
                                    }
                                },
                            
                                //  Override of "on" from Base to facilitate the firing of Widget events
                                //  based on DOM events of the same name/type (e.g. "click", "mouseover").
                                //  Temporary solution until we have the ability to listen to when
                                //  someone adds an event listener (bug 2528230)
                                on: function (type) {
                                    this._initUIEvent(type);
                                    return Widget.superclass.on.apply(this, arguments);
                                },
                            
                                //  Override of "publish" from Base to facilitate the firing of Widget events
                                //  based on DOM events of the same name/type (e.g. "click", "mouseover").
                                //  Temporary solution until we have the ability to listen to when
                                //  someone publishes an event (bug 2528230)
                                publish: function (type, config) {
                                    var sType = this._getUIEvent(type);
                                    if (sType && config && config.defaultFn) {
                                        this._initUIEvent(sType);
                                    }
                                    return Widget.superclass.publish.apply(this, arguments);
                                }
                            
                            }, true); // overwrite existing EventTarget methods