X-Git-Url: http://git.ithinksw.org/extjs.git/blobdiff_plain/7a654f8d43fdb43d78b63d90528bed6e86b608cc..f562e4c6e5fac7bcb445985b99acbea4d706e6f0:/src/core/src/dom/Element.style.js diff --git a/src/core/src/dom/Element.style.js b/src/core/src/dom/Element.style.js index da93b66b..2475e4b4 100644 --- a/src/core/src/dom/Element.style.js +++ b/src/core/src/dom/Element.style.js @@ -1,10 +1,24 @@ +/* + +This file is part of Ext JS 4 + +Copyright (c) 2011 Sencha Inc + +Contact: http://www.sencha.com/contact + +GNU General Public License Usage +This file may be used under the terms of the GNU General Public License version 3.0 as published by the Free Software Foundation and appearing in the file LICENSE included in the packaging of this file. Please review the following information to ensure the GNU General Public License version 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html. + +If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact. + +*/ /** - * @class Ext.core.Element + * @class Ext.Element */ (function(){ - Ext.core.Element.boxMarkup = '
'; // local style camelizing for speed - var supports = Ext.supports, + var ELEMENT = Ext.Element, + supports = Ext.supports, view = document.defaultView, opacityRe = /alpha\(opacity=(.*)\)/i, trimRe = /^\s+|\s+$/g, @@ -31,10 +45,20 @@ borders = {l: BORDER + LEFT + WIDTH, r: BORDER + RIGHT + WIDTH, t: BORDER + TOP + WIDTH, b: BORDER + BOTTOM + WIDTH}, paddings = {l: PADDING + LEFT, r: PADDING + RIGHT, t: PADDING + TOP, b: PADDING + BOTTOM}, margins = {l: MARGIN + LEFT, r: MARGIN + RIGHT, t: MARGIN + TOP, b: MARGIN + BOTTOM}, - data = Ext.core.Element.data; + data = ELEMENT.data; + + ELEMENT.boxMarkup = '
'; + + // These property values are read from the parentNode if they cannot be read + // from the child: + ELEMENT.inheritedProps = { + fontSize: 1, + fontStyle: 1, + opacity: 1 + }; + + Ext.override(ELEMENT, { - Ext.override(Ext.core.Element, { - /** * TODO: Look at this */ @@ -42,7 +66,7 @@ adjustWidth : function(width) { var me = this, isNum = (typeof width == 'number'); - + if(isNum && me.autoBoxAdjust && !me.isBorderBox()){ width -= (me.getBorderWidth("lr") + me.getPadding("lr")); } @@ -53,7 +77,7 @@ adjustHeight : function(height) { var me = this, isNum = (typeof height == "number"); - + if(isNum && me.autoBoxAdjust && !me.isBorderBox()){ height -= (me.getBorderWidth("tb") + me.getPadding("tb")); } @@ -63,19 +87,19 @@ /** * Adds one or more CSS classes to the element. Duplicate classes are automatically filtered out. - * @param {String/Array} className The CSS classes to add separated by space, or an array of classes - * @return {Ext.core.Element} this + * @param {String/String[]} className The CSS classes to add separated by space, or an array of classes + * @return {Ext.Element} this */ addCls : function(className){ var me = this, cls = [], space = ((me.dom.className.replace(trimRe, '') == '') ? "" : " "), i, len, v; - if (!Ext.isDefined(className)) { + if (className === undefined) { return me; } // Separate case is for speed - if (!Ext.isArray(className)) { + if (Object.prototype.toString.call(className) !== '[object Array]') { if (typeof className === 'string') { className = className.replace(trimRe, '').split(spacesRe); if (className.length === 1) { @@ -103,16 +127,16 @@ /** * Removes one or more CSS classes from the element. - * @param {String/Array} className The CSS classes to remove separated by space, or an array of classes - * @return {Ext.core.Element} this + * @param {String/String[]} className The CSS classes to remove separated by space, or an array of classes + * @return {Ext.Element} this */ removeCls : function(className){ var me = this, i, idx, len, cls, elClasses; - if (!Ext.isDefined(className)) { + if (className === undefined) { return me; } - if (!Ext.isArray(className)){ + if (Object.prototype.toString.call(className) !== '[object Array]') { className = className.replace(trimRe, '').split(spacesRe); } if (me.dom && me.dom.className) { @@ -123,7 +147,7 @@ cls = cls.replace(trimRe, ''); idx = Ext.Array.indexOf(elClasses, cls); if (idx != -1) { - elClasses.splice(idx, 1); + Ext.Array.erase(elClasses, idx, 1); } } } @@ -134,8 +158,8 @@ /** * Adds one or more CSS classes to this element and removes the same class(es) from all siblings. - * @param {String/Array} className The CSS class to add, or an array of classes - * @return {Ext.core.Element} this + * @param {String/String[]} className The CSS class to add, or an array of classes + * @return {Ext.Element} this */ radioCls : function(className){ var cn = this.dom.parentNode.childNodes, @@ -153,7 +177,8 @@ /** * Toggles the specified CSS class on this element (removes it if it already exists, otherwise adds it). * @param {String} className The CSS class to toggle - * @return {Ext.core.Element} this + * @return {Ext.Element} this + * @method */ toggleCls : Ext.supports.ClassList ? function(className) { @@ -168,6 +193,7 @@ * Checks if the specified CSS class exists on this element's DOM node. * @param {String} className The CSS class to check for * @return {Boolean} True if the class exists, else false + * @method */ hasCls : Ext.supports.ClassList ? function(className) { @@ -192,7 +218,7 @@ * Replaces a CSS class on the element with another. If the old name does not exist, the new name will simply be added. * @param {String} oldClassName The CSS class to replace * @param {String} newClassName The replacement CSS class - * @return {Ext.core.Element} this + * @return {Ext.Element} this */ replaceCls : function(oldClassName, newClassName){ return this.removeCls(oldClassName).addCls(newClassName); @@ -206,57 +232,91 @@ * Normalizes currentStyle and computedStyle. * @param {String} property The style property whose value is returned. * @return {String} The current value of the style property for this element. + * @method */ - getStyle : function(){ + getStyle : function() { return view && view.getComputedStyle ? function(prop){ var el = this.dom, - v, cs, out, display; + v, cs, out, display, cleaner; if(el == document){ return null; } - prop = Ext.core.Element.normalize(prop); + prop = ELEMENT.normalize(prop); out = (v = el.style[prop]) ? v : (cs = view.getComputedStyle(el, "")) ? cs[prop] : null; - + // Ignore cases when the margin is correctly reported as 0, the bug only shows // numbers larger. if(prop == 'marginRight' && out != '0px' && !supports.RightMargin){ + cleaner = ELEMENT.getRightMarginFixCleaner(el); display = this.getStyle('display'); el.style.display = 'inline-block'; out = view.getComputedStyle(el, '').marginRight; el.style.display = display; + cleaner(); } - + if(prop == 'backgroundColor' && out == 'rgba(0, 0, 0, 0)' && !supports.TransparentColor){ out = 'transparent'; } return out; } : - function(prop){ + function (prop) { var el = this.dom, m, cs; if (el == document) { return null; } - - if (prop == 'opacity') { - if (el.style.filter.match) { - m = el.style.filter.match(opacityRe); - if(m){ - var fv = parseFloat(m[1]); - if(!isNaN(fv)){ - return fv ? fv / 100 : 0; + prop = ELEMENT.normalize(prop); + + do { + if (prop == 'opacity') { + if (el.style.filter.match) { + m = el.style.filter.match(opacityRe); + if(m){ + var fv = parseFloat(m[1]); + if(!isNaN(fv)){ + return fv ? fv / 100 : 0; + } } } + return 1; } - return 1; - } - prop = Ext.core.Element.normalize(prop); - return el.style[prop] || ((cs = el.currentStyle) ? cs[prop] : null); - }; + + // the try statement does have a cost, so we avoid it unless we are + // on IE6 + if (!Ext.isIE6) { + return el.style[prop] || ((cs = el.currentStyle) ? cs[prop] : null); + } + + try { + return el.style[prop] || ((cs = el.currentStyle) ? cs[prop] : null); + } catch (e) { + // in some cases, IE6 will throw Invalid Argument for properties + // like fontSize (see in /examples/tabs/tabs.html). + } + + if (!ELEMENT.inheritedProps[prop]) { + break; + } + + el = el.parentNode; + // this is _not_ perfect, but we can only hope that the style we + // need is inherited from a parentNode. If not and since IE won't + // give us the info we need, we are never going to be 100% right. + } while (el); + + // + Ext.log({ + level: 'warn', + msg: 'Failed to get ' + this.dom.id + '.currentStyle.' + prop + }); + // + return null; + } }(), /** @@ -291,7 +351,7 @@ * Wrapper for setting style properties, also takes single object parameter of multiple styles. * @param {String/Object} property The style property to be set, or an object of multiple styles. * @param {String} value (optional) The value to apply to the given property, or null if an object was passed. - * @return {Ext.core.Element} this + * @return {Ext.Element} this */ setStyle : function(prop, value){ var me = this, @@ -300,8 +360,7 @@ if (!me.dom) { return me; } - - if (!Ext.isObject(prop)) { + if (typeof prop === 'string') { tmp = {}; tmp[prop] = value; prop = tmp; @@ -313,7 +372,7 @@ me.setOpacity(value); } else { - me.dom.style[Ext.core.Element.normalize(style)] = value; + me.dom.style[ELEMENT.normalize(style)] = value; } } } @@ -322,10 +381,10 @@ /** * Set the opacity of the element - * @param {Float} opacity The new opacity. 0 = transparent, .5 = 50% visibile, 1 = fully visible, etc + * @param {Number} opacity The new opacity. 0 = transparent, .5 = 50% visibile, 1 = fully visible, etc * @param {Boolean/Object} animate (optional) a standard Element animation config object or true for * the default animation ({duration: .35, easing: 'easeIn'}) - * @return {Ext.core.Element} this + * @return {Ext.Element} this */ setOpacity: function(opacity, animate) { var me = this, @@ -371,7 +430,7 @@ /** * Clears any opacity settings from this element. Required in some cases for IE. - * @return {Ext.core.Element} this + * @return {Ext.Element} this */ clearOpacity : function(){ var style = this.dom.style; @@ -384,11 +443,11 @@ } return this; }, - + /** * @private * Returns 1 if the browser returns the subpixel dimension rounded to the lowest pixel. - * @return {Number} 0 or 1 + * @return {Number} 0 or 1 */ adjustDirect2DDimension: function(dimension) { var me = this, @@ -398,7 +457,7 @@ inlinePosition = dom.style['position'], originIndex = dimension === 'width' ? 0 : 1, floating; - + if (display === 'inline') { dom.style['display'] = 'inline-block'; } @@ -408,16 +467,16 @@ // floating will contain digits that appears after the decimal point // if height or width are set to auto we fallback to msTransformOrigin calculation floating = (parseFloat(me.getStyle(dimension)) || parseFloat(dom.currentStyle.msTransformOrigin.split(' ')[originIndex]) * 2) % 1; - + dom.style['position'] = inlinePosition; - + if (display === 'inline') { dom.style['display'] = inlineDisplay; } return floating; }, - + /** * Returns the offset height of the element * @param {Boolean} contentHeight (optional) true to get the height minus borders and padding @@ -465,7 +524,7 @@ } return height; }, - + /** * Returns the offset width of the element * @param {Boolean} contentWidth (optional) true to get the width minus borders and padding @@ -484,8 +543,8 @@ overflow = style.overflow; me.setStyle({overflow: 'hidden'}); } - - // Fix Opera 10.5x width calculation issues + + // Fix Opera 10.5x width calculation issues if (Ext.isOpera10_5) { if (dom.parentNode.currentStyle.position === 'relative') { parentPosition = dom.parentNode.style.position; @@ -494,7 +553,7 @@ dom.parentNode.style.position = parentPosition; } width = Math.max(width || 0, dom.offsetWidth); - + // Gecko will in some cases report an offsetWidth that is actually less than the width of the // text contents, because it measures fonts with sub-pixel precision but rounds the calculated // value down. Using getBoundingClientRect instead of offsetWidth allows us to get the precise @@ -520,11 +579,11 @@ width++; } } - + if (contentWidth) { width -= (me.getBorderWidth("lr") + me.getPadding("lr")); } - + if (Ext.isIEQuirks) { me.setStyle({ overflow: overflow}); } @@ -537,12 +596,12 @@ /** * Set the width of this Element. - * @param {Mixed} width The new width. This may be one of: