From: Mike Sherov Date: Mon, 10 Dec 2012 23:25:23 +0000 (-0500) Subject: Pass style declarations around for performance improvements and paving the way for... X-Git-Tag: 1.9.0b1~34 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=a918dc8aacb8461321c332f6f3b5756bdda5e8b2;p=jquery.git Pass style declarations around for performance improvements and paving the way for the css array signature Also, simplify the jQuery.css numeric coercion signature --- diff --git a/src/css.js b/src/css.js index 5df4f7efd..37f4d03e0 100644 --- a/src/css.js +++ b/src/css.js @@ -1,4 +1,4 @@ -var curCSS, iframe, +var curCSS, getStyles, iframe, ralpha = /alpha\([^)]*\)/i, ropacity = /opacity\s*=\s*([^)]*)/, rposition = /^(top|right|bottom|left)$/, @@ -47,7 +47,7 @@ function isHidden( elem, el ) { // isHidden might be called from jQuery#filter function; // in that case, element will be second argument elem = el || elem; - return curCSS( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem ); + return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem ); } function showHide( elements, show ) { @@ -76,7 +76,7 @@ function showHide( elements, show ) { values[ index ] = jQuery._data( elem, "olddisplay", css_defaultDisplay(elem.nodeName) ); } } else if ( !values[ index ] && !isHidden( elem ) ) { - jQuery._data( elem, "olddisplay", curCSS( elem, "display" ) ); + jQuery._data( elem, "olddisplay", jQuery.css( elem, "display" ) ); } } @@ -217,7 +217,7 @@ jQuery.extend({ } }, - css: function( elem, name, numeric, extra ) { + css: function( elem, name, extra, styles ) { var val, num, hooks, origName = jQuery.camelCase( name ); @@ -235,7 +235,7 @@ jQuery.extend({ // Otherwise, if a way to get the computed value exists, use that if ( val === undefined ) { - val = curCSS( elem, name ); + val = curCSS( elem, name, styles ); } //convert "normal" to computed value @@ -244,9 +244,9 @@ jQuery.extend({ } // Return, converting to number if forced or a qualifier was provided and val looks numeric - if ( numeric || extra !== undefined ) { + if ( extra ) { num = parseFloat( val ); - return numeric || jQuery.isNumeric( num ) ? num || 0 : val; + return extra === true || jQuery.isNumeric( num ) ? num || 0 : val; } return val; }, @@ -273,18 +273,22 @@ jQuery.extend({ } }); -// NOTE: To any future maintainer, we've window.getComputedStyle +// NOTE: we've included the "window" in window.getComputedStyle // because jsdom on node.js will break without it. if ( window.getComputedStyle ) { - curCSS = function( elem, name ) { - var ret, width, minWidth, maxWidth, - computed = window.getComputedStyle( elem, null ), - style = elem.style; + getStyles = function( elem ) { + return window.getComputedStyle( elem, null ); + }; - if ( computed ) { + curCSS = function( elem, name, _computed ) { + var width, minWidth, maxWidth, + computed = _computed || getStyles( elem ), // getPropertyValue is only needed for .css('filter') in IE9, see #12537 - ret = computed.getPropertyValue( name ) || computed[ name ]; + ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined, + style = elem.style; + + if ( computed ) { if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) { ret = jQuery.style( elem, name ); @@ -295,13 +299,17 @@ if ( window.getComputedStyle ) { // Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) { + + // Remember the original values width = style.width; minWidth = style.minWidth; maxWidth = style.maxWidth; + // Put in the new values to get a computed value out style.minWidth = style.maxWidth = style.width = ret; ret = computed.width; + // Revert the changed values style.width = width; style.minWidth = minWidth; style.maxWidth = maxWidth; @@ -311,9 +319,14 @@ if ( window.getComputedStyle ) { return ret; }; } else if ( document.documentElement.currentStyle ) { - curCSS = function( elem, name ) { - var left, rsLeft, - ret = elem.currentStyle && elem.currentStyle[ name ], + getStyles = function( elem ) { + return elem.currentStyle; + }; + + curCSS = function( elem, name, _computed ) { + var left, rs, rsLeft, + computed = _computed || getStyles( elem ), + ret = computed ? computed[ name ] : undefined, style = elem.style; // Avoid setting ret to empty string here @@ -333,11 +346,12 @@ if ( window.getComputedStyle ) { // Remember the original values left = style.left; - rsLeft = elem.runtimeStyle && elem.runtimeStyle.left; + rs = elem.runtimeStyle; + rsLeft = rs && rs.left; // Put in the new values to get a computed value out if ( rsLeft ) { - elem.runtimeStyle.left = elem.currentStyle.left; + rs.left = elem.currentStyle.left; } style.left = name === "fontSize" ? "1em" : ret; ret = style.pixelLeft + "px"; @@ -345,7 +359,7 @@ if ( window.getComputedStyle ) { // Revert the changed values style.left = left; if ( rsLeft ) { - elem.runtimeStyle.left = rsLeft; + rs.left = rsLeft; } } @@ -360,7 +374,7 @@ function setPositiveNumber( elem, value, subtract ) { value; } -function augmentWidthOrHeight( elem, name, extra, isBorderBox ) { +function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) { var i = extra === ( isBorderBox ? "border" : "content" ) ? // If we already have the right measurement, avoid augmentation 4 : @@ -372,29 +386,26 @@ function augmentWidthOrHeight( elem, name, extra, isBorderBox ) { for ( ; i < 4; i += 2 ) { // both box models exclude margin, so add it if we want it if ( extra === "margin" ) { - // we use jQuery.css instead of curCSS here - // because of the reliableMarginRight CSS hook! - val += jQuery.css( elem, extra + cssExpand[ i ], true ); + val += jQuery.css( elem, extra + cssExpand[ i ], true, styles ); } - // From this point on we use curCSS for maximum performance (relevant in animations) if ( isBorderBox ) { // border-box includes padding, so remove it if we want content if ( extra === "content" ) { - val -= parseFloat( curCSS( elem, "padding" + cssExpand[ i ] ) ) || 0; + val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); } // at this point, extra isn't border nor margin, so remove border if ( extra !== "margin" ) { - val -= parseFloat( curCSS( elem, "border" + cssExpand[ i ] + "Width" ) ) || 0; + val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); } } else { // at this point, extra isn't content, so add padding - val += parseFloat( curCSS( elem, "padding" + cssExpand[ i ] ) ) || 0; + val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); // at this point, extra isn't content nor padding, so add border if ( extra !== "padding" ) { - val += parseFloat( curCSS( elem, "border" + cssExpand[ i ] + "Width" ) ) || 0; + val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); } } } @@ -407,14 +418,15 @@ function getWidthOrHeight( elem, name, extra ) { // Start with offset property, which is equivalent to the border-box value var val = name === "width" ? elem.offsetWidth : elem.offsetHeight, valueIsBorderBox = true, - isBorderBox = jQuery.support.boxSizing && jQuery.css( elem, "boxSizing" ) === "border-box"; + styles = getStyles( elem ), + isBorderBox = jQuery.support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; // some non-html elements return undefined for offsetWidth, so check for null/undefined // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285 // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668 if ( val <= 0 || val == null ) { // Fall back to computed then uncomputed css if necessary - val = curCSS( elem, name ); + val = curCSS( elem, name, styles ); if ( val < 0 || val == null ) { val = elem.style[ name ]; } @@ -438,7 +450,8 @@ function getWidthOrHeight( elem, name, extra ) { elem, name, extra || ( isBorderBox ? "border" : "content" ), - valueIsBorderBox + valueIsBorderBox, + styles ) ) + "px"; } @@ -479,7 +492,7 @@ function css_defaultDisplay( nodeName ) { function actualDisplay( name, doc ) { var elem, display; elem = jQuery( doc.createElement( name ) ); - display = curCSS( elem.appendTo( doc.body )[0], "display" ); + display = jQuery.css( elem.appendTo( doc.body )[0], "display" ); elem.remove(); return display; } @@ -490,7 +503,7 @@ jQuery.each([ "height", "width" ], function( i, name ) { if ( computed ) { // certain elements can have dimension info if we invisibly show them // however, it must have a current display style that would benefit from this - if ( elem.offsetWidth === 0 && rdisplayswap.test( curCSS( elem, "display" ) ) ) { + if ( elem.offsetWidth === 0 && rdisplayswap.test( jQuery.css( elem, "display" ) ) ) { return jQuery.swap( elem, cssShow, function() { return getWidthOrHeight( elem, name, extra ); }); @@ -501,12 +514,14 @@ jQuery.each([ "height", "width" ], function( i, name ) { }, set: function( elem, value, extra ) { + var styles = extra && getStyles( elem ); return setPositiveNumber( elem, value, extra ? augmentWidthOrHeight( elem, name, extra, - jQuery.support.boxSizing && jQuery.css( elem, "boxSizing" ) === "border-box" + jQuery.support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + styles ) : 0 ); } @@ -604,7 +619,7 @@ jQuery(function() { if ( jQuery.expr && jQuery.expr.filters ) { jQuery.expr.filters.hidden = function( elem ) { - return ( elem.offsetWidth === 0 && elem.offsetHeight === 0 ) || (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || curCSS( elem, "display" )) === "none"); + return ( elem.offsetWidth === 0 && elem.offsetHeight === 0 ) || (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || jQuery.css( elem, "display" )) === "none"); }; jQuery.expr.filters.visible = function( elem ) { diff --git a/src/dimensions.js b/src/dimensions.js index c41cce1b3..9e4d5729d 100644 --- a/src/dimensions.js +++ b/src/dimensions.js @@ -31,7 +31,7 @@ jQuery.each( { Height: "height", Width: "width" }, function( name, type ) { return value === undefined ? // Get width or height on the element, requesting but not forcing parseFloat - jQuery.css( elem, type, value, extra ) : + jQuery.css( elem, type, extra ) : // Set width or height on the element jQuery.style( elem, type, value, extra ); diff --git a/src/effects.js b/src/effects.js index da680f0b6..3d9ae7f4b 100644 --- a/src/effects.js +++ b/src/effects.js @@ -420,11 +420,11 @@ Tween.propHooks = { return tween.elem[ tween.prop ]; } - // passing any value as a 4th parameter to .css will automatically + // passing a non empty string as a 3rd parameter to .css will automatically // attempt a parseFloat and fallback to a string if the parse fails // so, simple values such as "10px" are parsed to Float. // complex values such as "rotate(1rad)" are returned as is. - result = jQuery.css( tween.elem, tween.prop, false, "" ); + result = jQuery.css( tween.elem, tween.prop, "auto" ); // Empty strings, null, undefined and "auto" are converted to 0. return !result || result === "auto" ? 0 : result; }, diff --git a/src/offset.js b/src/offset.js index 93446eae4..04c94cade 100644 --- a/src/offset.js +++ b/src/offset.js @@ -108,16 +108,16 @@ jQuery.fn.extend({ } // Add offsetParent borders - parentOffset.top += parseFloat( jQuery.css( offsetParent[ 0 ], "borderTopWidth" ) ) || 0; - parentOffset.left += parseFloat( jQuery.css( offsetParent[ 0 ], "borderLeftWidth" ) ) || 0; + parentOffset.top += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true ); + parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true ); } // Subtract parent offsets and element margins // note: when an element has margin: auto the offsetLeft and marginLeft // are the same in Safari causing offset.left to incorrectly be 0 return { - top: offset.top - parentOffset.top - ( parseFloat( jQuery.css( elem, "marginTop" ) ) || 0 ), - left: offset.left - parentOffset.left - ( parseFloat( jQuery.css( elem, "marginLeft" ) ) || 0 ) + top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ), + left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true) }; },