From 315199c156c5b822a857ca236bda123f01a2da37 Mon Sep 17 00:00:00 2001 From: Timmy Willison <4timmywil@gmail.com> Date: Sun, 11 Nov 2018 17:34:43 -0500 Subject: Dimensions: fall back to offsetWidth/Height for border-box in IE - Use getClientRects() to explicitly detect hidden/disconnected elements Close gh-4223 Fixes gh-4102 --- src/css.js | 33 ++++++++++++++++++--------------- test/data/testsuite.css | 4 ++++ test/unit/dimensions.js | 32 +++++++++++++++++++++++++++----- 3 files changed, 49 insertions(+), 20 deletions(-) diff --git a/src/css.js b/src/css.js index cc873994b..f18cf19f2 100644 --- a/src/css.js +++ b/src/css.js @@ -1,9 +1,7 @@ define( [ "./core", - "./var/pnum", "./core/access", "./core/camelCase", - "./var/document", "./var/rcssNum", "./css/var/rnumnonpx", "./css/var/cssExpand", @@ -18,7 +16,7 @@ define( [ "./core/init", "./core/ready", "./selector" // contains -], function( jQuery, pnum, access, camelCase, document, rcssNum, rnumnonpx, cssExpand, +], function( jQuery, access, camelCase, rcssNum, rnumnonpx, cssExpand, getStyles, swap, curCSS, adjustCSS, addGetHookIf, support, finalPropName ) { "use strict"; @@ -122,7 +120,8 @@ function getWidthOrHeight( elem, dimension, extra ) { var styles = getStyles( elem ), val = curCSS( elem, dimension, styles ), isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box", - valueIsBorderBox = isBorderBox; + valueIsBorderBox = isBorderBox, + offsetProp = "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ); // Support: Firefox <=54 // Return a confounding non-pixel value or feign ignorance, as appropriate. @@ -133,22 +132,26 @@ function getWidthOrHeight( elem, dimension, extra ) { val = "auto"; } - // Check for style in case a browser which returns unreliable values - // for getComputedStyle silently falls back to the reliable elem.style - valueIsBorderBox = valueIsBorderBox && - ( support.boxSizingReliable() || val === elem.style[ dimension ] ); // Fall back to offsetWidth/offsetHeight when value is "auto" // This happens for inline elements with no explicit setting (gh-3571) // Support: Android <=4.1 - 4.3 only // Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602) - if ( val === "auto" || - !parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) { - - val = elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ]; - - // offsetWidth/offsetHeight provide border-box values - valueIsBorderBox = true; + // Support: IE 9-11 only + // Also use offsetWidth/offsetHeight for when box sizing is unreliable + // We use getClientRects() to check for hidden/disconnected. + // In those cases, the computed value can be trusted to be border-box + if ( ( isBorderBox && !support.boxSizingReliable() || val === "auto" || + !parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) && + elem.getClientRects().length ) { + + // Where available, offsetWidth/offsetHeight approximate border box dimensions. + // Where not available (e.g., SVG), assume unreliable box-sizing and interpret the + // retrieved value as a content box dimension. + valueIsBorderBox = offsetProp in elem; + if ( valueIsBorderBox ) { + val = elem[ offsetProp ]; + } } // Normalize "" and auto diff --git a/test/data/testsuite.css b/test/data/testsuite.css index f6225df30..b975e44df 100644 --- a/test/data/testsuite.css +++ b/test/data/testsuite.css @@ -142,3 +142,7 @@ section { background:#f0f; display:block; } padding: 0; margin: 0; } + +.border-box, .border-box * { + box-sizing: border-box; +} diff --git a/test/unit/dimensions.js b/test/unit/dimensions.js index ea7793ff9..36b07f11e 100644 --- a/test/unit/dimensions.js +++ b/test/unit/dimensions.js @@ -659,7 +659,9 @@ QUnit.test( "interaction with scrollbars (gh-3589)", function( assert ) { parent = jQuery( "
" ) .css( { position: "absolute", width: "1000px", height: "1000px" } ) .appendTo( "#qunit-fixture" ), - fraction = jQuery( "
" ).appendTo( parent ).width() % 1, + fraction = jQuery.support.boxSizingReliable() ? + jQuery( "
" ).appendTo( parent ).width() % 1 : + 0, borderWidth = 1, padding = 2, size = 100 + fraction, @@ -695,10 +697,8 @@ QUnit.test( "interaction with scrollbars (gh-3589)", function( assert ) { borderBox[ 0 ].offsetWidth; if ( borderBoxLoss > 0 ) { - borderBox.css( { - width: ( size + borderBoxLoss ) + "px", - height: ( size + borderBoxLoss ) + "px" - } ); + borderBox[ 0 ].style.width = ( size + borderBoxLoss ) + "px"; + borderBox[ 0 ].style.height = ( size + borderBoxLoss ) + "px"; } for ( i = 0; i < 3; i++ ) { @@ -750,4 +750,26 @@ QUnit.test( "interaction with scrollbars (gh-3589)", function( assert ) { } } ); +QUnit.test( "outerWidth/Height for table cells and textarea with border-box in IE 11 (gh-4102)", function( assert ) { + assert.expect( 5 ); + var $table = jQuery( "" ).appendTo( "#qunit-fixture" ), + $thead = jQuery( "" ).appendTo( $table ), + $firstTh = jQuery( "" ), + $tbody = jQuery( "" ).appendTo( $table ), + $textarea = jQuery( "
" ), + $secondTh = jQuery( "" ), + $thirdTh = jQuery( "" ), + $td = jQuery( "text