diff options
author | Mike Sherov <mike.sherov@gmail.com> | 2012-05-21 13:44:19 -0400 |
---|---|---|
committer | Dave Methvin <dave.methvin@gmail.com> | 2012-05-21 13:44:19 -0400 |
commit | e0151e5827d7091f311c82d9f951aaaa2688ba8c (patch) | |
tree | d165ce81413d61a4e04096e33e637c1b8f305e8c | |
parent | 978acb9caf9ad5e645e1e5188a0120f05822cc81 (diff) | |
download | jquery-e0151e5827d7091f311c82d9f951aaaa2688ba8c.tar.gz jquery-e0151e5827d7091f311c82d9f951aaaa2688ba8c.zip |
Fix #10877. Make outerWidth/Height a setter. Closes gh-783.
-rw-r--r-- | src/css.js | 94 | ||||
-rw-r--r-- | src/dimensions.js | 42 | ||||
-rw-r--r-- | test/unit/css.js | 18 | ||||
-rw-r--r-- | test/unit/dimensions.js | 68 |
4 files changed, 130 insertions, 92 deletions
diff --git a/src/css.js b/src/css.js index ba0042dff..4858338ba 100644 --- a/src/css.js +++ b/src/css.js @@ -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 + ); + } }; }); diff --git a/src/dimensions.js b/src/dimensions.js index d4d7915ff..79d7c22bc 100644 --- a/src/dimensions.js +++ b/src/dimensions.js @@ -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 ); diff --git a/test/unit/css.js b/test/unit/css.js index 1cefe8114..a7d16bd5a 100644 --- a/test/unit/css.js +++ b/test/unit/css.js @@ -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() { diff --git a/test/unit/dimensions.js b/test/unit/dimensions.js index 01135f1a1..0b4eedcbf 100644 --- a/test/unit/dimensions.js +++ b/test/unit/dimensions.js @@ -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); |