From 6d31477a35bfa70d209522b5e8c7e948b6c4d599 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Go=C5=82=C4=99biowski-Owczarek?= Date: Mon, 14 Oct 2019 18:34:06 +0200 Subject: [PATCH] CSS: Workaround buggy getComputedStyle on table rows in IE/Edge Fixes gh-4490 Closes gh-4503 --- src/css.js | 28 +++++++++++++++++++--------- src/css/support.js | 31 ++++++++++++++++++++++++++++++- test/unit/css.js | 20 ++++++++++++++++++++ test/unit/support.js | 13 +++++++++++++ 4 files changed, 82 insertions(+), 10 deletions(-) diff --git a/src/css.js b/src/css.js index d4c34dbb7..a7a70614f 100644 --- a/src/css.js +++ b/src/css.js @@ -2,6 +2,7 @@ define( [ "./core", "./core/access", "./core/camelCase", + "./core/nodeName", "./var/rcssNum", "./css/var/rnumnonpx", "./css/var/cssExpand", @@ -16,7 +17,7 @@ define( [ "./core/init", "./core/ready", "./selector" // contains -], function( jQuery, access, camelCase, rcssNum, rnumnonpx, cssExpand, +], function( jQuery, access, camelCase, nodeName, rcssNum, rnumnonpx, cssExpand, getStyles, swap, curCSS, adjustCSS, addGetHookIf, support, finalPropName ) { "use strict"; @@ -139,17 +140,26 @@ function getWidthOrHeight( elem, dimension, extra ) { } - // 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) - // 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 + // Support: IE 9 - 11 only + // Use offsetWidth/offsetHeight for when box sizing is unreliable. + // In those cases, the computed value can be trusted to be border-box. if ( ( !support.boxSizingReliable() && isBorderBox || + + // Support: IE 10 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Interestingly, in some cases IE 9 doesn't suffer from this issue. + !support.reliableTrDimensions() && nodeName( elem, "tr" ) || + + // Fall back to offsetWidth/offsetHeight when value is "auto" + // This happens for inline elements with no explicit setting (gh-3571) val === "auto" || + + // Support: Android <=4.1 - 4.3 only + // Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602) !parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) && + + // Make sure the element is visible & connected elem.getClientRects().length ) { isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; diff --git a/src/css/support.js b/src/css/support.js index 9c4da57d9..6d9561def 100644 --- a/src/css/support.js +++ b/src/css/support.js @@ -60,7 +60,7 @@ define( [ } var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal, - reliableMarginLeftVal, + reliableTrDimensionsVal, reliableMarginLeftVal, container = document.createElement( "div" ), div = document.createElement( "div" ); @@ -95,6 +95,35 @@ define( [ scrollboxSize: function() { computeStyleTests(); return scrollboxSizeVal; + }, + + // Support: IE 9 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Behavior in IE 9 is more subtle than in newer versions & it passes + // some versions of this test; make sure not to make it pass there! + reliableTrDimensions: function() { + var table, tr, trChild; + if ( reliableTrDimensionsVal == null ) { + table = document.createElement( "table" ); + tr = document.createElement( "tr" ); + trChild = document.createElement( "div" ); + + table.style.cssText = "position:absolute;left:-11111px"; + tr.style.height = "1px"; + trChild.style.height = "9px"; + + documentElement + .appendChild( table ) + .appendChild( tr ) + .appendChild( trChild ); + + var trStyle = window.getComputedStyle( tr ); + reliableTrDimensionsVal = parseInt( trStyle.height ) > 3; + + documentElement.removeChild( table ); + } + return reliableTrDimensionsVal; } } ); } )(); diff --git a/test/unit/css.js b/test/unit/css.js index 13de4704b..190e6d169 100644 --- a/test/unit/css.js +++ b/test/unit/css.js @@ -1293,6 +1293,26 @@ QUnit.test( "css('width') and css('height') should respect box-sizing, see #1100 assert.equal( el_dis.css( "height" ), el_dis.css( "height", el_dis.css( "height" ) ).css( "height" ), "css('height') is not respecting box-sizing for disconnected element, see #11004" ); } ); +QUnit.test( "table rows width/height should be unaffected by inline styles", function( assert ) { + assert.expect( 2 ); + + var table = jQuery( + "\n" + + " \n" + + " \n" + + "
\n" + + "
\n" + + " \n" + + "
" + ); + var tr = table.find( "tr" ); + + table.appendTo( "#qunit-fixture" ); + + assert.ok( parseInt( tr.css( "width" ) ) > 10, "tr width unaffected by inline style" ); + assert.ok( parseInt( tr.css( "height" ) ) > 10, "tr height unaffected by inline style" ); +} ); + testIframe( "css('width') should work correctly before document ready (#14084)", "css/cssWidthBeforeDocReady.html", diff --git a/test/unit/support.js b/test/unit/support.js index b280e364e..be1d89c9d 100644 --- a/test/unit/support.js +++ b/test/unit/support.js @@ -73,6 +73,7 @@ testIframe( "pixelPosition": true, "radioValue": true, "reliableMarginLeft": true, + "reliableTrDimensions": false, "scrollboxSize": true }, ie_10_11: { @@ -90,6 +91,7 @@ testIframe( "pixelPosition": true, "radioValue": false, "reliableMarginLeft": true, + "reliableTrDimensions": false, "scrollboxSize": true }, ie_9: { @@ -107,6 +109,7 @@ testIframe( "pixelPosition": true, "radioValue": false, "reliableMarginLeft": true, + "reliableTrDimensions": false, "scrollboxSize": false }, chrome: { @@ -124,6 +127,7 @@ testIframe( "pixelPosition": true, "radioValue": true, "reliableMarginLeft": true, + "reliableTrDimensions": true, "scrollboxSize": true }, safari: { @@ -141,6 +145,7 @@ testIframe( "pixelPosition": true, "radioValue": true, "reliableMarginLeft": true, + "reliableTrDimensions": true, "scrollboxSize": true }, safari_9_10: { @@ -158,6 +163,7 @@ testIframe( "pixelPosition": false, "radioValue": true, "reliableMarginLeft": true, + "reliableTrDimensions": true, "scrollboxSize": true }, firefox: { @@ -175,6 +181,7 @@ testIframe( "pixelPosition": true, "radioValue": true, "reliableMarginLeft": true, + "reliableTrDimensions": true, "scrollboxSize": true }, firefox_60: { @@ -192,6 +199,7 @@ testIframe( "pixelPosition": true, "radioValue": true, "reliableMarginLeft": false, + "reliableTrDimensions": true, "scrollboxSize": true }, ios: { @@ -209,6 +217,7 @@ testIframe( "pixelPosition": true, "radioValue": true, "reliableMarginLeft": true, + "reliableTrDimensions": true, "scrollboxSize": true }, ios_9_10: { @@ -226,6 +235,7 @@ testIframe( "pixelPosition": false, "radioValue": true, "reliableMarginLeft": true, + "reliableTrDimensions": true, "scrollboxSize": true }, ios_8: { @@ -243,6 +253,7 @@ testIframe( "pixelPosition": false, "radioValue": true, "reliableMarginLeft": true, + "reliableTrDimensions": true, "scrollboxSize": true }, ios_7: { @@ -260,6 +271,7 @@ testIframe( "pixelPosition": false, "radioValue": true, "reliableMarginLeft": true, + "reliableTrDimensions": true, "scrollboxSize": true }, android: { @@ -277,6 +289,7 @@ testIframe( "pixelPosition": false, "radioValue": true, "reliableMarginLeft": false, + "reliableTrDimensions": true, "scrollboxSize": true } };