]> source.dussan.org Git - jquery.git/commitdiff
CSS: Make .css("width") & .css("height") return fractional values
authorMichał Gołębiowski <m.goleb@gmail.com>
Wed, 1 Jul 2015 23:20:18 +0000 (01:20 +0200)
committerMichał Gołębiowski <m.goleb@gmail.com>
Tue, 7 Jul 2015 16:14:04 +0000 (18:14 +0200)
Fixes gh-1724
Closes gh-2454
Refs gh-2439

src/css.js
src/css/support.js
test/unit/css.js
test/unit/dimensions.js
test/unit/support.js

index 24ddb6708660dc4e313be053bf8ddd6540da7332..43ba09cd3cbe0af5263f0a2f2d172ada458cc2d4 100644 (file)
@@ -115,21 +115,28 @@ function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
 function getWidthOrHeight( elem, name, extra ) {
 
        // Start with offset property, which is equivalent to the border-box value
-       var valueIsBorderBox = true,
-               val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
+       var val,
+               valueIsBorderBox = true,
                styles = getStyles( elem ),
                isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
 
-       // Support: IE11 only
-       // In IE 11 fullscreen elements inside of an iframe have
-       // 100x too small dimensions (gh-1764).
-       if ( document.msFullscreenElement && window.top !== window ) {
-               // Support: IE11 only
+       if ( support.gBCRDimensions() ) {
+               // Support: IE <= 11 only
                // Running getBoundingClientRect on a disconnected node
                // in IE throws an error.
                if ( elem.getClientRects().length ) {
-                       val = Math.round( elem.getBoundingClientRect()[ name ] * 100 );
+                       val = elem.getBoundingClientRect()[ name ];
                }
+       } else {
+               // In IE8 gBCR doesn't report width & height; we need to fall back to offset*.
+               val = name === "width" ? elem.offsetWidth : elem.offsetHeight;
+       }
+
+       // Support: IE11 only
+       // In IE 11 fullscreen elements inside of an iframe have
+       // 100x too small dimensions (gh-1764).
+       if ( document.msFullscreenElement && window.top !== window ) {
+               val *= 100;
        }
 
        // some non-html elements return undefined for offsetWidth, so check for null/undefined
@@ -320,7 +327,13 @@ jQuery.each([ "height", "width" ], function( i, name ) {
                                // certain elements can have dimension info if we invisibly show them
                                // however, it must have a current display style that would benefit from this
                                return rdisplayswap.test( jQuery.css( elem, "display" ) ) &&
-                                       elem.offsetWidth === 0 ?
+                                       // Support: Safari 8+
+                                       // Table columns in Safari have non-zero offsetWidth & zero
+                                       // getBoundingClientRect().width unless display is changed.
+                                       // Support: IE <= 11 only
+                                       // Running getBoundingClientRect on a disconnected node
+                                       // in IE throws an error.
+                                       ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ?
                                                swap( elem, cssShow, function() {
                                                        return getWidthOrHeight( elem, name, extra );
                                                }) :
index 17848d5356b26b8c73ca85f1575a1ca099211873..854fa6b3603e3e2cfc9a792d83754175151fd40a 100644 (file)
@@ -4,8 +4,8 @@ define([
 ], function( jQuery, support ) {
 
 (function() {
-       var div, container, style, a, pixelPositionVal, boxSizingReliableVal, pixelMarginRightVal,
-               reliableHiddenOffsetsVal, reliableMarginRightVal;
+       var div, container, style, a, pixelPositionVal, boxSizingReliableVal, gBCRDimensionsVal,
+               pixelMarginRightVal, reliableHiddenOffsetsVal, reliableMarginRightVal;
 
        // Setup
        div = document.createElement( "div" );
@@ -55,6 +55,13 @@ define([
                        return boxSizingReliableVal;
                },
 
+               gBCRDimensions: function() {
+                       if ( pixelPositionVal == null ) {
+                               computeStyleTests();
+                       }
+                       return gBCRDimensionsVal;
+               },
+
                pixelMarginRight: function() {
                        // Support: Android 4.0-4.3
                        if ( pixelPositionVal == null ) {
@@ -105,6 +112,10 @@ define([
                pixelPositionVal = boxSizingReliableVal = false;
                pixelMarginRightVal = reliableMarginRightVal = true;
 
+               // Support: IE<9
+               // In IE8 gBCR doesn't report width & height.
+               gBCRDimensionsVal = !!div.getBoundingClientRect().width;
+
                // Check for getComputedStyle so that this code is not run in IE<9.
                if ( window.getComputedStyle ) {
                        divStyle = window.getComputedStyle( div );
index 34620d05e3c7b5d36143007d2b3facd83a1ffe4e..9c3a186d074e44376425becb1f7bd4c847d7c9b0 100644 (file)
@@ -904,6 +904,52 @@ testIframeWithCallback( "css('width') should work correctly before document read
        }
 );
 
+( function() {
+       var supportsFractionalGBCR,
+               qunitFixture = document.getElementById( "qunit-fixture" ),
+               div = document.createElement( "div" );
+       div.style.width = "3.3px";
+       qunitFixture.appendChild( div );
+       supportsFractionalGBCR = jQuery.support.gBCRDimensions() &&
+               div.getBoundingClientRect().width.toFixed(1) === "3.3";
+       qunitFixture.removeChild( div );
+
+       test( "css('width') and css('height') should return fractional values for nodes in the document", function() {
+               if ( !supportsFractionalGBCR ) {
+                       expect( 1 );
+                       ok( true, "This browser doesn't support fractional values in getBoundingClientRect()" );
+                       return;
+               }
+
+               expect( 2 );
+
+               var el = jQuery( "<div class='test-div'></div>" ).appendTo( "#qunit-fixture" );
+               jQuery( "<style>.test-div { width: 33.3px; height: 88.8px; }</style>" ).appendTo( "#qunit-fixture" );
+
+               equal( Number( el.css( "width" ).replace( /px$/, "" ) ).toFixed( 1 ), "33.3",
+                       "css('width') should return fractional values" );
+               equal( Number( el.css( "height" ).replace( /px$/, "" ) ).toFixed( 1 ), "88.8",
+                       "css('height') should return fractional values" );
+       } );
+
+       test( "css('width') and css('height') should return fractional values for disconnected nodes", function() {
+               if ( !supportsFractionalGBCR ) {
+                       expect( 1 );
+                       ok( true, "This browser doesn't support fractional values in getBoundingClientRect()" );
+                       return;
+               }
+
+               expect( 2 );
+
+               var el = jQuery( "<div style='width: 33.3px; height: 88.8px;'></div>" );
+
+               equal( Number( el.css( "width" ).replace( /px$/, "" ) ).toFixed( 1 ), "33.3",
+                       "css('width') should return fractional values" );
+               equal( Number( el.css( "height" ).replace( /px$/, "" ) ).toFixed( 1 ), "88.8",
+                       "css('height') should return fractional values" );
+       } );
+} )();
+
 test("certain css values of 'normal' should be convertable to a number, see #8627", function() {
        expect ( 3 );
 
index c03b96c8bfe98b5fa05650ef38f36a75c313508d..f4a35981bb655ae4fd9a051a6bcfc9b7954c7131 100644 (file)
@@ -258,10 +258,12 @@ test("child of a hidden elem (or unconnected node) has accurate inner/outer/Widt
        equal( $divChild.outerWidth(), $divNormal.outerWidth(), "child of a hidden element outerWidth() is wrong see #9441" );
        equal( $divChild.outerWidth(true), $divNormal.outerWidth( true ), "child of a hidden element outerWidth( true ) is wrong see #9300" );
 
-       equal( $divChild.height(), $divNormal.height(), "child of a hidden element height() is wrong see #9441" );
-       equal( $divChild.innerHeight(), $divNormal.innerHeight(), "child of a hidden element innerHeight() is wrong see #9441" );
-       equal( $divChild.outerHeight(), $divNormal.outerHeight(), "child of a hidden element outerHeight() is wrong see #9441" );
-       equal( $divChild.outerHeight(true), $divNormal.outerHeight( true ), "child of a hidden element outerHeight( true ) is wrong see #9300" );
+       // Support: IE 10-11, Edge
+       // Child height is not always decimal
+       equal( $divChild.height().toFixed( 3 ), $divNormal.height().toFixed( 3 ), "child of a hidden element height() is wrong see #9441" );
+       equal( $divChild.innerHeight().toFixed( 3 ), $divNormal.innerHeight().toFixed( 3 ), "child of a hidden element innerHeight() is wrong see #9441" );
+       equal( $divChild.outerHeight().toFixed( 3 ), $divNormal.outerHeight().toFixed( 3 ), "child of a hidden element outerHeight() is wrong see #9441" );
+       equal( $divChild.outerHeight( true ).toFixed( 3 ), $divNormal.outerHeight( true ).toFixed( 3 ), "child of a hidden element outerHeight( true ) is wrong see #9300" );
 
        // tests that child div of an unconnected div works the same as a normal div
        equal( $divUnconnected.width(), $divNormal.width(), "unconnected element width() is wrong see #9441" );
@@ -269,10 +271,12 @@ test("child of a hidden elem (or unconnected node) has accurate inner/outer/Widt
        equal( $divUnconnected.outerWidth(), $divNormal.outerWidth(), "unconnected element outerWidth() is wrong see #9441" );
        equal( $divUnconnected.outerWidth(true), $divNormal.outerWidth( true ), "unconnected element outerWidth( true ) is wrong see #9300" );
 
-       equal( $divUnconnected.height(), $divNormal.height(), "unconnected element height() is wrong see #9441" );
-       equal( $divUnconnected.innerHeight(), $divNormal.innerHeight(), "unconnected element innerHeight() is wrong see #9441" );
-       equal( $divUnconnected.outerHeight(), $divNormal.outerHeight(), "unconnected element outerHeight() is wrong see #9441" );
-       equal( $divUnconnected.outerHeight(true), $divNormal.outerHeight( true ), "unconnected element outerHeight( true ) is wrong see #9300" );
+       // Support: IE 10-11, Edge
+       // Child height is not always decimal
+       equal( $divUnconnected.height().toFixed( 3 ), $divNormal.height().toFixed( 3 ), "unconnected element height() is wrong see #9441" );
+       equal( $divUnconnected.innerHeight().toFixed( 3 ), $divNormal.innerHeight().toFixed( 3 ), "unconnected element innerHeight() is wrong see #9441" );
+       equal( $divUnconnected.outerHeight().toFixed( 3 ), $divNormal.outerHeight().toFixed( 3 ), "unconnected element outerHeight() is wrong see #9441" );
+       equal( $divUnconnected.outerHeight( true ).toFixed( 3 ), $divNormal.outerHeight( true ).toFixed( 3 ), "unconnected element outerHeight( true ) is wrong see #9300" );
 
        // teardown html
        $divHiddenParent.remove();
@@ -329,10 +333,12 @@ test("box-sizing:border-box child of a hidden elem (or unconnected node) has acc
        equal( $divChild.outerWidth(), $divNormal.outerWidth(), "child of a hidden element outerWidth() is wrong see #10413" );
        equal( $divChild.outerWidth(true), $divNormal.outerWidth( true ), "child of a hidden element outerWidth( true ) is wrong see #10413" );
 
-       equal( $divChild.height(), $divNormal.height(), "child of a hidden element height() is wrong see #10413" );
-       equal( $divChild.innerHeight(), $divNormal.innerHeight(), "child of a hidden element innerHeight() is wrong see #10413" );
-       equal( $divChild.outerHeight(), $divNormal.outerHeight(), "child of a hidden element outerHeight() is wrong see #10413" );
-       equal( $divChild.outerHeight(true), $divNormal.outerHeight( true ), "child of a hidden element outerHeight( true ) is wrong see #10413" );
+       // Support: IE 10-11, Edge
+       // Child height is not always decimal
+       equal( $divChild.height().toFixed( 3 ), $divNormal.height().toFixed( 3 ), "child of a hidden element height() is wrong see #10413" );
+       equal( $divChild.innerHeight().toFixed( 3 ), $divNormal.innerHeight().toFixed( 3 ), "child of a hidden element innerHeight() is wrong see #10413" );
+       equal( $divChild.outerHeight().toFixed( 3 ), $divNormal.outerHeight().toFixed( 3 ), "child of a hidden element outerHeight() is wrong see #10413" );
+       equal( $divChild.outerHeight( true ).toFixed( 3 ), $divNormal.outerHeight( true ).toFixed( 3 ), "child of a hidden element outerHeight( true ) is wrong see #10413" );
 
        // tests that child div of an unconnected div works the same as a normal div
        equal( $divUnconnected.width(), $divNormal.width(), "unconnected element width() is wrong see #10413" );
@@ -340,10 +346,12 @@ test("box-sizing:border-box child of a hidden elem (or unconnected node) has acc
        equal( $divUnconnected.outerWidth(), $divNormal.outerWidth(), "unconnected element outerWidth() is wrong see #10413" );
        equal( $divUnconnected.outerWidth(true), $divNormal.outerWidth( true ), "unconnected element outerWidth( true ) is wrong see #10413" );
 
-       equal( $divUnconnected.height(), $divNormal.height(), "unconnected element height() is wrong see #10413" );
-       equal( $divUnconnected.innerHeight(), $divNormal.innerHeight(), "unconnected element innerHeight() is wrong see #10413" );
-       equal( $divUnconnected.outerHeight(), $divNormal.outerHeight(), "unconnected element outerHeight() is wrong see #10413" );
-       equal( $divUnconnected.outerHeight(true), $divNormal.outerHeight( true ), "unconnected element outerHeight( true ) is wrong see #10413" );
+       // Support: IE 10-11, Edge
+       // Child height is not always decimal
+       equal( $divUnconnected.height().toFixed( 3 ), $divNormal.height().toFixed( 3 ), "unconnected element height() is wrong see #10413" );
+       equal( $divUnconnected.innerHeight().toFixed( 3 ), $divNormal.innerHeight().toFixed( 3 ), "unconnected element innerHeight() is wrong see #10413" );
+       equal( $divUnconnected.outerHeight().toFixed( 3 ), $divNormal.outerHeight().toFixed( 3 ), "unconnected element outerHeight() is wrong see #10413" );
+       equal( $divUnconnected.outerHeight( true ).toFixed( 3 ), $divNormal.outerHeight( true ).toFixed( 3 ), "unconnected element outerHeight( true ) is wrong see #10413" );
 
        // teardown html
        $divHiddenParent.remove();
index 07478e014f5423659857f1bda81874f51c2363e6..b5865b2bd4fc21e91083338c7a3dba6af567a6ee 100644 (file)
@@ -82,6 +82,7 @@ testIframeWithCallback( "Check CSP (https://developer.mozilla.org/en-US/docs/Sec
                        "cssFloat": true,
                        "deleteExpando": true,
                        "focusin": false,
+                       "gBCRDimensions": true,
                        "html5Clone": true,
                        "htmlSerialize": true,
                        "input": true,
@@ -114,6 +115,7 @@ testIframeWithCallback( "Check CSP (https://developer.mozilla.org/en-US/docs/Sec
                        "cssFloat": true,
                        "deleteExpando": true,
                        "focusin": true,
+                       "gBCRDimensions": true,
                        "html5Clone": true,
                        "htmlSerialize": true,
                        "input": true,
@@ -146,6 +148,7 @@ testIframeWithCallback( "Check CSP (https://developer.mozilla.org/en-US/docs/Sec
                        "cssFloat": true,
                        "deleteExpando": true,
                        "focusin": true,
+                       "gBCRDimensions": true,
                        "html5Clone": true,
                        "htmlSerialize": true,
                        "input": true,
@@ -178,6 +181,7 @@ testIframeWithCallback( "Check CSP (https://developer.mozilla.org/en-US/docs/Sec
                        "cssFloat": false,
                        "deleteExpando": false,
                        "focusin": true,
+                       "gBCRDimensions": false,
                        "html5Clone": false,
                        "htmlSerialize": false,
                        "input": false,
@@ -212,6 +216,7 @@ testIframeWithCallback( "Check CSP (https://developer.mozilla.org/en-US/docs/Sec
                        "cssFloat": true,
                        "deleteExpando": true,
                        "focusin": false,
+                       "gBCRDimensions": true,
                        "html5Clone": true,
                        "htmlSerialize": true,
                        "input": true,
@@ -244,6 +249,7 @@ testIframeWithCallback( "Check CSP (https://developer.mozilla.org/en-US/docs/Sec
                        "cssFloat": true,
                        "deleteExpando": true,
                        "focusin": false,
+                       "gBCRDimensions": true,
                        "html5Clone": true,
                        "htmlSerialize": true,
                        "input": true,
@@ -276,6 +282,7 @@ testIframeWithCallback( "Check CSP (https://developer.mozilla.org/en-US/docs/Sec
                        "cssFloat": true,
                        "deleteExpando": true,
                        "focusin": false,
+                       "gBCRDimensions": true,
                        "html5Clone": true,
                        "htmlSerialize": true,
                        "input": true,
@@ -308,6 +315,7 @@ testIframeWithCallback( "Check CSP (https://developer.mozilla.org/en-US/docs/Sec
                        "cssFloat": true,
                        "deleteExpando": true,
                        "focusin": false,
+                       "gBCRDimensions": true,
                        "html5Clone": true,
                        "htmlSerialize": true,
                        "input": true,
@@ -340,6 +348,7 @@ testIframeWithCallback( "Check CSP (https://developer.mozilla.org/en-US/docs/Sec
                        "cssFloat": true,
                        "deleteExpando": true,
                        "focusin": false,
+                       "gBCRDimensions": true,
                        "html5Clone": true,
                        "htmlSerialize": true,
                        "input": true,
@@ -372,6 +381,7 @@ testIframeWithCallback( "Check CSP (https://developer.mozilla.org/en-US/docs/Sec
                        "cssFloat": true,
                        "deleteExpando": true,
                        "focusin": false,
+                       "gBCRDimensions": true,
                        "html5Clone": true,
                        "htmlSerialize": true,
                        "input": true,
@@ -404,6 +414,7 @@ testIframeWithCallback( "Check CSP (https://developer.mozilla.org/en-US/docs/Sec
                        "cssFloat": true,
                        "deleteExpando": true,
                        "focusin": false,
+                       "gBCRDimensions": true,
                        "html5Clone": true,
                        "htmlSerialize": true,
                        "input": true,
@@ -436,6 +447,7 @@ testIframeWithCallback( "Check CSP (https://developer.mozilla.org/en-US/docs/Sec
                        "cssFloat": true,
                        "deleteExpando": true,
                        "focusin": false,
+                       "gBCRDimensions": true,
                        "html5Clone": true,
                        "htmlSerialize": true,
                        "input": true,