CSS: Support relative adjustment in any applicable unit

Fixes gh-1711
Closes gh-2011

(cherry picked from commit 9b03f6df88)

Conflicts:
	src/css.js
	src/effects.js
This commit is contained in:
Mr21
2015-02-04 14:10:14 +01:00
committed by Richard Gibson
parent 9edd95ffd7
commit 6fb2cefc60
5 changed files with 135 additions and 61 deletions

View File

@@ -3,10 +3,12 @@ define([
"./var/pnum",
"./core/access",
"./css/var/rmargin",
"./var/rcssNum",
"./css/var/rnumnonpx",
"./css/var/cssExpand",
"./css/var/isHidden",
"./css/curCSS",
"./css/adjustCSS",
"./css/defaultDisplay",
"./css/addGetHookIf",
"./css/support",
@@ -15,8 +17,8 @@ define([
"./css/swap",
"./core/ready",
"./selector" // contains
], function( jQuery, pnum, access, rmargin, rnumnonpx, cssExpand, isHidden,
curCSS, defaultDisplay, addGetHookIf, support ) {
], function( jQuery, pnum, access, rmargin, rcssNum, rnumnonpx, cssExpand, isHidden,
curCSS, adjustCSS, defaultDisplay, addGetHookIf, support ) {
var
// BuildExclude
@@ -30,7 +32,6 @@ var
// https://developer.mozilla.org/en-US/docs/CSS/display
rdisplayswap = /^(none|table(?!-c[ea]).+)/,
rnumsplit = new RegExp( "^(" + pnum + ")(.*)$", "i" ),
rrelNum = new RegExp( "^([+-])=(" + pnum + ")", "i" ),
cssShow = { position: "absolute", visibility: "hidden", display: "block" },
cssNormalTransform = {
@@ -273,9 +274,9 @@ jQuery.extend({
if ( value !== undefined ) {
type = typeof value;
// convert relative number strings (+= or -=) to relative numbers. #7345
if ( type === "string" && (ret = rrelNum.exec( value )) ) {
value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );
// Convert "+=" or "-=" to relative numbers (#7345)
if ( type === "string" && (ret = rcssNum.exec( value )) && ret[ 1 ] ) {
value = adjustCSS( elem, name, ret );
// Fixes bug #9237
type = "number";
}
@@ -285,9 +286,9 @@ jQuery.extend({
return;
}
// If a number was passed in, add 'px' (except for certain CSS properties)
if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
value += "px";
// If a number was passed in, add the unit (except for certain CSS properties)
if ( type === "number" ) {
value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" );
}
// Fixes #8908, it can be done more correctly by specifing setters in cssHooks,

61
src/css/adjustCSS.js Normal file
View File

@@ -0,0 +1,61 @@
define([
"../core",
"../var/rcssNum"
], function( jQuery, rcssNum ) {
function adjustCSS( elem, prop, valueParts, tween ) {
var adjusted,
scale = 1,
maxIterations = 20,
currentValue = tween ?
function() { return tween.cur(); } :
function() { return jQuery.css( elem, prop, "" ); },
initial = currentValue(),
unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ),
// Starting value computation is required for potential unit mismatches
initialInUnit = ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) &&
rcssNum.exec( jQuery.css( elem, prop ) );
if ( initialInUnit && initialInUnit[ 3 ] !== unit ) {
// Trust units reported by jQuery.css
unit = unit || initialInUnit[ 3 ];
// Make sure we update the tween properties later on
valueParts = valueParts || [];
// Iteratively approximate from a nonzero starting point
initialInUnit = +initial || 1;
do {
// If previous iteration zeroed out, double until we get *something*.
// Use string for doubling so we don't accidentally see scale as unchanged below
scale = scale || ".5";
// Adjust and apply
initialInUnit = initialInUnit / scale;
jQuery.style( elem, prop, initialInUnit + unit );
// Update scale, tolerating zero or NaN from tween.cur()
// Break the loop if scale is unchanged or perfect, or if we've just had enough.
} while (
scale !== (scale = currentValue() / initial) && scale !== 1 && --maxIterations
);
}
if ( valueParts ) {
initialInUnit = +initialInUnit || +initial || 0;
// Apply relative offset (+=/-=) if specified
adjusted = valueParts[ 1 ] ?
initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] :
+valueParts[ 2 ];
if ( tween ) {
tween.unit = unit;
tween.start = initialInUnit;
tween.end = adjusted;
}
}
return adjusted;
}
return adjustCSS;
});

57
src/effects.js vendored
View File

@@ -1,8 +1,9 @@
define([
"./core",
"./var/pnum",
"./var/rcssNum",
"./css/var/cssExpand",
"./css/var/isHidden",
"./css/adjustCSS",
"./css/defaultDisplay",
"./core/init",
@@ -11,65 +12,17 @@ define([
"./css",
"./deferred",
"./traversing"
], function( jQuery, pnum, cssExpand, isHidden, defaultDisplay ) {
], function( jQuery, rcssNum, cssExpand, isHidden, adjustCSS, defaultDisplay ) {
var
fxNow, timerId,
rfxtypes = /^(?:toggle|show|hide)$/,
rfxnum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ),
rrun = /queueHooks$/,
animationPrefilters = [ defaultPrefilter ],
tweeners = {
"*": [ function( prop, value ) {
var tween = this.createTween( prop, value ),
target = tween.cur(),
parts = rfxnum.exec( value ),
unit = parts && parts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ),
// Starting value computation is required for potential unit mismatches
start = ( jQuery.cssNumber[ prop ] || unit !== "px" && +target ) &&
rfxnum.exec( jQuery.css( tween.elem, prop ) ),
scale = 1,
maxIterations = 20;
if ( start && start[ 3 ] !== unit ) {
// Trust units reported by jQuery.css
unit = unit || start[ 3 ];
// Make sure we update the tween properties later on
parts = parts || [];
// Iteratively approximate from a nonzero starting point
start = +target || 1;
do {
// If previous iteration zeroed out, double until we get *something*
// Use a string for doubling factor so we don't accidentally see scale
// as unchanged below
scale = scale || ".5";
// Adjust and apply
start = start / scale;
jQuery.style( tween.elem, prop, start + unit );
// Update scale, tolerating zero or NaN from tween.cur()
// And breaking the loop if scale is unchanged or perfect,
// or if we've just had enough
} while (
scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations
);
}
// Update tween properties
if ( parts ) {
start = tween.start = +start || +target || 0;
tween.unit = unit;
// If a +=/-= token was provided, we're doing a relative animation
tween.end = parts[ 1 ] ?
start + ( parts[ 1 ] + 1 ) * parts[ 2 ] :
+parts[ 2 ];
}
var tween = this.createTween( prop, value );
adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween );
return tween;
} ]
};

7
src/var/rcssNum.js Normal file
View File

@@ -0,0 +1,7 @@
define([
"../var/pnum"
], function( pnum ) {
return new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" );
});