]> source.dussan.org Git - jquery.git/commitdiff
Fix #10877. Make outerWidth/Height a setter. Closes gh-783.
authorMike Sherov <mike.sherov@gmail.com>
Mon, 21 May 2012 17:44:19 +0000 (13:44 -0400)
committerDave Methvin <dave.methvin@gmail.com>
Mon, 21 May 2012 17:44:19 +0000 (13:44 -0400)
src/css.js
src/dimensions.js
test/unit/css.js
test/unit/dimensions.js

index ba0042dff020db111ecbdbab7af1bca08dcce959..4858338ba2763cfc61240eb8203e8fde39466eb9 100644 (file)
@@ -1,5 +1,6 @@
 (function( jQuery ) {
 
+// order is important!
 jQuery.cssExpand = [ "Top", "Right", "Bottom", "Left" ];
 
 var ralpha = /alpha\([^)]*\)/i,
@@ -13,7 +14,6 @@ var ralpha = /alpha\([^)]*\)/i,
 
        cssShow = { position: "absolute", visibility: "hidden", display: "block" },
 
-       // order is important!
        cssExpand = jQuery.cssExpand,
        cssPrefixes = [ "Webkit", "O", "Moz", "ms" ],
 
@@ -127,7 +127,7 @@ jQuery.extend({
                        }
 
                        // If a hook was provided, use that value, otherwise just set the specified value
-                       if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value )) !== undefined ) {
+                       if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) {
                                // Wrapped to prevent IE from throwing errors when 'invalid' values are provided
                                // Fixes bug #5509
                                try {
@@ -266,19 +266,57 @@ if ( document.defaultView && document.defaultView.getComputedStyle ) {
        };
 }
 
-function setPositiveNumber( elem, value ) {
+function setPositiveNumber( elem, value, subtract ) {
        var matches = rnumsplit.exec( value );
        return matches ?
-                       Math.max( 0, matches[ 1 ] ) + ( matches [ 2 ] || "px" )
+                       Math.max( 0, +matches[ 1 ] - ( subtract || 0 ) ) + ( matches [ 2 ] || "px" )
                        : value;
 }
 
+function augmentWidthOrHeight( name, elem, extra, isBorderBox ) {
+       var val = 0,
+               i = name === "width" ? 1 : 0;
+
+       // if the measurement we need is already represented by the measurement
+       // there's no need to augment further
+       if ( extra !== (isBorderBox ? "border" : "content") ) {
+               for ( ; i < 4; i += 2 ) {
+                       // both box models exclude margin, so add it if we want it
+                       if ( extra === "margin" ) {
+                               // we use jQuery.css instead of curCSS here
+                               // because of the reliableMarginRight CSS hook!
+                               val += parseFloat( jQuery.css( elem, extra + cssExpand[ i ] ) ) || 0;
+                       }
+
+                       if ( isBorderBox ) {
+                               // border-box includes padding, so remove it if we want content
+                               if ( extra === "content" ) {
+                                       val -= parseFloat( curCSS( elem, "padding" + cssExpand[ i ] ) ) || 0;
+                               }
+
+                               // at this point, extra isnt border nor margin, so remove border
+                               if ( extra !== "margin" ) {
+                                       val -= parseFloat( curCSS( elem, "border" + cssExpand[ i ] + "Width" ) ) || 0;
+                               }
+                       } else {
+                               // at this point, extra isnt content, so add padding
+                               val += parseFloat( curCSS( elem, "padding" + cssExpand[ i ] ) ) || 0;
+
+                               // at this point, extra isnt content nor padding, so add border
+                               if ( extra !== "padding" ) {
+                                       val += parseFloat( curCSS( elem, "border" + cssExpand[ i ] + "Width" ) ) || 0;
+                               }
+                       }
+               }
+       }
+
+       return val;
+}
+
 function getWidthOrHeight( elem, name, extra ) {
 
        // Start with offset property, which is equivalent to the border-box value
        var val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
-               i = name === "width" ? 1 : 0,
-               len = 4,
                valueIsBorderBox = true,
                isBorderBox = jQuery.support.boxSizing && jQuery.css( elem, "boxSizing" ) === "border-box";
 
@@ -307,38 +345,7 @@ function getWidthOrHeight( elem, name, extra ) {
                extra = isBorderBox ? "border" : "content";
        }
 
-       // if the measurement we need is already represented by the retrieved width
-       // there's no need to augment further
-       if ( extra !== (valueIsBorderBox ? "border" : "content") ) {
-               for ( ; i < len; i += 2 ) {
-                       // both box models exclude margin, so add it if we want it
-                       if ( extra === "margin" ) {
-                               // we use jQuery.css instead of curCSS here
-                               // because of the reliableMarginRight CSS hook!
-                               val += parseFloat( jQuery.css( elem, extra + cssExpand[ i ] ) ) || 0;
-                       }
-
-                       if ( valueIsBorderBox ) {
-                               // border-box includes padding, so remove it if we want content
-                               if ( extra === "content" ) {
-                                       val -= parseFloat( curCSS( elem, "padding" + cssExpand[ i ] ) ) || 0;
-                               }
-
-                               // at this point, extra isnt border nor margin, so remove border
-                               if ( extra !== "margin" ) {
-                                       val -= parseFloat( curCSS( elem, "border" + cssExpand[ i ] + "Width" ) ) || 0;
-                               }
-                       } else {
-                               // at this point, extra isnt content, so add padding
-                               val += parseFloat( curCSS( elem, "padding" + cssExpand[ i ] ) ) || 0;
-
-                               // at this point, extra isnt content nor padding, so add border
-                               if ( extra !== "padding" ) {
-                                       val += parseFloat( curCSS( elem, "border" + cssExpand[ i ] + "Width" ) ) || 0;
-                               }
-                       }
-               }
-       }
+       val += augmentWidthOrHeight( name, elem, extra, valueIsBorderBox );
 
        return val + "px";
 }
@@ -357,7 +364,16 @@ jQuery.each([ "height", "width" ], function( i, name ) {
                        }
                },
 
-               set: setPositiveNumber
+               set: function( elem, value, extra ) {
+                       return setPositiveNumber( elem, value, extra ?
+                               augmentWidthOrHeight(
+                                       name,
+                                       elem,
+                                       extra,
+                                       jQuery.support.boxSizing && jQuery.css( elem, "boxSizing" ) === "border-box"
+                               ) : 0
+                       );
+               }
        };
 });
 
