3 Copyright 2012 Yahoo! Inc. All rights reserved.
4 Licensed under the BSD License.
5 http://yuilibrary.com/license/
7 YUI.add('widget-autohide', function (Y, NAME) {
10 * A widget-level extension that provides ability to hide widget when
11 * certain events occur.
13 * @module widget-autohide
14 * @author eferraiuolo, tilomitra
19 var WIDGET_AUTOHIDE = 'widgetAutohide',
20 AUTOHIDE = 'autohide',
21 CLICK_OUTSIDE = 'clickoutside',
22 FOCUS_OUTSIDE = 'focusoutside',
23 DOCUMENT = 'document',
28 RENDERED = "rendered",
29 BOUNDING_BOX = "boundingBox",
33 getCN = Y.ClassNameManager.getClassName;
36 * The WidgetAutohide class provides the hideOn attribute which can
37 * be used to hide the widget when certain events occur.
39 * @class WidgetAutohide
40 * @param {Object} config User configuration object
42 function WidgetAutohide(config) {
43 Y.after(this._bindUIAutohide, this, BIND_UI);
44 Y.after(this._syncUIAutohide, this, SYNC_UI);
47 if (this.get(RENDERED)) {
48 this._bindUIAutohide();
49 this._syncUIAutohide();
55 * Static property used to define the default attribute
56 * configuration introduced by WidgetAutohide.
62 WidgetAutohide.ATTRS = {
69 * @description An array of objects corresponding to the nodes, events, and keycodes to hide the widget on.
70 * The implementer can supply an array of objects, with each object having the following properties:
71 * <p>eventName: (string, required): The eventName to listen to.</p>
72 * <p>node: (Y.Node, optional): The Y.Node that will fire the event (defaults to the boundingBox of the widget)</p>
73 * <p>keyCode: (string, optional): If listening for key events, specify the keyCode</p>
74 * <p>By default, this attribute consists of one object which will cause the widget to hide if the
75 * escape key is pressed.</p>
78 validator: Y.Lang.isArray,
79 valueFn : function() {
82 node: Y.one(DOCUMENT),
91 WidgetAutohide.prototype = {
92 // *** Instance Members *** //
94 _uiHandlesAutohide : null,
96 // *** Lifecycle Methods *** //
98 destructor : function () {
100 this._detachUIHandlesAutohide();
104 * Binds event listeners to the widget.
106 * This method in invoked after bindUI is invoked for the Widget class
107 * using YUI's aop infrastructure.
109 * @method _bindUIAutohide
112 _bindUIAutohide : function () {
114 this.after(VISIBLE+CHANGE, this._afterHostVisibleChangeAutohide);
115 this.after("hideOnChange", this._afterHideOnChange);
119 * Syncs up the widget based on its current state. In particular, removes event listeners if
120 * widget is not visible, and attaches them otherwise.
122 * This method in invoked after syncUI is invoked for the Widget class
123 * using YUI's aop infrastructure.
125 * @method _syncUIAutohide
128 _syncUIAutohide : function () {
130 this._uiSetHostVisibleAutohide(this.get(VISIBLE));
133 // *** Private Methods *** //
136 * Removes event listeners if widget is not visible, and attaches them otherwise.
138 * @method _uiSetHostVisibleAutohide
141 _uiSetHostVisibleAutohide : function (visible) {
144 //this._attachUIHandlesAutohide();
145 Y.later(1, this, '_attachUIHandlesAutohide');
147 this._detachUIHandlesAutohide();
152 * Iterates through all objects in the hideOn attribute and creates event listeners.
154 * @method _attachUIHandlesAutohide
157 _attachUIHandlesAutohide : function () {
159 if (this._uiHandlesAutohide) { return; }
161 var bb = this.get(BOUNDING_BOX),
162 hide = Y.bind(this.hide,this),
165 hideOn = this.get('hideOn'),
167 o = {node: undefined, ev: undefined, keyCode: undefined};
169 //push all events on which the widget should be hidden
170 for (; i < hideOn.length; i++) {
172 o.node = hideOn[i].node;
173 o.ev = hideOn[i].eventName;
174 o.keyCode = hideOn[i].keyCode;
176 //no keycode or node defined
177 if (!o.node && !o.keyCode && o.ev) {
178 uiHandles.push(bb.on(o.ev, hide));
181 //node defined, no keycode (not a keypress)
182 else if (o.node && !o.keyCode && o.ev) {
183 uiHandles.push(o.node.on(o.ev, hide));
186 //node defined, keycode defined, event defined (its a key press)
187 else if (o.node && o.keyCode && o.ev) {
188 uiHandles.push(o.node.on(o.ev, hide, o.keyCode));
192 Y.log('The event with name "'+o.ev+'" could not be attached.');
197 this._uiHandlesAutohide = uiHandles;
201 * Detaches all event listeners created by this extension
203 * @method _detachUIHandlesAutohide
206 _detachUIHandlesAutohide : function () {
208 Y.each(this._uiHandlesAutohide, function(h){
211 this._uiHandlesAutohide = null;
215 * Default function called when the visibility of the widget changes. Determines
216 * whether to attach or detach event listeners based on the visibility of the widget.
218 * @method _afterHostVisibleChangeAutohide
221 _afterHostVisibleChangeAutohide : function (e) {
223 this._uiSetHostVisibleAutohide(e.newVal);
227 * Default function called when hideOn Attribute is changed. Remove existing listeners and create new listeners.
229 * @method _afterHideOnChange
231 _afterHideOnChange : function(e) {
232 this._detachUIHandlesAutohide();
234 if (this.get(VISIBLE)) {
235 this._attachUIHandlesAutohide();
240 Y.WidgetAutohide = WidgetAutohide;
243 }, '3.7.2', {"requires": ["base-build", "event-key", "event-outside", "widget"]});