Optimize width/height retrieval (moved logic to getWH, removed adjustWH). Supplements #9441, #9300.

This commit is contained in:
timmywil 2011-06-06 23:35:16 -04:00
parent 80ad14bd14
commit 75203de743
3 changed files with 51 additions and 73 deletions

View file

@ -172,51 +172,13 @@ jQuery.each(["height", "width"], function( i, name ) {
if ( computed ) { if ( computed ) {
if ( elem.offsetWidth !== 0 ) { if ( elem.offsetWidth !== 0 ) {
val = getWH( elem, name, extra ); return getWH( elem, name, extra );
} else { } else {
jQuery.swap( elem, cssShow, function() { jQuery.swap( elem, cssShow, function() {
val = getWH( elem, name, extra ); val = getWH( elem, name, extra );
}); });
} }
if ( val <= 0 ) {
val = curCSS( elem, name, name );
if ( val === "0px" && currentStyle ) {
val = currentStyle( elem, name, name );
}
if ( val != null ) {
fellback = true;
}
}
if ( !fellback && ( val < 0 || val == null ) ) {
val = elem.style[ name ];
fellback = true;
}
// Should return "auto" instead of 0, use 0 for
// temporary backwards-compat
if ( fellback && ( val === "" || val === "auto" ) ) {
val = "0px";
} else if ( typeof val !== "string" ) {
val += "px";
}
if ( extra ) {
val = parseFloat( val ) || 0;
if ( fellback ) {
val += adjustWH( elem, name, "padding" );
if ( extra !== "padding" ) {
val += adjustWH( elem, name, "border", "Width" );
}
}
if ( extra === "margin" ) {
val += adjustWH( elem, name, "margin" );
}
}
return val; return val;
} }
}, },
@ -224,7 +186,7 @@ jQuery.each(["height", "width"], function( i, name ) {
set: function( elem, value ) { set: function( elem, value ) {
if ( rnumpx.test( value ) ) { if ( rnumpx.test( value ) ) {
// ignore negative width and height values #1599 // ignore negative width and height values #1599
value = parseFloat(value); value = parseFloat( value );
if ( value >= 0 ) { if ( value >= 0 ) {
return value + "px"; return value + "px";
@ -347,36 +309,51 @@ if ( document.documentElement.currentStyle ) {
curCSS = getComputedStyle || currentStyle; curCSS = getComputedStyle || currentStyle;
function getWH( elem, name, extra ) { function getWH( elem, name, extra ) {
var val = name === "width" ? elem.offsetWidth : elem.offsetHeight;
if ( extra === "border" ) { // Start with offset property
return val; var val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
} which = name === "width" ? cssWidth : cssHeight;
if ( !extra ) {
val -= adjustWH( elem, name, "padding");
}
if ( extra !== "margin" ) {
val -= adjustWH( elem, name, "border", "Width");
}
return val;
}
function adjustWH( elem, name, prepend, append ) {
var which = name === "width" ? cssWidth : cssHeight,
val = 0;
if( !append ){
append = "";
}
if ( extra !== "margin" && extra !== "border" ) {
jQuery.each( which, function() { jQuery.each( which, function() {
val += parseFloat( jQuery.css( elem, prepend + this + append ) ) || 0; val -= parseFloat( jQuery.css( elem, "border" + this + "Width" ) ) || 0;
if ( !extra ) {
val -= parseFloat( jQuery.css( elem, "padding" + this ) ) || 0;
}
}); });
}
return val; if ( val > 0 ) {
if ( extra === "margin" ) {
jQuery.each( which, function() {
val += parseFloat( jQuery.css( elem, extra + this ) ) || 0;
});
}
return val + "px";
}
// Fall back to computed then uncomputed css if necessary
val = curCSS( elem, name, name );
if ( val < 0 || val == null ) {
val = elem.style[ name ] || 0;
}
// Normalize "", auto, and prepare for extra
val = parseFloat( val ) || 0;
// Add padding, border, margin
if ( extra ) {
jQuery.each( which, function() {
val += parseFloat( jQuery.css( elem, "padding" + this ) ) || 0;
if ( extra !== "padding" ) {
val += parseFloat( jQuery.css( elem, "border" + this + "Width" ) ) || 0;
}
if ( extra === "margin" ) {
val += parseFloat( jQuery.css( elem, extra + this ) ) || 0;
}
});
}
return val + "px";
} }
if ( jQuery.expr && jQuery.expr.filters ) { if ( jQuery.expr && jQuery.expr.filters ) {

View file

@ -1,12 +1,12 @@
(function( jQuery ) { (function( jQuery ) {
// Create innerHeight, innerWidth, outerHeight and outerWidth methods // Create width, height, innerHeight, innerWidth, outerHeight and outerWidth methods
jQuery.each([ "Height", "Width" ], function( i, name ) { jQuery.each([ "Height", "Width" ], function( i, name ) {
var type = name.toLowerCase(); var type = name.toLowerCase();
// innerHeight and innerWidth // innerHeight and innerWidth
jQuery.fn["inner" + name] = function() { jQuery.fn[ "inner" + name ] = function() {
var elem = this[0]; var elem = this[0];
return elem && elem.style ? return elem && elem.style ?
parseFloat( jQuery.css( elem, type, "padding" ) ) : parseFloat( jQuery.css( elem, type, "padding" ) ) :
@ -14,7 +14,7 @@ jQuery.each([ "Height", "Width" ], function( i, name ) {
}; };
// outerHeight and outerWidth // outerHeight and outerWidth
jQuery.fn["outer" + name] = function( margin ) { jQuery.fn[ "outer" + name ] = function( margin ) {
var elem = this[0]; var elem = this[0];
return elem && elem.style ? return elem && elem.style ?
parseFloat( jQuery.css( elem, type, margin ? "margin" : "border" ) ) : parseFloat( jQuery.css( elem, type, margin ? "margin" : "border" ) ) :

View file

@ -214,23 +214,24 @@ test("outerWidth()", function() {
test("child of a hidden elem has accurate inner/outer/Width()/Height() see #9441 #9300", function() { test("child of a hidden elem has accurate inner/outer/Width()/Height() see #9441 #9300", function() {
expect(8); expect(8);
//setup html // setup html
var $divNormal = jQuery( '<div>' ).css({ width: "100px", border: "10px solid white", padding: "2px", margin: "3px" }); var $divNormal = jQuery("<div>").css({ width: "100px", height: "100px", border: "10px solid white", padding: "2px", margin: "3px" }),
var $divChild = $divNormal.clone(); $divChild = $divNormal.clone(),
var $divHiddenParent = jQuery( '<div>' ).css( "display", "none" ).append( $divChild ); $divHiddenParent = jQuery("<div>").css( "display", "none" ).append( $divChild ).appendTo("body");
jQuery( 'body' ).append( $divHiddenParent ).append( $divNormal ); $divNormal.appendTo("body");
//tests that child div of a hidden div works the same as a normal div // tests that child div of a hidden div works the same as a normal div
equals( $divChild.width(), $divNormal.width(), "child of a hidden element width() is wrong see #9441" ); equals( $divChild.width(), $divNormal.width(), "child of a hidden element width() is wrong see #9441" );
equals( $divChild.innerWidth(), $divNormal.innerWidth(), "child of a hidden element innerWidth() is wrong see #9441" ); equals( $divChild.innerWidth(), $divNormal.innerWidth(), "child of a hidden element innerWidth() is wrong see #9441" );
equals( $divChild.outerWidth(), $divNormal.outerWidth(), "child of a hidden element outerWidth() is wrong see #9441" ); equals( $divChild.outerWidth(), $divNormal.outerWidth(), "child of a hidden element outerWidth() is wrong see #9441" );
equals( $divChild.outerWidth(true), $divNormal.outerWidth( true ), "child of a hidden element outerWidth( true ) is wrong see #9300" ); equals( $divChild.outerWidth(true), $divNormal.outerWidth( true ), "child of a hidden element outerWidth( true ) is wrong see #9300" );
equals( $divChild.height(), $divNormal.height(), "child of a hidden element height() is wrong see #9441" ); equals( $divChild.height(), $divNormal.height(), "child of a hidden element height() is wrong see #9441" );
equals( $divChild.innerHeight(), $divNormal.innerHeight(), "child of a hidden element innerHeight() is wrong see #9441" ); equals( $divChild.innerHeight(), $divNormal.innerHeight(), "child of a hidden element innerHeight() is wrong see #9441" );
equals( $divChild.outerHeight(), $divNormal.outerHeight(), "child of a hidden element outerHeight() is wrong see #9441" ); equals( $divChild.outerHeight(), $divNormal.outerHeight(), "child of a hidden element outerHeight() is wrong see #9441" );
equals( $divChild.outerHeight(true), $divNormal.outerHeight( true ), "child of a hidden element outerHeight( true ) is wrong see #9300" ); equals( $divChild.outerHeight(true), $divNormal.outerHeight( true ), "child of a hidden element outerHeight( true ) is wrong see #9300" );
//teardown html // teardown html
$divHiddenParent.remove(); $divHiddenParent.remove();
$divNormal.remove(); $divNormal.remove();
}); });