Version 3.18.1
Show:

File: widget-autohide/js/Widget-Autohide.js

            /**
             * A widget-level extension that provides ability to hide widget when
             * certain events occur.
             *
             * @module widget-autohide
             * @author eferraiuolo, tilomitra
             * @since 3.4.0
             */
            
            
            var WIDGET_AUTOHIDE    = 'widgetAutohide',
                AUTOHIDE            = 'autohide',
                CLICK_OUTSIDE     = 'clickoutside',
                FOCUS_OUTSIDE     = 'focusoutside',
                DOCUMENT            = 'document',
                KEY                 = 'key',
                PRESS_ESCAPE         = 'esc',
                BIND_UI             = 'bindUI',
                SYNC_UI             = "syncUI",
                RENDERED            = "rendered",
                BOUNDING_BOX        = "boundingBox",
                VISIBLE             = "visible",
                CHANGE              = 'Change',
            
                getCN               = Y.ClassNameManager.getClassName;
            
            /**
             * The WidgetAutohide class provides the hideOn attribute which can
             * be used to hide the widget when certain events occur.
             *
             * @class WidgetAutohide
             * @param {Object} config User configuration object
             */
            function WidgetAutohide(config) {
                Y.after(this._bindUIAutohide, this, BIND_UI);
                Y.after(this._syncUIAutohide, this, SYNC_UI);
            
            
                if (this.get(RENDERED)) {
                    this._bindUIAutohide();
                    this._syncUIAutohide();
                }
            
            }
            
            /**
            * Static property used to define the default attribute
            * configuration introduced by WidgetAutohide.
            *
            * @property ATTRS
            * @static
            * @type Object
            */
            WidgetAutohide.ATTRS = {
            
            
                /**
                 * @attribute hideOn
                 * @type array
                 *
                 * @description An array of objects corresponding to the nodes, events, and keycodes to hide the widget on.
                 * The implementer can supply an array of objects, with each object having the following properties:
                 * <p>eventName: (string, required): The eventName to listen to.</p>
                 * <p>node: (Y.Node, optional): The Y.Node that will fire the event (defaults to the boundingBox of the widget)</p>
                 * <p>keyCode: (string, optional): If listening for key events, specify the keyCode</p>
                 * <p>By default, this attribute consists of one object which will cause the widget to hide if the
                 * escape key is pressed.</p>
                 */
                hideOn: {
                    validator: Y.Lang.isArray,
                    valueFn  : function() {
                        return [
                            {
                                node: Y.one(DOCUMENT),
                                eventName: KEY,
                                keyCode: PRESS_ESCAPE
                            }
                        ];
                    }
                }
            };
            
            WidgetAutohide.prototype = {
                // *** Instance Members *** //
            
                    _uiHandlesAutohide : null,
            
                    // *** Lifecycle Methods *** //
            
                    destructor : function () {
            
                        this._detachUIHandlesAutohide();
                    },
            
                    /**
                     * Binds event listeners to the widget.
                     * <p>
                     * This method in invoked after bindUI is invoked for the Widget class
                     * using YUI's aop infrastructure.
                     * </p>
                     * @method _bindUIAutohide
                     * @protected
                     */
                    _bindUIAutohide : function () {
            
                        this.after(VISIBLE+CHANGE, this._afterHostVisibleChangeAutohide);
                        this.after("hideOnChange", this._afterHideOnChange);
                    },
            
                    /**
                     * Syncs up the widget based on its current state. In particular, removes event listeners if
                     * widget is not visible, and attaches them otherwise.
                     * <p>
                     * This method in invoked after syncUI is invoked for the Widget class
                     * using YUI's aop infrastructure.
                     * </p>
                     * @method _syncUIAutohide
                     * @protected
                     */
                    _syncUIAutohide : function () {
            
                        this._uiSetHostVisibleAutohide(this.get(VISIBLE));
                    },
            
                    // *** Private Methods *** //
            
                    /**
                     * Removes event listeners if widget is not visible, and attaches them otherwise.
                     *
                     * @method _uiSetHostVisibleAutohide
                     * @protected
                     */
                    _uiSetHostVisibleAutohide : function (visible) {
            
                        if (visible) {
                            //this._attachUIHandlesAutohide();
                            Y.later(1, this, '_attachUIHandlesAutohide');
                        } else {
                            this._detachUIHandlesAutohide();
                        }
                    },
            
                    /**
                     * Iterates through all objects in the hideOn attribute and creates event listeners.
                     *
                     * @method _attachUIHandlesAutohide
                     * @protected
                     */
                    _attachUIHandlesAutohide : function () {
            
                        if (this._uiHandlesAutohide) { return; }
            
                        var bb = this.get(BOUNDING_BOX),
                            hide = Y.bind(this.hide,this),
                            uiHandles = [],
                            self = this,
                            hideOn = this.get('hideOn'),
                            i = 0,
                            o = {node: undefined, ev: undefined, keyCode: undefined};
            
                            //push all events on which the widget should be hidden
                            for (; i < hideOn.length; i++) {
            
                                o.node = hideOn[i].node;
                                o.ev = hideOn[i].eventName;
                                o.keyCode = hideOn[i].keyCode;
            
                                //no keycode or node defined
                                if (!o.node && !o.keyCode && o.ev) {
                                    uiHandles.push(bb.on(o.ev, hide));
                                }
            
                                //node defined, no keycode (not a keypress)
                                else if (o.node && !o.keyCode && o.ev) {
                                    uiHandles.push(o.node.on(o.ev, hide));
                                }
            
                                //node defined, keycode defined, event defined (its a key press)
                                else if (o.node && o.keyCode && o.ev) {
                                    uiHandles.push(o.node.on(o.ev, hide, o.keyCode));
                                }
            
                                else {
                                    Y.log('The event with name "'+o.ev+'" could not be attached.');
                                }
            
                            }
            
                        this._uiHandlesAutohide = uiHandles;
                    },
            
                    /**
                     * Detaches all event listeners created by this extension
                     *
                     * @method _detachUIHandlesAutohide
                     * @protected
                     */
                    _detachUIHandlesAutohide : function () {
            
                        Y.each(this._uiHandlesAutohide, function(h){
                            h.detach();
                        });
                        this._uiHandlesAutohide = null;
                    },
            
                    /**
                     * Default function called when the visibility of the widget changes. Determines
                     * whether to attach or detach event listeners based on the visibility of the widget.
                     *
                     * @method _afterHostVisibleChangeAutohide
                     * @protected
                     */
                    _afterHostVisibleChangeAutohide : function (e) {
            
                        this._uiSetHostVisibleAutohide(e.newVal);
                    },
            
                    /**
                     * Default function called when hideOn Attribute is changed. Remove existing listeners and create new listeners.
                     *
                     * @method _afterHideOnChange
                     * @protected
                     */
                    _afterHideOnChange : function(e) {
                        this._detachUIHandlesAutohide();
            
                        if (this.get(VISIBLE)) {
                            this._attachUIHandlesAutohide();
                        }
                    }
            };
            
            Y.WidgetAutohide = WidgetAutohide;