AutorÃa | Ultima modificación | Ver Log |
YUI.add('widget-stack', function (Y, NAME) {/*** Provides stackable (z-index) support for Widgets through an extension.** @module widget-stack*/var L = Y.Lang,UA = Y.UA,Node = Y.Node,Widget = Y.Widget,ZINDEX = "zIndex",SHIM = "shim",VISIBLE = "visible",BOUNDING_BOX = "boundingBox",RENDER_UI = "renderUI",BIND_UI = "bindUI",SYNC_UI = "syncUI",OFFSET_WIDTH = "offsetWidth",OFFSET_HEIGHT = "offsetHeight",PARENT_NODE = "parentNode",FIRST_CHILD = "firstChild",OWNER_DOCUMENT = "ownerDocument",WIDTH = "width",HEIGHT = "height",PX = "px",// HANDLE KEYSSHIM_DEFERRED = "shimdeferred",SHIM_RESIZE = "shimresize",// EventsVisibleChange = "visibleChange",WidthChange = "widthChange",HeightChange = "heightChange",ShimChange = "shimChange",ZIndexChange = "zIndexChange",ContentUpdate = "contentUpdate",// CSSSTACKED = "stacked";/*** Widget extension, which can be used to add stackable (z-index) support to the* base Widget class along with a shimming solution, through the* <a href="Base.html#method_build">Base.build</a> method.** @class WidgetStack* @param {Object} User configuration object*/function Stack(config) {}// Static Properties/*** Static property used to define the default attribute* configuration introduced by WidgetStack.** @property ATTRS* @type Object* @static*/Stack.ATTRS = {/*** @attribute shim* @type boolean* @default false, for all browsers other than IE6, for which a shim is enabled by default.** @description Boolean flag to indicate whether or not a shim should be added to the Widgets* boundingBox, to protect it from select box bleedthrough.*/shim: {value: (UA.ie == 6)},/*** @attribute zIndex* @type number* @default 0* @description The z-index to apply to the Widgets boundingBox. Non-numerical values for* zIndex will be converted to 0*/zIndex: {value : 0,setter: '_setZIndex'}};/*** The HTML parsing rules for the WidgetStack class.** @property HTML_PARSER* @static* @type Object*/Stack.HTML_PARSER = {zIndex: function (srcNode) {return this._parseZIndex(srcNode);}};/*** Default class used to mark the shim element** @property SHIM_CLASS_NAME* @type String* @static* @default "yui3-widget-shim"*/Stack.SHIM_CLASS_NAME = Widget.getClassName(SHIM);/*** Default class used to mark the boundingBox of a stacked widget.** @property STACKED_CLASS_NAME* @type String* @static* @default "yui3-widget-stacked"*/Stack.STACKED_CLASS_NAME = Widget.getClassName(STACKED);/*** Default markup template used to generate the shim element.** @property SHIM_TEMPLATE* @type String* @static*/Stack.SHIM_TEMPLATE = '<iframe class="' + Stack.SHIM_CLASS_NAME + '" frameborder="0" title="Widget Stacking Shim" src="javascript:false" tabindex="-1" role="presentation"></iframe>';Stack.prototype = {initializer : function() {this._stackNode = this.get(BOUNDING_BOX);this._stackHandles = {};// WIDGET METHOD OVERLAPY.after(this._renderUIStack, this, RENDER_UI);Y.after(this._syncUIStack, this, SYNC_UI);Y.after(this._bindUIStack, this, BIND_UI);},/*** Synchronizes the UI to match the Widgets stack state. This method in* invoked after syncUI is invoked for the Widget class using YUI's aop infrastructure.** @method _syncUIStack* @protected*/_syncUIStack: function() {this._uiSetShim(this.get(SHIM));this._uiSetZIndex(this.get(ZINDEX));},/*** Binds event listeners responsible for updating the UI state in response to* Widget stack related state changes.* <p>* This method is invoked after bindUI is invoked for the Widget class* using YUI's aop infrastructure.* </p>* @method _bindUIStack* @protected*/_bindUIStack: function() {this.after(ShimChange, this._afterShimChange);this.after(ZIndexChange, this._afterZIndexChange);},/*** Creates/Initializes the DOM to support stackability.* <p>* This method in invoked after renderUI is invoked for the Widget class* using YUI's aop infrastructure.* </p>* @method _renderUIStack* @protected*/_renderUIStack: function() {this._stackNode.addClass(Stack.STACKED_CLASS_NAME);},/**Parses a `zIndex` attribute value from this widget's `srcNode`.@method _parseZIndex@param {Node} srcNode The node to parse a `zIndex` value from.@return {Mixed} The parsed `zIndex` value.@protected**/_parseZIndex: function (srcNode) {var zIndex;// Prefers how WebKit handles `z-index` which better matches the// spec://// * http://www.w3.org/TR/CSS2/visuren.html#z-index// * https://bugs.webkit.org/show_bug.cgi?id=15562//// When a node isn't rendered in the document, and/or when a// node is not positioned, then it doesn't have a context to derive// a valid `z-index` value from.if (!srcNode.inDoc() || srcNode.getStyle('position') === 'static') {zIndex = 'auto';} else {// Uses `getComputedStyle()` because it has greater accuracy in// more browsers than `getStyle()` does for `z-index`.zIndex = srcNode.getComputedStyle('zIndex');}// This extension adds a stacking context to widgets, therefore a// `srcNode` witout a stacking context (i.e. "auto") will return// `null` from this DOM parser. This way the widget's default or// user provided value for `zIndex` will be used.return zIndex === 'auto' ? null : zIndex;},/*** Default setter for zIndex attribute changes. Normalizes zIndex values to* numbers, converting non-numerical values to 0.** @method _setZIndex* @protected* @param {String | Number} zIndex* @return {Number} Normalized zIndex*/_setZIndex: function(zIndex) {if (L.isString(zIndex)) {zIndex = parseInt(zIndex, 10);}if (!L.isNumber(zIndex)) {zIndex = 0;}return zIndex;},/*** Default attribute change listener for the shim attribute, responsible* for updating the UI, in response to attribute changes.** @method _afterShimChange* @protected* @param {EventFacade} e The event facade for the attribute change*/_afterShimChange : function(e) {this._uiSetShim(e.newVal);},/*** Default attribute change listener for the zIndex attribute, responsible* for updating the UI, in response to attribute changes.** @method _afterZIndexChange* @protected* @param {EventFacade} e The event facade for the attribute change*/_afterZIndexChange : function(e) {this._uiSetZIndex(e.newVal);},/*** Updates the UI to reflect the zIndex value passed in.** @method _uiSetZIndex* @protected* @param {number} zIndex The zindex to be reflected in the UI*/_uiSetZIndex: function (zIndex) {this._stackNode.setStyle(ZINDEX, zIndex);},/*** Updates the UI to enable/disable the shim. If the widget is not currently visible,* creation of the shim is deferred until it is made visible, for performance reasons.** @method _uiSetShim* @protected* @param {boolean} enable If true, creates/renders the shim, if false, removes it.*/_uiSetShim: function (enable) {if (enable) {// Lazy creationif (this.get(VISIBLE)) {this._renderShim();} else {this._renderShimDeferred();}// Eagerly attach resize handlers//// Required because of Event stack behavior, commit ref: cd8dddc// Should be revisted after Ticket #2531067 is resolved.if (UA.ie == 6) {this._addShimResizeHandlers();}} else {this._destroyShim();}},/*** Sets up change handlers for the visible attribute, to defer shim creation/rendering* until the Widget is made visible.** @method _renderShimDeferred* @private*/_renderShimDeferred : function() {this._stackHandles[SHIM_DEFERRED] = this._stackHandles[SHIM_DEFERRED] || [];var handles = this._stackHandles[SHIM_DEFERRED],createBeforeVisible = function(e) {if (e.newVal) {this._renderShim();}};handles.push(this.on(VisibleChange, createBeforeVisible));// Depending how how Ticket #2531067 is resolved, a reversal of// commit ref: cd8dddc could lead to a more elagent solution, with// the addition of this line here://// handles.push(this.after(VisibleChange, this.sizeShim));},/*** Sets up event listeners to resize the shim when the size of the Widget changes.* <p>* NOTE: This method is only used for IE6 currently, since IE6 doesn't support a way to* resize the shim purely through CSS, when the Widget does not have an explicit width/height* set.* </p>* @method _addShimResizeHandlers* @private*/_addShimResizeHandlers : function() {this._stackHandles[SHIM_RESIZE] = this._stackHandles[SHIM_RESIZE] || [];var sizeShim = this.sizeShim,handles = this._stackHandles[SHIM_RESIZE];handles.push(this.after(VisibleChange, sizeShim));handles.push(this.after(WidthChange, sizeShim));handles.push(this.after(HeightChange, sizeShim));handles.push(this.after(ContentUpdate, sizeShim));},/*** Detaches any handles stored for the provided key** @method _detachStackHandles* @param String handleKey The key defining the group of handles which should be detached* @private*/_detachStackHandles : function(handleKey) {var handles = this._stackHandles[handleKey],handle;if (handles && handles.length > 0) {while((handle = handles.pop())) {handle.detach();}}},/*** Creates the shim element and adds it to the DOM** @method _renderShim* @private*/_renderShim : function() {var shimEl = this._shimNode,stackEl = this._stackNode;if (!shimEl) {shimEl = this._shimNode = this._getShimTemplate();stackEl.insertBefore(shimEl, stackEl.get(FIRST_CHILD));this._detachStackHandles(SHIM_DEFERRED);this.sizeShim();}},/*** Removes the shim from the DOM, and detaches any related event* listeners.** @method _destroyShim* @private*/_destroyShim : function() {if (this._shimNode) {this._shimNode.get(PARENT_NODE).removeChild(this._shimNode);this._shimNode = null;this._detachStackHandles(SHIM_DEFERRED);this._detachStackHandles(SHIM_RESIZE);}},/*** For IE6, synchronizes the size and position of iframe shim to that of* Widget bounding box which it is protecting. For all other browsers,* this method does not do anything.** @method sizeShim*/sizeShim: function () {var shim = this._shimNode,node = this._stackNode;if (shim && UA.ie === 6 && this.get(VISIBLE)) {shim.setStyle(WIDTH, node.get(OFFSET_WIDTH) + PX);shim.setStyle(HEIGHT, node.get(OFFSET_HEIGHT) + PX);}},/*** Creates a cloned shim node, using the SHIM_TEMPLATE html template, for use on a new instance.** @method _getShimTemplate* @private* @return {Node} node A new shim Node instance.*/_getShimTemplate : function() {return Node.create(Stack.SHIM_TEMPLATE, this._stackNode.get(OWNER_DOCUMENT));}};Y.WidgetStack = Stack;}, '3.18.1', {"requires": ["base-build", "widget"], "skinnable": true});