]> source.dussan.org Git - jquery.git/commitdiff
Fix #10413, #10679. Fix box-sizing:border-box and add css vendor prefix support.
authorMike Sherov <mike.sherov@gmail.com>
Fri, 6 Apr 2012 12:39:59 +0000 (08:39 -0400)
committerDave Methvin <dave.methvin@gmail.com>
Fri, 6 Apr 2012 12:39:59 +0000 (08:39 -0400)
src/css.js
src/support.js
test/unit/dimensions.js

index c1775b7abca1cfa4e5003dd61c64390b4d464e25..afbf96afb753b70a617db69d0e2aa13b4cde3ff3 100644 (file)
@@ -13,12 +13,35 @@ var ralpha = /alpha\([^)]*\)/i,
 
        // order is important!
        cssExpand = [ "Top", "Right", "Bottom", "Left" ],
+       cssPrefixes = [ "O", "Webkit", "Moz", "ms" ],
 
        curCSS,
-
        getComputedStyle,
        currentStyle;
 
+// return a css property mapped to a potentially vendor prefixed property
+function vendorPropName( style, name ) {
+
+       // shortcut for names that are not vendor prefixed
+       if ( name in style ) {
+               return name;
+       }
+
+       // check for vendor prefixed names
+       var capName = name.charAt(0).toUpperCase() + name.slice(1),
+               origName = name,
+               i = cssPrefixes.length;
+
+       while ( i-- ) {
+               name = cssPrefixes[ i ] + capName;
+               if ( name in style ) {
+                       return name;
+               }
+       }
+
+       return origName;
+}
+
 jQuery.fn.css = function( name, value ) {
        return jQuery.access( this, function( elem, name, value ) {
                return value !== undefined ?
@@ -72,10 +95,15 @@ jQuery.extend({
                }
 
                // Make sure that we're working with the right name
-               var ret, type, origName = jQuery.camelCase( name ),
-                       style = elem.style, hooks = jQuery.cssHooks[ origName ];
+               var ret, type, hooks,
+                       origName = jQuery.camelCase( name ),
+                       style = elem.style;
 
-               name = jQuery.cssProps[ origName ] || origName;
+               name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );
+
+               // gets hook for the prefixed version
+               // followed by the unprefixed version
+               hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
 
                // Check if we're setting a value
                if ( value !== undefined ) {
@@ -119,12 +147,15 @@ jQuery.extend({
        },
 
        css: function( elem, name, extra ) {
-               var ret, hooks;
+               var ret, hooks,
+                       origName = jQuery.camelCase( name );
 
                // Make sure that we're working with the right name
-               name = jQuery.camelCase( name );
-               hooks = jQuery.cssHooks[ name ];
-               name = jQuery.cssProps[ name ] || name;
+               name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );
+
+               // gets hook for the prefixed version
+               // followed by the unprefixed version
+               hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
 
                // cssFloat needs a special treatment
                if ( name === "cssFloat" ) {
@@ -244,9 +275,29 @@ function getWidthOrHeight( elem, name, extra ) {
        // Start with offset property
        var val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
                i = name === "width" ? 1 : 0,
-               len = 4;
+               len = 4,
+               usedOffset = true;
+
+       if ( val <= 0 ) {
+               usedOffset = false;
+
+               // Fall back to computed then uncomputed css if necessary
+               val = curCSS( elem, name );
+               if ( val < 0 || val == null ) {
+                       val = elem.style[ name ];
+               }
+
+               // Computed unit is not pixels. Stop here and return.
+               if ( rnumnonpx.test(val) ) {
+                       return val;
+               }
+
+               // Normalize "", auto, and prepare for extra
+               val = parseFloat( val ) || 0;
+       }
 
-       if ( val > 0 ) {
+       //if we're using border-box, the css width/height value behaves like the offsetWidth/Height property!
+       if ( usedOffset || ( jQuery.support.boxSizing && jQuery.css( elem, "boxSizing" ) === "border-box" ) ) {
                if ( extra !== "border" ) {
                        for ( ; i < len; i += 2 ) {
                                if ( !extra ) {
@@ -259,33 +310,17 @@ function getWidthOrHeight( elem, name, extra ) {
                                }
                        }
                }
-
-               return val + "px";
-       }
-
-       // Fall back to computed then uncomputed css if necessary
-       val = curCSS( elem, name );
-       if ( val < 0 || val == null ) {
-               val = elem.style[ name ];
-       }
-
-       // Computed unit is not pixels. Stop here and return.
-       if ( rnumnonpx.test(val) ) {
-               return val;
-       }
-
-       // Normalize "", auto, and prepare for extra
-       val = parseFloat( val ) || 0;
-
-       // Add padding, border, margin
-       if ( extra ) {
-               for ( ; i < len; i += 2 ) {
-                       val += parseFloat( jQuery.css( elem, "padding" + cssExpand[ i ] ) ) || 0;
-                       if ( extra !== "padding" ) {
-                               val += parseFloat( jQuery.css( elem, "border" + cssExpand[ i ] + "Width" ) ) || 0;
-                       }
-                       if ( extra === "margin" ) {
-                               val += parseFloat( jQuery.css( elem, extra + cssExpand[ i ]) ) || 0;
+       } else {
+               // Add padding, border, margin
+               if ( extra ) {
+                       for ( ; i < len; i += 2 ) {
+                               val += parseFloat( jQuery.css( elem, "padding" + cssExpand[ i ] ) ) || 0;
+                               if ( extra !== "padding" ) {
+                                       val += parseFloat( jQuery.css( elem, "border" + cssExpand[ i ] + "Width" ) ) || 0;
+                               }
+                               if ( extra === "margin" ) {
+                                       val += parseFloat( jQuery.css( elem, extra + cssExpand[ i ] ) ) || 0;
+                               }
                        }
                }
        }
index 5a0d1b7311ae8446dec7f86b00f1b182e874510d..ccf9d4315610e436a779dfa7b81cecea3b7eee45 100644 (file)
@@ -180,6 +180,7 @@ jQuery.support = (function() {
        jQuery(function() {
                var container, offsetSupport, marginDiv,
                        conMarginTop = 1,
+                       boxSizingPrefixes = [ "", "-moz-", "-webkit-", "" ],
                        body = document.getElementsByTagName("body")[0];
 
                if ( !body ) {
@@ -250,6 +251,9 @@ jQuery.support = (function() {
                        support.shrinkWrapBlocks = ( div.offsetWidth !== 3 );
                }
 
+               div.style.cssText = boxSizingPrefixes.join("box-sizing:border-box;") + "width:4px;padding:1px;border:1px;display:block";
+               support.boxSizing = ( div.offsetWidth === 4 );
+
                offsetSupport = {
                        doesNotIncludeMarginInBodyOffset: ( body.offsetTop !== conMarginTop )
                };
index c6b8e835c163283d8c82d25e5c6fcafd42eb6445..ef3d8ca682746c12a1b31bf54406a5bc54eb5479 100644 (file)
@@ -230,12 +230,13 @@ test("outerWidth()", function() {
        jQuery.removeData($div[0], "olddisplay", true);
 });
 
-test("child of a hidden elem has accurate inner/outer/Width()/Height()  see #9441 #9300", function() {
-       expect(8);
+test("child of a hidden elem (or unconnected node) has accurate inner/outer/Width()/Height()  see #9441 #9300", function() {
+       expect(16);
 
        // setup html
-       var $divNormal       = jQuery("<div>").css({ width: "100px", height: "100px", border: "10px solid white", padding: "2px", margin: "3px" }),
-               $divChild        = $divNormal.clone(),
+       var $divNormal = jQuery("<div>").css({ width: "100px", height: "100px", border: "10px solid white", padding: "2px", margin: "3px" }),
+               $divChild = $divNormal.clone(),
+               $divUnconnected = $divNormal.clone(),
                $divHiddenParent = jQuery("<div>").css( "display", "none" ).append( $divChild ).appendTo("body");
        $divNormal.appendTo("body");
 
@@ -250,6 +251,17 @@ test("child of a hidden elem has accurate inner/outer/Width()/Height()  see #944
        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" );
 
+       // 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" );
+       equal( $divUnconnected.innerWidth(), $divNormal.innerWidth(), "unconnected element innerWidth() is wrong see #9441" );
+       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" );
+
        // teardown html
        $divHiddenParent.remove();
        $divNormal.remove();
@@ -278,6 +290,43 @@ test("getting dimensions shouldnt modify runtimeStyle see #9233", function() {
        $div.remove();
 });
 
+test("box-sizing:border-box child of a hidden elem (or unconnected node) has accurate inner/outer/Width()/Height()  see #10413", function() {
+       expect(16);
+
+       // setup html
+       var $divNormal = jQuery("<div>").css({ boxSizing: "border-box", width: "100px", height: "100px", border: "10px solid white", padding: "2px", margin: "3px" }),
+               $divChild = $divNormal.clone(),
+               $divUnconnected = $divNormal.clone(),
+               $divHiddenParent = jQuery("<div>").css( "display", "none" ).append( $divChild ).appendTo("body");
+       $divNormal.appendTo("body");
+
+       // tests that child div of a hidden div works the same as a normal div
+       equal( $divChild.width(), $divNormal.width(), "child of a hidden element width() is wrong see #10413" );
+       equal( $divChild.innerWidth(), $divNormal.innerWidth(), "child of a hidden element innerWidth() is wrong see #10413" );
+       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" );
+
+       // 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" );
+       equal( $divUnconnected.innerWidth(), $divNormal.innerWidth(), "unconnected element innerWidth() is wrong see #10413" );
+       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" );
+
+       // teardown html
+       $divHiddenParent.remove();
+       $divNormal.remove();
+});
+
 test("outerHeight()", function() {
        expect(11);