Commit a918dc8a authored by Mike Sherov's avatar Mike Sherov

Pass style declarations around for performance improvements and paving the way...

Pass style declarations around for performance improvements and paving the way for the css array signature
Also, simplify the jQuery.css numeric coercion signature
parent aa0e4aad
var curCSS, iframe, var curCSS, getStyles, iframe,
ralpha = /alpha\([^)]*\)/i, ralpha = /alpha\([^)]*\)/i,
ropacity = /opacity\s*=\s*([^)]*)/, ropacity = /opacity\s*=\s*([^)]*)/,
rposition = /^(top|right|bottom|left)$/, rposition = /^(top|right|bottom|left)$/,
...@@ -47,7 +47,7 @@ function isHidden( elem, el ) { ...@@ -47,7 +47,7 @@ function isHidden( elem, el ) {
// isHidden might be called from jQuery#filter function; // isHidden might be called from jQuery#filter function;
// in that case, element will be second argument // in that case, element will be second argument
elem = el || elem; 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 ) { function showHide( elements, show ) {
...@@ -76,7 +76,7 @@ function showHide( elements, show ) { ...@@ -76,7 +76,7 @@ function showHide( elements, show ) {
values[ index ] = jQuery._data( elem, "olddisplay", css_defaultDisplay(elem.nodeName) ); values[ index ] = jQuery._data( elem, "olddisplay", css_defaultDisplay(elem.nodeName) );
} }
} else if ( !values[ index ] && !isHidden( elem ) ) { } 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({ ...@@ -217,7 +217,7 @@ jQuery.extend({
} }
}, },
css: function( elem, name, numeric, extra ) { css: function( elem, name, extra, styles ) {
var val, num, hooks, var val, num, hooks,
origName = jQuery.camelCase( name ); origName = jQuery.camelCase( name );
...@@ -235,7 +235,7 @@ jQuery.extend({ ...@@ -235,7 +235,7 @@ jQuery.extend({
// Otherwise, if a way to get the computed value exists, use that // Otherwise, if a way to get the computed value exists, use that
if ( val === undefined ) { if ( val === undefined ) {
val = curCSS( elem, name ); val = curCSS( elem, name, styles );
} }
//convert "normal" to computed value //convert "normal" to computed value
...@@ -244,9 +244,9 @@ jQuery.extend({ ...@@ -244,9 +244,9 @@ jQuery.extend({
} }
// Return, converting to number if forced or a qualifier was provided and val looks numeric // Return, converting to number if forced or a qualifier was provided and val looks numeric
if ( numeric || extra !== undefined ) { if ( extra ) {
num = parseFloat( val ); num = parseFloat( val );
return numeric || jQuery.isNumeric( num ) ? num || 0 : val; return extra === true || jQuery.isNumeric( num ) ? num || 0 : val;
} }
return val; return val;
}, },
...@@ -273,18 +273,22 @@ jQuery.extend({ ...@@ -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. // because jsdom on node.js will break without it.
if ( window.getComputedStyle ) { if ( window.getComputedStyle ) {
curCSS = function( elem, name ) { getStyles = function( elem ) {
var ret, width, minWidth, maxWidth, return window.getComputedStyle( elem, null );
computed = window.getComputedStyle( elem, null ), };
style = elem.style;
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 // 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 ) ) { if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) {
ret = jQuery.style( elem, name ); ret = jQuery.style( elem, name );
...@@ -295,13 +299,17 @@ if ( window.getComputedStyle ) { ...@@ -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 // 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 // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values
if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) { if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {
// Remember the original values
width = style.width; width = style.width;
minWidth = style.minWidth; minWidth = style.minWidth;
maxWidth = style.maxWidth; maxWidth = style.maxWidth;
// Put in the new values to get a computed value out
style.minWidth = style.maxWidth = style.width = ret; style.minWidth = style.maxWidth = style.width = ret;
ret = computed.width; ret = computed.width;
// Revert the changed values
style.width = width; style.width = width;
style.minWidth = minWidth; style.minWidth = minWidth;
style.maxWidth = maxWidth; style.maxWidth = maxWidth;
...@@ -311,9 +319,14 @@ if ( window.getComputedStyle ) { ...@@ -311,9 +319,14 @@ if ( window.getComputedStyle ) {
return ret; return ret;
}; };
} else if ( document.documentElement.currentStyle ) { } else if ( document.documentElement.currentStyle ) {
curCSS = function( elem, name ) { getStyles = function( elem ) {
var left, rsLeft, return elem.currentStyle;
ret = elem.currentStyle && elem.currentStyle[ name ], };
curCSS = function( elem, name, _computed ) {
var left, rs, rsLeft,
computed = _computed || getStyles( elem ),
ret = computed ? computed[ name ] : undefined,
style = elem.style; style = elem.style;
// Avoid setting ret to empty string here // Avoid setting ret to empty string here
...@@ -333,11 +346,12 @@ if ( window.getComputedStyle ) { ...@@ -333,11 +346,12 @@ if ( window.getComputedStyle ) {
// Remember the original values // Remember the original values
left = style.left; 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 // Put in the new values to get a computed value out
if ( rsLeft ) { if ( rsLeft ) {
elem.runtimeStyle.left = elem.currentStyle.left; rs.left = elem.currentStyle.left;
} }
style.left = name === "fontSize" ? "1em" : ret; style.left = name === "fontSize" ? "1em" : ret;
ret = style.pixelLeft + "px"; ret = style.pixelLeft + "px";
...@@ -345,7 +359,7 @@ if ( window.getComputedStyle ) { ...@@ -345,7 +359,7 @@ if ( window.getComputedStyle ) {
// Revert the changed values // Revert the changed values
style.left = left; style.left = left;
if ( rsLeft ) { if ( rsLeft ) {
elem.runtimeStyle.left = rsLeft; rs.left = rsLeft;
} }
} }
...@@ -360,7 +374,7 @@ function setPositiveNumber( elem, value, subtract ) { ...@@ -360,7 +374,7 @@ function setPositiveNumber( elem, value, subtract ) {
value; value;
} }
function augmentWidthOrHeight( elem, name, extra, isBorderBox ) { function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
var i = extra === ( isBorderBox ? "border" : "content" ) ? var i = extra === ( isBorderBox ? "border" : "content" ) ?
// If we already have the right measurement, avoid augmentation // If we already have the right measurement, avoid augmentation
4 : 4 :
...@@ -372,29 +386,26 @@ function augmentWidthOrHeight( elem, name, extra, isBorderBox ) { ...@@ -372,29 +386,26 @@ function augmentWidthOrHeight( elem, name, extra, isBorderBox ) {
for ( ; i < 4; i += 2 ) { for ( ; i < 4; i += 2 ) {
// both box models exclude margin, so add it if we want it // both box models exclude margin, so add it if we want it
if ( extra === "margin" ) { if ( extra === "margin" ) {
// we use jQuery.css instead of curCSS here val += jQuery.css( elem, extra + cssExpand[ i ], true, styles );
// because of the reliableMarginRight CSS hook!
val += jQuery.css( elem, extra + cssExpand[ i ], true );
} }
// From this point on we use curCSS for maximum performance (relevant in animations)
if ( isBorderBox ) { if ( isBorderBox ) {
// border-box includes padding, so remove it if we want content // border-box includes padding, so remove it if we want content
if ( extra === "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 // at this point, extra isn't border nor margin, so remove border
if ( extra !== "margin" ) { if ( extra !== "margin" ) {
val -= parseFloat( curCSS( elem, "border" + cssExpand[ i ] + "Width" ) ) || 0; val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
} }
} else { } else {
// at this point, extra isn't content, so add padding // 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 // at this point, extra isn't content nor padding, so add border
if ( extra !== "padding" ) { 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 ) { ...@@ -407,14 +418,15 @@ function getWidthOrHeight( elem, name, extra ) {
// Start with offset property, which is equivalent to the border-box value // Start with offset property, which is equivalent to the border-box value
var val = name === "width" ? elem.offsetWidth : elem.offsetHeight, var val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
valueIsBorderBox = true, 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 // some non-html elements return undefined for offsetWidth, so check for null/undefined
// svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285 // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
// MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668 // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
if ( val <= 0 || val == null ) { if ( val <= 0 || val == null ) {
// Fall back to computed then uncomputed css if necessary // Fall back to computed then uncomputed css if necessary
val = curCSS( elem, name ); val = curCSS( elem, name, styles );
if ( val < 0 || val == null ) { if ( val < 0 || val == null ) {
val = elem.style[ name ]; val = elem.style[ name ];
} }
...@@ -438,7 +450,8 @@ function getWidthOrHeight( elem, name, extra ) { ...@@ -438,7 +450,8 @@ function getWidthOrHeight( elem, name, extra ) {
elem, elem,
name, name,
extra || ( isBorderBox ? "border" : "content" ), extra || ( isBorderBox ? "border" : "content" ),
valueIsBorderBox valueIsBorderBox,
styles
) )
) + "px"; ) + "px";
} }
...@@ -479,7 +492,7 @@ function css_defaultDisplay( nodeName ) { ...@@ -479,7 +492,7 @@ function css_defaultDisplay( nodeName ) {
function actualDisplay( name, doc ) { function actualDisplay( name, doc ) {
var elem, display; var elem, display;
elem = jQuery( doc.createElement( name ) ); elem = jQuery( doc.createElement( name ) );
display = curCSS( elem.appendTo( doc.body )[0], "display" ); display = jQuery.css( elem.appendTo( doc.body )[0], "display" );
elem.remove(); elem.remove();
return display; return display;
} }
...@@ -490,7 +503,7 @@ jQuery.each([ "height", "width" ], function( i, name ) { ...@@ -490,7 +503,7 @@ jQuery.each([ "height", "width" ], function( i, name ) {
if ( computed ) { if ( computed ) {
// certain elements can have dimension info if we invisibly show them // certain elements can have dimension info if we invisibly show them
// however, it must have a current display style that would benefit from this // 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 jQuery.swap( elem, cssShow, function() {
return getWidthOrHeight( elem, name, extra ); return getWidthOrHeight( elem, name, extra );
}); });
...@@ -501,12 +514,14 @@ jQuery.each([ "height", "width" ], function( i, name ) { ...@@ -501,12 +514,14 @@ jQuery.each([ "height", "width" ], function( i, name ) {
}, },
set: function( elem, value, extra ) { set: function( elem, value, extra ) {
var styles = extra && getStyles( elem );
return setPositiveNumber( elem, value, extra ? return setPositiveNumber( elem, value, extra ?
augmentWidthOrHeight( augmentWidthOrHeight(
elem, elem,
name, name,
extra, extra,
jQuery.support.boxSizing && jQuery.css( elem, "boxSizing" ) === "border-box" jQuery.support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
styles
) : 0 ) : 0
); );
} }
...@@ -604,7 +619,7 @@ jQuery(function() { ...@@ -604,7 +619,7 @@ jQuery(function() {
if ( jQuery.expr && jQuery.expr.filters ) { if ( jQuery.expr && jQuery.expr.filters ) {
jQuery.expr.filters.hidden = function( elem ) { 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 ) { jQuery.expr.filters.visible = function( elem ) {
......
...@@ -31,7 +31,7 @@ jQuery.each( { Height: "height", Width: "width" }, function( name, type ) { ...@@ -31,7 +31,7 @@ jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
return value === undefined ? return value === undefined ?
// Get width or height on the element, requesting but not forcing parseFloat // 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 // Set width or height on the element
jQuery.style( elem, type, value, extra ); jQuery.style( elem, type, value, extra );
......
...@@ -420,11 +420,11 @@ Tween.propHooks = { ...@@ -420,11 +420,11 @@ Tween.propHooks = {
return tween.elem[ tween.prop ]; 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 // attempt a parseFloat and fallback to a string if the parse fails
// so, simple values such as "10px" are parsed to Float. // so, simple values such as "10px" are parsed to Float.
// complex values such as "rotate(1rad)" are returned as is. // 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. // Empty strings, null, undefined and "auto" are converted to 0.
return !result || result === "auto" ? 0 : result; return !result || result === "auto" ? 0 : result;
}, },
......
...@@ -108,16 +108,16 @@ jQuery.fn.extend({ ...@@ -108,16 +108,16 @@ jQuery.fn.extend({
} }
// Add offsetParent borders // Add offsetParent borders
parentOffset.top += parseFloat( jQuery.css( offsetParent[ 0 ], "borderTopWidth" ) ) || 0; parentOffset.top += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true );
parentOffset.left += parseFloat( jQuery.css( offsetParent[ 0 ], "borderLeftWidth" ) ) || 0; parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true );
} }
// Subtract parent offsets and element margins // Subtract parent offsets and element margins
// note: when an element has margin: auto the offsetLeft and marginLeft // note: when an element has margin: auto the offsetLeft and marginLeft
// are the same in Safari causing offset.left to incorrectly be 0 // are the same in Safari causing offset.left to incorrectly be 0
return { return {
top: offset.top - parentOffset.top - ( parseFloat( jQuery.css( elem, "marginTop" ) ) || 0 ), top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
left: offset.left - parentOffset.left - ( parseFloat( jQuery.css( elem, "marginLeft" ) ) || 0 ) left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true)
}; };
}, },
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment