src/cm/media/js/lib/yui/yui3-3.15.0/build/widget-stack/widget-stack-debug.js
changeset 602 e16a97fb364a
equal deleted inserted replaced
601:d334a616c023 602:e16a97fb364a
       
     1 YUI.add('widget-stack', function (Y, NAME) {
       
     2 
       
     3 /**
       
     4  * Provides stackable (z-index) support for Widgets through an extension.
       
     5  *
       
     6  * @module widget-stack
       
     7  */
       
     8     var L = Y.Lang,
       
     9         UA = Y.UA,
       
    10         Node = Y.Node,
       
    11         Widget = Y.Widget,
       
    12 
       
    13         ZINDEX = "zIndex",
       
    14         SHIM = "shim",
       
    15         VISIBLE = "visible",
       
    16 
       
    17         BOUNDING_BOX = "boundingBox",
       
    18 
       
    19         RENDER_UI = "renderUI",
       
    20         BIND_UI = "bindUI",
       
    21         SYNC_UI = "syncUI",
       
    22 
       
    23         OFFSET_WIDTH = "offsetWidth",
       
    24         OFFSET_HEIGHT = "offsetHeight",
       
    25         PARENT_NODE = "parentNode",
       
    26         FIRST_CHILD = "firstChild",
       
    27         OWNER_DOCUMENT = "ownerDocument",
       
    28 
       
    29         WIDTH = "width",
       
    30         HEIGHT = "height",
       
    31         PX = "px",
       
    32 
       
    33         // HANDLE KEYS
       
    34         SHIM_DEFERRED = "shimdeferred",
       
    35         SHIM_RESIZE = "shimresize",
       
    36 
       
    37         // Events
       
    38         VisibleChange = "visibleChange",
       
    39         WidthChange = "widthChange",
       
    40         HeightChange = "heightChange",
       
    41         ShimChange = "shimChange",
       
    42         ZIndexChange = "zIndexChange",
       
    43         ContentUpdate = "contentUpdate",
       
    44 
       
    45         // CSS
       
    46         STACKED = "stacked";
       
    47 
       
    48     /**
       
    49      * Widget extension, which can be used to add stackable (z-index) support to the
       
    50      * base Widget class along with a shimming solution, through the
       
    51      * <a href="Base.html#method_build">Base.build</a> method.
       
    52      *
       
    53      * @class WidgetStack
       
    54      * @param {Object} User configuration object
       
    55      */
       
    56     function Stack(config) {}
       
    57 
       
    58     // Static Properties
       
    59     /**
       
    60      * Static property used to define the default attribute
       
    61      * configuration introduced by WidgetStack.
       
    62      *
       
    63      * @property ATTRS
       
    64      * @type Object
       
    65      * @static
       
    66      */
       
    67     Stack.ATTRS = {
       
    68         /**
       
    69          * @attribute shim
       
    70          * @type boolean
       
    71          * @default false, for all browsers other than IE6, for which a shim is enabled by default.
       
    72          *
       
    73          * @description Boolean flag to indicate whether or not a shim should be added to the Widgets
       
    74          * boundingBox, to protect it from select box bleedthrough.
       
    75          */
       
    76         shim: {
       
    77             value: (UA.ie == 6)
       
    78         },
       
    79 
       
    80         /**
       
    81          * @attribute zIndex
       
    82          * @type number
       
    83          * @default 0
       
    84          * @description The z-index to apply to the Widgets boundingBox. Non-numerical values for
       
    85          * zIndex will be converted to 0
       
    86          */
       
    87         zIndex: {
       
    88             value : 0,
       
    89             setter: '_setZIndex'
       
    90         }
       
    91     };
       
    92 
       
    93     /**
       
    94      * The HTML parsing rules for the WidgetStack class.
       
    95      *
       
    96      * @property HTML_PARSER
       
    97      * @static
       
    98      * @type Object
       
    99      */
       
   100     Stack.HTML_PARSER = {
       
   101         zIndex: function (srcNode) {
       
   102             return this._parseZIndex(srcNode);
       
   103         }
       
   104     };
       
   105 
       
   106     /**
       
   107      * Default class used to mark the shim element
       
   108      *
       
   109      * @property SHIM_CLASS_NAME
       
   110      * @type String
       
   111      * @static
       
   112      * @default "yui3-widget-shim"
       
   113      */
       
   114     Stack.SHIM_CLASS_NAME = Widget.getClassName(SHIM);
       
   115 
       
   116     /**
       
   117      * Default class used to mark the boundingBox of a stacked widget.
       
   118      *
       
   119      * @property STACKED_CLASS_NAME
       
   120      * @type String
       
   121      * @static
       
   122      * @default "yui3-widget-stacked"
       
   123      */
       
   124     Stack.STACKED_CLASS_NAME = Widget.getClassName(STACKED);
       
   125 
       
   126     /**
       
   127      * Default markup template used to generate the shim element.
       
   128      *
       
   129      * @property SHIM_TEMPLATE
       
   130      * @type String
       
   131      * @static
       
   132      */
       
   133     Stack.SHIM_TEMPLATE = '<iframe class="' + Stack.SHIM_CLASS_NAME + '" frameborder="0" title="Widget Stacking Shim" src="javascript:false" tabindex="-1" role="presentation"></iframe>';
       
   134 
       
   135     Stack.prototype = {
       
   136 
       
   137         initializer : function() {
       
   138             this._stackNode = this.get(BOUNDING_BOX);
       
   139             this._stackHandles = {};
       
   140 
       
   141             // WIDGET METHOD OVERLAP
       
   142             Y.after(this._renderUIStack, this, RENDER_UI);
       
   143             Y.after(this._syncUIStack, this, SYNC_UI);
       
   144             Y.after(this._bindUIStack, this, BIND_UI);
       
   145         },
       
   146 
       
   147         /**
       
   148          * Synchronizes the UI to match the Widgets stack state. This method in
       
   149          * invoked after syncUI is invoked for the Widget class using YUI's aop infrastructure.
       
   150          *
       
   151          * @method _syncUIStack
       
   152          * @protected
       
   153          */
       
   154         _syncUIStack: function() {
       
   155             this._uiSetShim(this.get(SHIM));
       
   156             this._uiSetZIndex(this.get(ZINDEX));
       
   157         },
       
   158 
       
   159         /**
       
   160          * Binds event listeners responsible for updating the UI state in response to
       
   161          * Widget stack related state changes.
       
   162          * <p>
       
   163          * This method is invoked after bindUI is invoked for the Widget class
       
   164          * using YUI's aop infrastructure.
       
   165          * </p>
       
   166          * @method _bindUIStack
       
   167          * @protected
       
   168          */
       
   169         _bindUIStack: function() {
       
   170             this.after(ShimChange, this._afterShimChange);
       
   171             this.after(ZIndexChange, this._afterZIndexChange);
       
   172         },
       
   173 
       
   174         /**
       
   175          * Creates/Initializes the DOM to support stackability.
       
   176          * <p>
       
   177          * This method in invoked after renderUI is invoked for the Widget class
       
   178          * using YUI's aop infrastructure.
       
   179          * </p>
       
   180          * @method _renderUIStack
       
   181          * @protected
       
   182          */
       
   183         _renderUIStack: function() {
       
   184             this._stackNode.addClass(Stack.STACKED_CLASS_NAME);
       
   185         },
       
   186 
       
   187         /**
       
   188         Parses a `zIndex` attribute value from this widget's `srcNode`.
       
   189 
       
   190         @method _parseZIndex
       
   191         @param {Node} srcNode The node to parse a `zIndex` value from.
       
   192         @return {Mixed} The parsed `zIndex` value.
       
   193         @protected
       
   194         **/
       
   195         _parseZIndex: function (srcNode) {
       
   196             var zIndex;
       
   197 
       
   198             // Prefers how WebKit handles `z-index` which better matches the
       
   199             // spec:
       
   200             //
       
   201             // * http://www.w3.org/TR/CSS2/visuren.html#z-index
       
   202             // * https://bugs.webkit.org/show_bug.cgi?id=15562
       
   203             //
       
   204             // When a node isn't rendered in the document, and/or when a
       
   205             // node is not positioned, then it doesn't have a context to derive
       
   206             // a valid `z-index` value from.
       
   207             if (!srcNode.inDoc() || srcNode.getStyle('position') === 'static') {
       
   208                 zIndex = 'auto';
       
   209             } else {
       
   210                 // Uses `getComputedStyle()` because it has greater accuracy in
       
   211                 // more browsers than `getStyle()` does for `z-index`.
       
   212                 zIndex = srcNode.getComputedStyle('zIndex');
       
   213             }
       
   214 
       
   215             // This extension adds a stacking context to widgets, therefore a
       
   216             // `srcNode` witout a stacking context (i.e. "auto") will return
       
   217             // `null` from this DOM parser. This way the widget's default or
       
   218             // user provided value for `zIndex` will be used.
       
   219             return zIndex === 'auto' ? null : zIndex;
       
   220         },
       
   221 
       
   222         /**
       
   223          * Default setter for zIndex attribute changes. Normalizes zIndex values to
       
   224          * numbers, converting non-numerical values to 0.
       
   225          *
       
   226          * @method _setZIndex
       
   227          * @protected
       
   228          * @param {String | Number} zIndex
       
   229          * @return {Number} Normalized zIndex
       
   230          */
       
   231         _setZIndex: function(zIndex) {
       
   232             if (L.isString(zIndex)) {
       
   233                 zIndex = parseInt(zIndex, 10);
       
   234             }
       
   235             if (!L.isNumber(zIndex)) {
       
   236                 zIndex = 0;
       
   237             }
       
   238             return zIndex;
       
   239         },
       
   240 
       
   241         /**
       
   242          * Default attribute change listener for the shim attribute, responsible
       
   243          * for updating the UI, in response to attribute changes.
       
   244          *
       
   245          * @method _afterShimChange
       
   246          * @protected
       
   247          * @param {EventFacade} e The event facade for the attribute change
       
   248          */
       
   249         _afterShimChange : function(e) {
       
   250             this._uiSetShim(e.newVal);
       
   251         },
       
   252 
       
   253         /**
       
   254          * Default attribute change listener for the zIndex attribute, responsible
       
   255          * for updating the UI, in response to attribute changes.
       
   256          *
       
   257          * @method _afterZIndexChange
       
   258          * @protected
       
   259          * @param {EventFacade} e The event facade for the attribute change
       
   260          */
       
   261         _afterZIndexChange : function(e) {
       
   262             this._uiSetZIndex(e.newVal);
       
   263         },
       
   264 
       
   265         /**
       
   266          * Updates the UI to reflect the zIndex value passed in.
       
   267          *
       
   268          * @method _uiSetZIndex
       
   269          * @protected
       
   270          * @param {number} zIndex The zindex to be reflected in the UI
       
   271          */
       
   272         _uiSetZIndex: function (zIndex) {
       
   273             this._stackNode.setStyle(ZINDEX, zIndex);
       
   274         },
       
   275 
       
   276         /**
       
   277          * Updates the UI to enable/disable the shim. If the widget is not currently visible,
       
   278          * creation of the shim is deferred until it is made visible, for performance reasons.
       
   279          *
       
   280          * @method _uiSetShim
       
   281          * @protected
       
   282          * @param {boolean} enable If true, creates/renders the shim, if false, removes it.
       
   283          */
       
   284         _uiSetShim: function (enable) {
       
   285             if (enable) {
       
   286                 // Lazy creation
       
   287                 if (this.get(VISIBLE)) {
       
   288                     this._renderShim();
       
   289                 } else {
       
   290                     this._renderShimDeferred();
       
   291                 }
       
   292 
       
   293                 // Eagerly attach resize handlers
       
   294                 //
       
   295                 // Required because of Event stack behavior, commit ref: cd8dddc
       
   296                 // Should be revisted after Ticket #2531067 is resolved.
       
   297                 if (UA.ie == 6) {
       
   298                     this._addShimResizeHandlers();
       
   299                 }
       
   300             } else {
       
   301                 this._destroyShim();
       
   302             }
       
   303         },
       
   304 
       
   305         /**
       
   306          * Sets up change handlers for the visible attribute, to defer shim creation/rendering
       
   307          * until the Widget is made visible.
       
   308          *
       
   309          * @method _renderShimDeferred
       
   310          * @private
       
   311          */
       
   312         _renderShimDeferred : function() {
       
   313 
       
   314             this._stackHandles[SHIM_DEFERRED] = this._stackHandles[SHIM_DEFERRED] || [];
       
   315 
       
   316             var handles = this._stackHandles[SHIM_DEFERRED],
       
   317                 createBeforeVisible = function(e) {
       
   318                     if (e.newVal) {
       
   319                         this._renderShim();
       
   320                     }
       
   321                 };
       
   322 
       
   323             handles.push(this.on(VisibleChange, createBeforeVisible));
       
   324             // Depending how how Ticket #2531067 is resolved, a reversal of
       
   325             // commit ref: cd8dddc could lead to a more elagent solution, with
       
   326             // the addition of this line here:
       
   327             //
       
   328             // handles.push(this.after(VisibleChange, this.sizeShim));
       
   329         },
       
   330 
       
   331         /**
       
   332          * Sets up event listeners to resize the shim when the size of the Widget changes.
       
   333          * <p>
       
   334          * NOTE: This method is only used for IE6 currently, since IE6 doesn't support a way to
       
   335          * resize the shim purely through CSS, when the Widget does not have an explicit width/height
       
   336          * set.
       
   337          * </p>
       
   338          * @method _addShimResizeHandlers
       
   339          * @private
       
   340          */
       
   341         _addShimResizeHandlers : function() {
       
   342 
       
   343             this._stackHandles[SHIM_RESIZE] = this._stackHandles[SHIM_RESIZE] || [];
       
   344 
       
   345             var sizeShim = this.sizeShim,
       
   346                 handles = this._stackHandles[SHIM_RESIZE];
       
   347 
       
   348             handles.push(this.after(VisibleChange, sizeShim));
       
   349             handles.push(this.after(WidthChange, sizeShim));
       
   350             handles.push(this.after(HeightChange, sizeShim));
       
   351             handles.push(this.after(ContentUpdate, sizeShim));
       
   352         },
       
   353 
       
   354         /**
       
   355          * Detaches any handles stored for the provided key
       
   356          *
       
   357          * @method _detachStackHandles
       
   358          * @param String handleKey The key defining the group of handles which should be detached
       
   359          * @private
       
   360          */
       
   361         _detachStackHandles : function(handleKey) {
       
   362             var handles = this._stackHandles[handleKey],
       
   363                 handle;
       
   364 
       
   365             if (handles && handles.length > 0) {
       
   366                 while((handle = handles.pop())) {
       
   367                     handle.detach();
       
   368                 }
       
   369             }
       
   370         },
       
   371 
       
   372         /**
       
   373          * Creates the shim element and adds it to the DOM
       
   374          *
       
   375          * @method _renderShim
       
   376          * @private
       
   377          */
       
   378         _renderShim : function() {
       
   379             var shimEl = this._shimNode,
       
   380                 stackEl = this._stackNode;
       
   381 
       
   382             if (!shimEl) {
       
   383                 shimEl = this._shimNode = this._getShimTemplate();
       
   384                 stackEl.insertBefore(shimEl, stackEl.get(FIRST_CHILD));
       
   385 
       
   386                 this._detachStackHandles(SHIM_DEFERRED);
       
   387                 this.sizeShim();
       
   388             }
       
   389         },
       
   390 
       
   391         /**
       
   392          * Removes the shim from the DOM, and detaches any related event
       
   393          * listeners.
       
   394          *
       
   395          * @method _destroyShim
       
   396          * @private
       
   397          */
       
   398         _destroyShim : function() {
       
   399             if (this._shimNode) {
       
   400                 this._shimNode.get(PARENT_NODE).removeChild(this._shimNode);
       
   401                 this._shimNode = null;
       
   402 
       
   403                 this._detachStackHandles(SHIM_DEFERRED);
       
   404                 this._detachStackHandles(SHIM_RESIZE);
       
   405             }
       
   406         },
       
   407 
       
   408         /**
       
   409          * For IE6, synchronizes the size and position of iframe shim to that of
       
   410          * Widget bounding box which it is protecting. For all other browsers,
       
   411          * this method does not do anything.
       
   412          *
       
   413          * @method sizeShim
       
   414          */
       
   415         sizeShim: function () {
       
   416             var shim = this._shimNode,
       
   417                 node = this._stackNode;
       
   418 
       
   419             if (shim && UA.ie === 6 && this.get(VISIBLE)) {
       
   420                 shim.setStyle(WIDTH, node.get(OFFSET_WIDTH) + PX);
       
   421                 shim.setStyle(HEIGHT, node.get(OFFSET_HEIGHT) + PX);
       
   422             }
       
   423         },
       
   424 
       
   425         /**
       
   426          * Creates a cloned shim node, using the SHIM_TEMPLATE html template, for use on a new instance.
       
   427          *
       
   428          * @method _getShimTemplate
       
   429          * @private
       
   430          * @return {Node} node A new shim Node instance.
       
   431          */
       
   432         _getShimTemplate : function() {
       
   433             return Node.create(Stack.SHIM_TEMPLATE, this._stackNode.get(OWNER_DOCUMENT));
       
   434         }
       
   435     };
       
   436 
       
   437     Y.WidgetStack = Stack;
       
   438 
       
   439 
       
   440 }, '@VERSION@', {"requires": ["base-build", "widget"], "skinnable": true});