Commit e0151e58 authored by Mike Sherov's avatar Mike Sherov Committed by Dave Methvin

Fix #10877. Make outerWidth/Height a setter. Closes gh-783.

parent 978acb9c
(function( jQuery ) { (function( jQuery ) {
// order is important!
jQuery.cssExpand = [ "Top", "Right", "Bottom", "Left" ]; jQuery.cssExpand = [ "Top", "Right", "Bottom", "Left" ];
var ralpha = /alpha\([^)]*\)/i, var ralpha = /alpha\([^)]*\)/i,
...@@ -13,7 +14,6 @@ var ralpha = /alpha\([^)]*\)/i, ...@@ -13,7 +14,6 @@ var ralpha = /alpha\([^)]*\)/i,
cssShow = { position: "absolute", visibility: "hidden", display: "block" }, cssShow = { position: "absolute", visibility: "hidden", display: "block" },
// order is important!
cssExpand = jQuery.cssExpand, cssExpand = jQuery.cssExpand,
cssPrefixes = [ "Webkit", "O", "Moz", "ms" ], cssPrefixes = [ "Webkit", "O", "Moz", "ms" ],
...@@ -127,7 +127,7 @@ jQuery.extend({ ...@@ -127,7 +127,7 @@ jQuery.extend({
} }
// If a hook was provided, use that value, otherwise just set the specified value // 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 // Wrapped to prevent IE from throwing errors when 'invalid' values are provided
// Fixes bug #5509 // Fixes bug #5509
try { try {
...@@ -266,19 +266,57 @@ if ( document.defaultView && document.defaultView.getComputedStyle ) { ...@@ -266,19 +266,57 @@ if ( document.defaultView && document.defaultView.getComputedStyle ) {
}; };
} }
function setPositiveNumber( elem, value ) { function setPositiveNumber( elem, value, subtract ) {
var matches = rnumsplit.exec( value ); var matches = rnumsplit.exec( value );
return matches ? return matches ?
Math.max( 0, matches[ 1 ] ) + ( matches [ 2 ] || "px" ) Math.max( 0, +matches[ 1 ] - ( subtract || 0 ) ) + ( matches [ 2 ] || "px" )
: value; : 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 ) { function getWidthOrHeight( elem, name, extra ) {
// Start with offset property, which is equivalent to the border-box value // Start with offset property, which is equivalent to the border-box value
var val = name === "width" ? elem.offsetWidth : elem.offsetHeight, var val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
i = name === "width" ? 1 : 0,
len = 4,
valueIsBorderBox = true, valueIsBorderBox = true,
isBorderBox = jQuery.support.boxSizing && jQuery.css( elem, "boxSizing" ) === "border-box"; isBorderBox = jQuery.support.boxSizing && jQuery.css( elem, "boxSizing" ) === "border-box";
...@@ -307,38 +345,7 @@ function getWidthOrHeight( elem, name, extra ) { ...@@ -307,38 +345,7 @@ function getWidthOrHeight( elem, name, extra ) {
extra = isBorderBox ? "border" : "content"; extra = isBorderBox ? "border" : "content";
} }
// if the measurement we need is already represented by the retrieved width val += augmentWidthOrHeight( name, elem, extra, valueIsBorderBox );
// 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;
}
}
}
}
return val + "px"; return val + "px";
} }
...@@ -357,7 +364,16 @@ jQuery.each([ "height", "width" ], function( i, name ) { ...@@ -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
);
}
}; };
}); });
......
...@@ -6,27 +6,27 @@ jQuery.each( { Height: "height", Width: "width" }, function( name, type ) { ...@@ -6,27 +6,27 @@ jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
scrollProp = "scroll" + name, scrollProp = "scroll" + name,
offsetProp = "offset" + name; offsetProp = "offset" + name;
// innerHeight and innerWidth // height, width, innerHeight and innerWidth
jQuery.fn[ "inner" + name ] = function() { jQuery.each( { padding: "inner" + name, content: type }, function( extra, funcName ) {
var elem = this[0]; jQuery.fn[ funcName ] = function( value ) {
return elem ? var args = [ type, extra ];
elem.style ? if ( arguments.length ) {
parseFloat( jQuery.css( elem, type, "padding" ) ) : args.push( value );
this[ type ]() : }
null; return getDimension.apply( this, args );
}; };
});
// outerHeight and outerWidth // outerHeight and outerWidth
jQuery.fn[ "outer" + name ] = function( margin ) { jQuery.fn[ "outer" + name ] = function( margin, value ) {
var elem = this[0]; var args = [ type, ( margin === true || value === true ) ? "margin" : "border" ];
return elem ? if ( arguments.length && typeof margin !== "boolean" ) {
elem.style ? args.push( margin );
parseFloat( jQuery.css( elem, type, margin ? "margin" : "border" ) ) : }
this[ type ]() : return getDimension.apply( this, args );
null;
}; };
jQuery.fn[ type ] = function( value ) { function getDimension( type, extra, value ) {
return jQuery.access( this, function( elem, type, value ) { return jQuery.access( this, function( elem, type, value ) {
var doc, orig, ret; var doc, orig, ret;
...@@ -58,15 +58,15 @@ jQuery.each( { Height: "height", Width: "width" }, function( name, type ) { ...@@ -58,15 +58,15 @@ jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
// Get width or height on the element // Get width or height on the element
if ( value === undefined ) { if ( value === undefined ) {
orig = jQuery.css( elem, type, "content" ); orig = jQuery.css( elem, type, extra );
ret = parseFloat( orig ); ret = parseFloat( orig );
return jQuery.isNumeric( ret ) ? ret : orig; return jQuery.isNumeric( ret ) ? ret : orig;
} }
// Set the width or height on the element // Set the width or height on the element
jQuery.style( elem, type, value ); jQuery.style( elem, type, value, extra );
}, type, value, arguments.length, null ); }, type, value, arguments.length > 2, null );
}; }
}); });
})( jQuery ); })( jQuery );
...@@ -555,16 +555,14 @@ test("outerWidth(true) and css('margin') returning % instead of px in Webkit, se ...@@ -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" ); 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() { test("css('width') and css('height') 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>"), 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_disconnected.clone().appendTo("#qunit-fixture"), el = el_dis.clone().appendTo("#qunit-fixture");
width_initial = el.css("width"),
width_roundtrip = el.css("width", el.css("width")).css("width"), equal( el.css("width"), el.css("width", el.css("width")).css("width"), "css('width') is not respecting box-sizing, see #11004");
width_initial_disconnected = el_disconnected.css("width"), 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");
width_roundtrip_disconnected = el_disconnected.css("width", el_disconnected.css("width")).css("width"); 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");
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( "cssHooks - expand", function() { test( "cssHooks - expand", function() {
......
...@@ -43,11 +43,6 @@ test("width()", function() { ...@@ -43,11 +43,6 @@ test("width()", function() {
testWidth( pass ); 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() { test("width(Function)", function() {
testWidth( fn ); testWidth( fn );
}); });
...@@ -99,11 +94,6 @@ test("height()", function() { ...@@ -99,11 +94,6 @@ test("height()", function() {
testHeight( pass ); 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() { test("height(Function)", function() {
testHeight( fn ); testHeight( fn );
}); });
...@@ -121,16 +111,13 @@ test("height(Function(args))", function() { ...@@ -121,16 +111,13 @@ test("height(Function(args))", function() {
}); });
test("innerWidth()", function() { test("innerWidth()", function() {
expect(8); expect(6);
var winWidth = jQuery( window ).width(), var winWidth = jQuery( window ).width(),
docWidth = jQuery( document ).width(); docWidth = jQuery( document ).width();
equal(jQuery(window).innerWidth(), winWidth, "Test on window without margin option"); equal(jQuery(window).innerWidth(), winWidth, "Test on window");
equal(jQuery(window).innerWidth(true), winWidth, "Test on window with margin option"); equal(jQuery(document).innerWidth(), docWidth, "Test on document");
equal(jQuery(document).innerWidth(), docWidth, "Test on document without margin option");
equal(jQuery(document).innerWidth(true), docWidth, "Test on document with margin option");
var $div = jQuery("#nothiddendiv"); var $div = jQuery("#nothiddendiv");
// set styles // set styles
...@@ -159,16 +146,13 @@ test("innerWidth()", function() { ...@@ -159,16 +146,13 @@ test("innerWidth()", function() {
}); });
test("innerHeight()", function() { test("innerHeight()", function() {
expect(8); expect(6);
var winHeight = jQuery( window ).height(), var winHeight = jQuery( window ).height(),
docHeight = jQuery( document ).height(); docHeight = jQuery( document ).height();
equal(jQuery(window).innerHeight(), winHeight, "Test on window without margin option"); equal(jQuery(window).innerHeight(), winHeight, "Test on window");
equal(jQuery(window).innerHeight(true), winHeight, "Test on window with margin option"); equal(jQuery(document).innerHeight(), docHeight, "Test on document");
equal(jQuery(document).innerHeight(), docHeight, "Test on document without margin option");
equal(jQuery(document).innerHeight(true), docHeight, "Test on document with margin option");
var $div = jQuery("#nothiddendiv"); var $div = jQuery("#nothiddendiv");
// set styles // set styles
...@@ -369,6 +353,46 @@ test("outerHeight()", function() { ...@@ -369,6 +353,46 @@ test("outerHeight()", function() {
jQuery.removeData($div[0], "olddisplay", true); 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 ) { testIframe("dimensions/documentSmall", "window vs. small document", function( jQuery, window, document ) {
expect(2); expect(2);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment