mirror of
https://github.com/jquery/jquery.git
synced 2024-11-23 02:54:22 +00:00
Dimensions: Include scroll gutter in "padding" box
Fixes gh-3589 Closes gh-3656
This commit is contained in:
parent
5bdd1ca1ab
commit
80f1c8239e
112
src/css.js
112
src/css.js
@ -80,58 +80,77 @@ function setPositiveNumber( elem, value, subtract ) {
|
||||
value;
|
||||
}
|
||||
|
||||
function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
|
||||
var i,
|
||||
val = 0;
|
||||
function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) {
|
||||
var i = dimension === "width" ? 1 : 0,
|
||||
extra = 0,
|
||||
delta = 0;
|
||||
|
||||
// If we already have the right measurement, avoid augmentation
|
||||
if ( extra === ( isBorderBox ? "border" : "content" ) ) {
|
||||
i = 4;
|
||||
|
||||
// Otherwise initialize for horizontal or vertical properties
|
||||
} else {
|
||||
i = name === "width" ? 1 : 0;
|
||||
// Adjustment may not be necessary
|
||||
if ( box === ( isBorderBox ? "border" : "content" ) ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for ( ; i < 4; i += 2 ) {
|
||||
|
||||
// Both box models exclude margin, so add it if we want it
|
||||
if ( extra === "margin" ) {
|
||||
val += jQuery.css( elem, extra + cssExpand[ i ], true, styles );
|
||||
// Both box models exclude margin
|
||||
if ( box === "margin" ) {
|
||||
delta += jQuery.css( elem, box + cssExpand[ i ], true, styles );
|
||||
}
|
||||
|
||||
if ( isBorderBox ) {
|
||||
// If we get here with a content-box, we're seeking "padding" or "border" or "margin"
|
||||
if ( !isBorderBox ) {
|
||||
|
||||
// border-box includes padding, so remove it if we want content
|
||||
if ( extra === "content" ) {
|
||||
val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
|
||||
// Add padding
|
||||
delta += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
|
||||
|
||||
// For "border" or "margin", add border
|
||||
if ( box !== "padding" ) {
|
||||
delta += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
|
||||
|
||||
// But still keep track of it otherwise
|
||||
} else {
|
||||
extra += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
|
||||
}
|
||||
|
||||
// At this point, extra isn't border nor margin, so remove border
|
||||
if ( extra !== "margin" ) {
|
||||
val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
|
||||
}
|
||||
// If we get here with a border-box (content + padding + border), we're seeking "content" or
|
||||
// "padding" or "margin"
|
||||
} else {
|
||||
|
||||
// At this point, extra isn't content, so add padding
|
||||
val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
|
||||
// For "content", subtract padding
|
||||
if ( box === "content" ) {
|
||||
delta -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
|
||||
}
|
||||
|
||||
// At this point, extra isn't content nor padding, so add border
|
||||
if ( extra !== "padding" ) {
|
||||
val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
|
||||
// For "content" or "padding", subtract border
|
||||
if ( box !== "margin" ) {
|
||||
delta -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return val;
|
||||
// Account for positive content-box scroll gutter when requested by providing computedVal
|
||||
if ( !isBorderBox && computedVal >= 0 ) {
|
||||
|
||||
// offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border
|
||||
// Assuming integer scroll gutter, subtract the rest and round down
|
||||
delta += Math.max( 0, Math.ceil(
|
||||
elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] -
|
||||
computedVal -
|
||||
delta -
|
||||
extra -
|
||||
0.5
|
||||
) );
|
||||
}
|
||||
|
||||
return delta;
|
||||
}
|
||||
|
||||
function getWidthOrHeight( elem, name, extra ) {
|
||||
function getWidthOrHeight( elem, dimension, extra ) {
|
||||
|
||||
// Start with computed style
|
||||
var valueIsBorderBox,
|
||||
styles = getStyles( elem ),
|
||||
val = curCSS( elem, name, styles ),
|
||||
val = curCSS( elem, dimension, styles ),
|
||||
isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
|
||||
|
||||
// Computed unit is not pixels. Stop here and return.
|
||||
@ -142,25 +161,28 @@ function getWidthOrHeight( elem, name, extra ) {
|
||||
// Check for style in case a browser which returns unreliable values
|
||||
// for getComputedStyle silently falls back to the reliable elem.style
|
||||
valueIsBorderBox = isBorderBox &&
|
||||
( support.boxSizingReliable() || val === elem.style[ name ] );
|
||||
( support.boxSizingReliable() || val === elem.style[ dimension ] );
|
||||
|
||||
// Fall back to offsetWidth/Height when value is "auto"
|
||||
// This happens for inline elements with no explicit setting (gh-3571)
|
||||
if ( val === "auto" ) {
|
||||
val = elem[ "offset" + name[ 0 ].toUpperCase() + name.slice( 1 ) ];
|
||||
val = elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ];
|
||||
}
|
||||
|
||||
// Normalize "", auto, and prepare for extra
|
||||
// Normalize "" and auto
|
||||
val = parseFloat( val ) || 0;
|
||||
|
||||
// Use the active box-sizing model to add/subtract irrelevant styles
|
||||
// Adjust for the element's box model
|
||||
return ( val +
|
||||
augmentWidthOrHeight(
|
||||
boxModelAdjustment(
|
||||
elem,
|
||||
name,
|
||||
dimension,
|
||||
extra || ( isBorderBox ? "border" : "content" ),
|
||||
valueIsBorderBox,
|
||||
styles
|
||||
styles,
|
||||
|
||||
// Provide the current computed size to request scroll gutter calculation (gh-3589)
|
||||
val
|
||||
)
|
||||
) + "px";
|
||||
}
|
||||
@ -319,8 +341,8 @@ jQuery.extend( {
|
||||
}
|
||||
} );
|
||||
|
||||
jQuery.each( [ "height", "width" ], function( i, name ) {
|
||||
jQuery.cssHooks[ name ] = {
|
||||
jQuery.each( [ "height", "width" ], function( i, dimension ) {
|
||||
jQuery.cssHooks[ dimension ] = {
|
||||
get: function( elem, computed, extra ) {
|
||||
if ( computed ) {
|
||||
|
||||
@ -336,18 +358,18 @@ jQuery.each( [ "height", "width" ], function( i, name ) {
|
||||
// in IE throws an error.
|
||||
( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ?
|
||||
swap( elem, cssShow, function() {
|
||||
return getWidthOrHeight( elem, name, extra );
|
||||
return getWidthOrHeight( elem, dimension, extra );
|
||||
} ) :
|
||||
getWidthOrHeight( elem, name, extra );
|
||||
getWidthOrHeight( elem, dimension, extra );
|
||||
}
|
||||
},
|
||||
|
||||
set: function( elem, value, extra ) {
|
||||
var matches,
|
||||
styles = extra && getStyles( elem ),
|
||||
subtract = extra && augmentWidthOrHeight(
|
||||
styles = getStyles( elem ),
|
||||
subtract = extra && boxModelAdjustment(
|
||||
elem,
|
||||
name,
|
||||
dimension,
|
||||
extra,
|
||||
jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
|
||||
styles
|
||||
@ -357,8 +379,8 @@ jQuery.each( [ "height", "width" ], function( i, name ) {
|
||||
if ( subtract && ( matches = rcssNum.exec( value ) ) &&
|
||||
( matches[ 3 ] || "px" ) !== "px" ) {
|
||||
|
||||
elem.style[ name ] = value;
|
||||
value = jQuery.css( elem, name );
|
||||
elem.style[ dimension ] = value;
|
||||
value = jQuery.css( elem, dimension );
|
||||
}
|
||||
|
||||
return setPositiveNumber( elem, value, subtract );
|
||||
|
@ -544,4 +544,87 @@ QUnit.test( "width/height on an inline element with no explicitly-set dimensions
|
||||
} );
|
||||
} );
|
||||
|
||||
QUnit.test( "interaction with scrollbars (gh-3589)", function( assert ) {
|
||||
assert.expect( 36 );
|
||||
|
||||
var i,
|
||||
suffix = "",
|
||||
updater = function( adjustment ) {
|
||||
return function( i, old ) {
|
||||
return old + adjustment;
|
||||
};
|
||||
},
|
||||
parent = jQuery( "<div/>" )
|
||||
.css( { position: "absolute", width: "1000px", height: "1000px" } )
|
||||
.appendTo( "#qunit-fixture" ),
|
||||
fraction = jQuery( "<div style='width:4.5px;'/>" ).appendTo( parent ).width() % 1,
|
||||
borderWidth = 1,
|
||||
padding = 2,
|
||||
size = 100 + fraction,
|
||||
scrollBox = {
|
||||
position: "absolute",
|
||||
overflow: "scroll",
|
||||
width: size + "px",
|
||||
height: size + "px"
|
||||
},
|
||||
borderBox = {
|
||||
border: borderWidth + "px solid blue",
|
||||
padding: padding + "px"
|
||||
},
|
||||
plainContentBox = jQuery( "<div />" )
|
||||
.css( scrollBox )
|
||||
.css( { "box-sizing": "content-box" } )
|
||||
.appendTo( parent ),
|
||||
contentBox = jQuery( "<div />" )
|
||||
.css( scrollBox )
|
||||
.css( borderBox )
|
||||
.css( { "box-sizing": "content-box" } )
|
||||
.appendTo( parent ),
|
||||
borderBox = jQuery( "<div />" )
|
||||
.css( scrollBox )
|
||||
.css( borderBox )
|
||||
.css( { "box-sizing": "border-box" } )
|
||||
.appendTo( parent ),
|
||||
$boxes = jQuery( [ plainContentBox[ 0 ], contentBox[ 0 ], borderBox[ 0 ] ] );
|
||||
|
||||
for ( i = 0; i < 3; i++ ) {
|
||||
if ( i === 1 ) {
|
||||
suffix = " after increasing inner* by " + i;
|
||||
size += i;
|
||||
$boxes.innerWidth( updater( i ) ).innerHeight( updater( i ) );
|
||||
} else if ( i === 2 ) {
|
||||
suffix = " after increasing outer* by " + i;
|
||||
size += i;
|
||||
$boxes.outerWidth( updater( i ) ).outerHeight( updater( i ) );
|
||||
}
|
||||
|
||||
assert.equal( plainContentBox.innerWidth(), size,
|
||||
"plain content-box innerWidth includes scroll gutter" + suffix );
|
||||
assert.equal( plainContentBox.innerHeight(), size,
|
||||
"plain content-box innerHeight includes scroll gutter" + suffix );
|
||||
assert.equal( plainContentBox.outerWidth(), size,
|
||||
"plain content-box outerWidth includes scroll gutter" + suffix );
|
||||
assert.equal( plainContentBox.outerHeight(), size,
|
||||
"plain content-box outerHeight includes scroll gutter" + suffix );
|
||||
|
||||
assert.equal( contentBox.innerWidth(), size + 2 * padding,
|
||||
"content-box innerWidth includes scroll gutter" + suffix );
|
||||
assert.equal( contentBox.innerHeight(), size + 2 * padding,
|
||||
"content-box innerHeight includes scroll gutter" + suffix );
|
||||
assert.equal( contentBox.outerWidth(), size + 2 * padding + 2 * borderWidth,
|
||||
"content-box outerWidth includes scroll gutter" + suffix );
|
||||
assert.equal( contentBox.outerHeight(), size + 2 * padding + 2 * borderWidth,
|
||||
"content-box outerHeight includes scroll gutter" + suffix );
|
||||
|
||||
assert.equal( borderBox.innerWidth(), size - 2 * borderWidth,
|
||||
"border-box innerWidth includes scroll gutter" + suffix );
|
||||
assert.equal( borderBox.innerHeight(), size - 2 * borderWidth,
|
||||
"border-box innerHeight includes scroll gutter" + suffix );
|
||||
assert.equal( borderBox.outerWidth(), size,
|
||||
"border-box outerWidth includes scroll gutter" + suffix );
|
||||
assert.equal( borderBox.outerHeight(), size,
|
||||
"border-box outerHeight includes scroll gutter" + suffix );
|
||||
}
|
||||
} );
|
||||
|
||||
} )();
|
||||
|
Loading…
Reference in New Issue
Block a user