diff --git a/src/css.js b/src/css.js index 0e5a55610..acd4bb3eb 100644 --- a/src/css.js +++ b/src/css.js @@ -27,8 +27,6 @@ var // except "table", "table-cell", or "table-caption" // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display rdisplayswap = /^(none|table(?!-c[ea]).+)/, - rnumsplit = new RegExp( "^(" + pnum + ")(.*)$", "i" ), - cssShow = { position: "absolute", visibility: "hidden", display: "block" }, cssNormalTransform = { letterSpacing: "0", @@ -59,11 +57,14 @@ function vendorPropName( name ) { } function setPositiveNumber( elem, value, subtract ) { - var matches = rnumsplit.exec( value ); + + // Any relative (+/-) values have already been + // normalized at this point + var matches = rcssNum.exec( value ); return matches ? // Guard against undefined "subtract", e.g., when used as in cssHooks - Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) : + Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) : value; } @@ -336,16 +337,25 @@ jQuery.each( [ "height", "width" ], function( i, name ) { }, set: function( elem, value, extra ) { - var styles = extra && getStyles( elem ); - return setPositiveNumber( elem, value, extra ? - augmentWidthOrHeight( + var matches, + styles = extra && getStyles( elem ), + subtract = extra && augmentWidthOrHeight( elem, name, extra, jQuery.css( elem, "boxSizing", false, styles ) === "border-box", styles - ) : 0 - ); + ); + + // Convert to pixels if value adjustment is needed + if ( subtract && ( matches = rcssNum.exec( value ) ) && + ( matches[ 3 ] || "px" ) !== "px" ) { + + elem.style[ name ] = value; + value = jQuery.css( elem, name ); + } + + return setPositiveNumber( elem, value, subtract ); } }; } ); diff --git a/test/unit/dimensions.js b/test/unit/dimensions.js index dfc7697f2..28f4ecd13 100644 --- a/test/unit/dimensions.js +++ b/test/unit/dimensions.js @@ -418,36 +418,41 @@ QUnit.test( "getters on non elements should return null", function( assert ) { } ); QUnit.test( "setters with and without box-sizing:border-box", function( assert ) { - assert.expect( 20 ); + assert.expect( 60 ); - // Support: Android 2.3 (-webkit-box-sizing). - var el_bb = jQuery( "
test
" ).appendTo( "#qunit-fixture" ), - el = jQuery( "
test
" ).appendTo( "#qunit-fixture" ), - expected = 100; + var parent = jQuery( "#foo" ).css({ width: "200px", height: "200px", "font-size": "16px" }), + el_bb = jQuery( "
" ).appendTo( parent ), + el = jQuery( "
" ).appendTo( parent ); - assert.equal( el_bb.width( 101 ).width(), expected + 1, "test border-box width(int) by roundtripping" ); - assert.equal( el_bb.innerWidth( 108 ).width(), expected + 2, "test border-box innerWidth(int) by roundtripping" ); - assert.equal( el_bb.outerWidth( 117 ).width(), expected + 3, "test border-box outerWidth(int) by roundtripping" ); - assert.equal( el_bb.outerWidth( 118, false ).width(), expected + 4, "test border-box outerWidth(int, false) by roundtripping" ); - assert.equal( el_bb.outerWidth( 129, true ).width(), expected + 5, "test border-box innerWidth(int, true) by roundtripping" ); + jQuery.each( { + "number": { set: 100, expected: 100 }, + "em": { set: "10em", expected: 160 }, + "percentage": { set: "50%", expected: 100 } + }, function( units, values ) { + assert.equal( el_bb.width( values.set ).width(), values.expected, "test border-box width(" + units + ") by roundtripping" ); + assert.equal( el_bb.innerWidth( values.set ).width(), values.expected - 2, "test border-box innerWidth(" + units + ") by roundtripping" ); + assert.equal( el_bb.outerWidth( values.set ).width(), values.expected - 6, "test border-box outerWidth(" + units + ") by roundtripping" ); + assert.equal( el_bb.outerWidth( values.set, false ).width(), values.expected - 6, "test border-box outerWidth(" + units + ", false) by roundtripping" ); + assert.equal( el_bb.outerWidth( values.set, true ).width(), values.expected - 16, "test border-box innerWidth(" + units + ", true) by roundtripping" ); - assert.equal( el_bb.height( 101 ).height(), expected + 1, "test border-box height(int) by roundtripping" ); - assert.equal( el_bb.innerHeight( 108 ).height(), expected + 2, "test border-box innerHeight(int) by roundtripping" ); - assert.equal( el_bb.outerHeight( 117 ).height(), expected + 3, "test border-box outerHeight(int) by roundtripping" ); - assert.equal( el_bb.outerHeight( 118, false ).height(), expected + 4, "test border-box outerHeight(int, false) by roundtripping" ); - assert.equal( el_bb.outerHeight( 129, true ).height(), expected + 5, "test border-box innerHeight(int, true) by roundtripping" ); + assert.equal( el_bb.height( values.set ).height(), values.expected, "test border-box height(" + units + ") by roundtripping" ); + assert.equal( el_bb.innerHeight( values.set ).height(), values.expected - 2, "test border-box innerHeight(" + units + ") by roundtripping" ); + assert.equal( el_bb.outerHeight( values.set ).height(), values.expected - 6, "test border-box outerHeight(" + units + ") by roundtripping" ); + assert.equal( el_bb.outerHeight( values.set, false ).height(), values.expected - 6, "test border-box outerHeight(" + units + ", false) by roundtripping" ); + assert.equal( el_bb.outerHeight( values.set, true ).height(), values.expected - 16, "test border-box innerHeight(" + units + ", true) by roundtripping" ); - assert.equal( el.width( 101 ).width(), expected + 1, "test border-box width(int) by roundtripping" ); - assert.equal( el.innerWidth( 108 ).width(), expected + 2, "test border-box innerWidth(int) by roundtripping" ); - assert.equal( el.outerWidth( 117 ).width(), expected + 3, "test border-box outerWidth(int) by roundtripping" ); - assert.equal( el.outerWidth( 118, false ).width(), expected + 4, "test border-box outerWidth(int, false) by roundtripping" ); - assert.equal( el.outerWidth( 129, true ).width(), expected + 5, "test border-box innerWidth(int, true) by roundtripping" ); + assert.equal( el.width( values.set ).width(), values.expected, "test non-border-box width(" + units + ") by roundtripping" ); + assert.equal( el.innerWidth( values.set ).width(), values.expected - 2, "test non-border-box innerWidth(" + units + ") by roundtripping" ); + assert.equal( el.outerWidth( values.set ).width(), values.expected - 6, "test non-border-box outerWidth(" + units + ") by roundtripping" ); + assert.equal( el.outerWidth( values.set, false ).width(), values.expected - 6, "test non-border-box outerWidth(" + units + ", false) by roundtripping" ); + assert.equal( el.outerWidth( values.set, true ).width(), values.expected - 16, "test non-border-box innerWidth(" + units + ", true) by roundtripping" ); - assert.equal( el.height( 101 ).height(), expected + 1, "test border-box height(int) by roundtripping" ); - assert.equal( el.innerHeight( 108 ).height(), expected + 2, "test border-box innerHeight(int) by roundtripping" ); - assert.equal( el.outerHeight( 117 ).height(), expected + 3, "test border-box outerHeight(int) by roundtripping" ); - assert.equal( el.outerHeight( 118, false ).height(), expected + 4, "test border-box outerHeight(int, false) by roundtripping" ); - assert.equal( el.outerHeight( 129, true ).height(), expected + 5, "test border-box innerHeight(int, true) by roundtripping" ); + assert.equal( el.height( values.set ).height(), values.expected, "test non-border-box height(" + units + ") by roundtripping" ); + assert.equal( el.innerHeight( values.set ).height(), values.expected - 2, "test non-border-box innerHeight(" + units + ") by roundtripping" ); + assert.equal( el.outerHeight( values.set ).height(), values.expected - 6, "test non-border-box outerHeight(" + units + ") by roundtripping" ); + assert.equal( el.outerHeight( values.set, false ).height(), values.expected - 6, "test non-border-box outerHeight(" + units + ", false) by roundtripping" ); + assert.equal( el.outerHeight( values.set, true ).height(), values.expected - 16, "test non-border-box innerHeight(" + units + ", true) by roundtripping" ); + } ); } ); testIframe(