index d4d7915ff39f59865449f5adfb71c14546634887..79d7c22bc2138e1ec6799c7db9f25a92ec7f0af5 100644 (file)
@@ -6,27 +6,27 @@ jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
                scrollProp = "scroll" + name,
                offsetProp = "offset" + name;
 
-       // innerHeight and innerWidth
-       jQuery.fn[ "inner" + name ] = function() {
-               var elem = this[0];
-               return elem ?
-                       elem.style ?
-                       parseFloat( jQuery.css( elem, type, "padding" ) ) :
-                       this[ type ]() :
-                       null;
-       };
+       // height, width, innerHeight and innerWidth
+       jQuery.each( { padding: "inner" + name, content: type }, function( extra, funcName ) {
+               jQuery.fn[ funcName ] = function( value ) {
+                       var args = [ type, extra ];
+                       if ( arguments.length ) {
+                               args.push( value );
+                       }
+                       return getDimension.apply( this, args );
+               };
+       });
 
        // outerHeight and outerWidth
-       jQuery.fn[ "outer" + name ] = function( margin ) {
-               var elem = this[0];
-               return elem ?
-                       elem.style ?
-                       parseFloat( jQuery.css( elem, type, margin ? "margin" : "border" ) ) :
-                       this[ type ]() :
-                       null;
+       jQuery.fn[ "outer" + name ] = function( margin, value ) {
+               var args = [ type, ( margin === true || value === true ) ? "margin" : "border" ];
+               if ( arguments.length && typeof margin !== "boolean" ) {
+                       args.push( margin );
+               }
+               return getDimension.apply( this, args );
        };
 
-       jQuery.fn[ type ] = function( value ) {
+       function getDimension( type, extra, value ) {
                return jQuery.access( this, function( elem, type, value ) {
                        var doc, orig, ret;
 
@@ -58,15 +58,15 @@ jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
 
                        // Get width or height on the element
                        if ( value === undefined ) {
-                               orig = jQuery.css( elem, type, "content" );
+                               orig = jQuery.css( elem, type, extra );
                                ret = parseFloat( orig );
                                return jQuery.isNumeric( ret ) ? ret : orig;
                        }
 
                        // Set the width or height on the element
-                       jQuery.style( elem, type, value );
-               }, type, value, arguments.length, null );
-       };
+                       jQuery.style( elem, type, value, extra );
+               }, type, value, arguments.length > 2, null );
+       }
 });
 
 })( jQuery );
index 1cefe8114f18760c3152898da45399484166f642..a7d16bd5a4820ebb005f4d6c1244eb64daa869bd 100644 (file)
@@ -555,16 +555,14 @@ test("outerWidth(true) and css('margin') returning % instead of px in Webkit, se
        equal( el.outerWidth(true), 400, "outerWidth(true) and css('margin') returning % instead of px in Webkit, see #10639" );
 });
 
-test("css('width') should respect box-sizing, see #11004", function() {
-       var el_disconnected = jQuery("<div style='width:300px;margin:2px;padding:2px;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;'>test</div>"),
-               el = el_disconnected.clone().appendTo("#qunit-fixture"),
-               width_initial = el.css("width"),
-               width_roundtrip = el.css("width", el.css("width")).css("width"),
-               width_initial_disconnected = el_disconnected.css("width"),
-               width_roundtrip_disconnected = el_disconnected.css("width", el_disconnected.css("width")).css("width");
-
-       equal( width_roundtrip, width_initial, "css('width') is not respecting box-sizing, see #11004");
-       equal( width_roundtrip_disconnected, width_initial_disconnected, "css('width') is not respecting box-sizing for disconnected element, see #11004");
+test("css('width') and css('height') should respect box-sizing, see #11004", function() {
+       var el_dis = jQuery("<div style='width:300px;height:300px;margin:2px;padding:2px;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;'>test</div>"),
+               el = el_dis.clone().appendTo("#qunit-fixture");
+
+       equal( el.css("width"), el.css("width", el.css("width")).css("width"), "css('width') is not respecting box-sizing, see #11004");
+       equal( el_dis.css("width"), el_dis.css("width", el_dis.css("width")).css("width"), "css('width') is not respecting box-sizing for disconnected element, see #11004");
+       equal( el.css("height"), el.css("height", el.css("height")).css("height"), "css('height') is not respecting box-sizing, see #11004");
+       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");
 });
 
 test( "cssHooks - expand", function() {
index 01135f1a133d1c6157daed23927cc62e29d87ed8..0b4eedcbfb7db94467602bf43e7eacf5dae32c4e 100644 (file)
@@ -43,11 +43,6 @@ test("width()", function() {
        testWidth( pass );
 });
 
-test("width(undefined)", function() {
-       expect(1);
-       equal(jQuery("#nothiddendiv").width(30).width(undefined).width(), 30, ".width(undefined) is chainable (#5571)");
-});
-
 test("width(Function)", function() {
        testWidth( fn );
 });
@@ -99,11 +94,6 @@ test("height()", function() {
        testHeight( pass );
 });
 
-test("height(undefined)", function() {
-       expect(1);
-       equal(jQuery("#nothiddendiv").height(30).height(undefined).height(), 30, ".height(undefined) is chainable (#5571)");
-});
-
 test("height(Function)", function() {
        testHeight( fn );
 });
@@ -121,16 +111,13 @@ test("height(Function(args))", function() {
 });
 
 test("innerWidth()", function() {
-       expect(8);
+       expect(6);
 
        var winWidth = jQuery( window ).width(),
                docWidth = jQuery( document ).width();
 
-       equal(jQuery(window).innerWidth(), winWidth, "Test on window without margin option");
-       equal(jQuery(window).innerWidth(true), winWidth, "Test on window with margin option");
-
-       equal(jQuery(document).innerWidth(), docWidth, "Test on document without margin option");
-       equal(jQuery(document).innerWidth(true), docWidth, "Test on document with margin option");
+       equal(jQuery(window).innerWidth(), winWidth, "Test on window");
+       equal(jQuery(document).innerWidth(), docWidth, "Test on document");
 
        var $div = jQuery("#nothiddendiv");
        // set styles
@@ -159,16 +146,13 @@ test("innerWidth()", function() {
 });
 
 test("innerHeight()", function() {
-       expect(8);
+       expect(6);
 
        var winHeight = jQuery( window ).height(),
                docHeight = jQuery( document ).height();
 
-       equal(jQuery(window).innerHeight(), winHeight, "Test on window without margin option");
-       equal(jQuery(window).innerHeight(true), winHeight, "Test on window with margin option");
-
-       equal(jQuery(document).innerHeight(), docHeight, "Test on document without margin option");
-       equal(jQuery(document).innerHeight(true), docHeight, "Test on document with margin option");
+       equal(jQuery(window).innerHeight(), winHeight, "Test on window");
+       equal(jQuery(document).innerHeight(), docHeight, "Test on document");
 
        var $div = jQuery("#nothiddendiv");
        // set styles
@@ -369,6 +353,46 @@ test("outerHeight()", function() {
        jQuery.removeData($div[0], "olddisplay", true);
 });
 
+test("passing undefined is a setter #5571", function() {
+       expect(4);
+       equal(jQuery("#nothiddendiv").height(30).height(undefined).height(), 30, ".height(undefined) is chainable (#5571)");
+       equal(jQuery("#nothiddendiv").height(30).innerHeight(undefined).height(), 30, ".innerHeight(undefined) is chainable (#5571)");
+       equal(jQuery("#nothiddendiv").height(30).outerHeight(undefined).height(), 30, ".outerHeight(undefined) is chainable (#5571)");
+       equal(jQuery("#nothiddendiv").width(30).width(undefined).width(), 30, ".width(undefined) is chainable (#5571)");
+});
+
+test("setters with and without box-sizing:border-box", function(){
+       expect(20);
+
+       var el_bb = jQuery("<div style='width:114px;height:114px;margin:5px;padding:3px;border:4px solid white;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;'>test</div>").appendTo("#qunit-fixture"),
+               el = jQuery("<div style='width:100px;height:100px;margin:5px;padding:3px;border:4px solid white;'>test</div>").appendTo("#qunit-fixture"),
+               expected = 100;
+
+       equal( el_bb.width( 101 ).width(), expected + 1, "test border-box width(int) by roundtripping" );
+       equal( el_bb.innerWidth( 108 ).width(), expected + 2, "test border-box innerWidth(int) by roundtripping" );
+       equal( el_bb.outerWidth( 117 ).width(), expected + 3, "test border-box outerWidth(int) by roundtripping" );
+       equal( el_bb.outerWidth( 118, false ).width(), expected + 4, "test border-box outerWidth(int, false) by roundtripping" );
+       equal( el_bb.outerWidth( 129, true ).width(), expected + 5, "test border-box innerWidth(int, true) by roundtripping" );
+
+       equal( el_bb.height( 101 ).height(), expected + 1, "test border-box height(int) by roundtripping" );
+       equal( el_bb.innerHeight( 108 ).height(), expected + 2, "test border-box innerHeight(int) by roundtripping" );
+       equal( el_bb.outerHeight( 117 ).height(), expected + 3, "test border-box outerHeight(int) by roundtripping" );
+       equal( el_bb.outerHeight( 118, false ).height(), expected + 4, "test border-box outerHeight(int, false) by roundtripping" );
+       equal( el_bb.outerHeight( 129, true ).height(), expected + 5, "test border-box innerHeight(int, true) by roundtripping" );
+
+       equal( el.width( 101 ).width(), expected + 1, "test border-box width(int) by roundtripping" );
+       equal( el.innerWidth( 108 ).width(), expected + 2, "test border-box innerWidth(int) by roundtripping" );
+       equal( el.outerWidth( 117 ).width(), expected + 3, "test border-box outerWidth(int) by roundtripping" );
+       equal( el.outerWidth( 118, false ).width(), expected + 4, "test border-box outerWidth(int, false) by roundtripping" );
+       equal( el.outerWidth( 129, true ).width(), expected + 5, "test border-box innerWidth(int, true) by roundtripping" );
+
+       equal( el.height( 101 ).height(), expected + 1, "test border-box height(int) by roundtripping" );
+       equal( el.innerHeight( 108 ).height(), expected + 2, "test border-box innerHeight(int) by roundtripping" );
+       equal( el.outerHeight( 117 ).height(), expected + 3, "test border-box outerHeight(int) by roundtripping" );
+       equal( el.outerHeight( 118, false ).height(), expected + 4, "test border-box outerHeight(int, false) by roundtripping" );
+       equal( el.outerHeight( 129, true ).height(), expected + 5, "test border-box innerHeight(int, true) by roundtripping" );
+});
+
 testIframe("dimensions/documentSmall", "window vs. small document", function( jQuery, window, document ) {
        expect(2);