mirror of
https://github.com/jquery/jquery.git
synced 2024-11-23 02:54:22 +00:00
Fix #13855: line-height animations. Close gh-1265.
This commit is contained in:
parent
c1b8edfcc9
commit
3971c2ebb2
@ -164,7 +164,7 @@ jQuery.extend({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// Exclude the following css properties to add px
|
// Don't automatically add "px" to these possibly-unitless properties
|
||||||
cssNumber: {
|
cssNumber: {
|
||||||
"columnCount": true,
|
"columnCount": true,
|
||||||
"fillOpacity": true,
|
"fillOpacity": true,
|
||||||
|
117
src/effects.js
vendored
117
src/effects.js
vendored
@ -5,44 +5,51 @@ var fxNow, timerId,
|
|||||||
animationPrefilters = [ defaultPrefilter ],
|
animationPrefilters = [ defaultPrefilter ],
|
||||||
tweeners = {
|
tweeners = {
|
||||||
"*": [function( prop, value ) {
|
"*": [function( prop, value ) {
|
||||||
var end, unit,
|
var tween = this.createTween( prop, value ),
|
||||||
tween = this.createTween( prop, value ),
|
|
||||||
parts = rfxnum.exec( value ),
|
|
||||||
target = tween.cur(),
|
target = tween.cur(),
|
||||||
start = +target || 0,
|
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,
|
scale = 1,
|
||||||
maxIterations = 20;
|
maxIterations = 20;
|
||||||
|
|
||||||
if ( parts ) {
|
if ( start && start[ 3 ] !== unit ) {
|
||||||
end = +parts[2];
|
// Trust units reported by jQuery.css
|
||||||
unit = parts[3] || ( jQuery.cssNumber[ prop ] ? "" : "px" );
|
unit = unit || start[ 3 ];
|
||||||
|
|
||||||
// We need to compute starting value
|
// Make sure we update the tween properties later on
|
||||||
if ( unit !== "px" && start ) {
|
parts = parts || [];
|
||||||
// Iteratively approximate from a nonzero starting point
|
|
||||||
// Prefer the current property, because this process will be trivial if it uses the same units
|
|
||||||
// Fallback to end or a simple constant
|
|
||||||
start = jQuery.css( tween.elem, prop, true ) || end || 1;
|
|
||||||
|
|
||||||
do {
|
// Iteratively approximate from a nonzero starting point
|
||||||
// If previous iteration zeroed out, double until we get *something*
|
start = +target || 1;
|
||||||
// Use a string for doubling factor so we don't accidentally see scale as unchanged below
|
|
||||||
scale = scale || ".5";
|
|
||||||
|
|
||||||
// Adjust and apply
|
do {
|
||||||
start = start / scale;
|
// If previous iteration zeroed out, double until we get *something*
|
||||||
jQuery.style( tween.elem, prop, start + unit );
|
// Use a string for doubling factor so we don't accidentally see scale as unchanged below
|
||||||
|
scale = scale || ".5";
|
||||||
|
|
||||||
// Update scale, tolerating zero or NaN from tween.cur()
|
// Adjust and apply
|
||||||
// And breaking the loop if scale is unchanged or perfect, or if we've just had enough
|
start = start / scale;
|
||||||
} while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );
|
jQuery.style( tween.elem, prop, start + unit );
|
||||||
}
|
|
||||||
|
|
||||||
tween.unit = unit;
|
// Update scale, tolerating zero or NaN from tween.cur()
|
||||||
tween.start = start;
|
// And breaking the loop if scale is unchanged or perfect, or if we've just had enough
|
||||||
// If a +=/-= token was provided, we're doing a relative animation
|
} while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );
|
||||||
tween.end = parts[1] ? start + ( parts[1] + 1 ) * end : end;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update tween properties
|
||||||
|
if ( parts ) {
|
||||||
|
tween.unit = unit;
|
||||||
|
tween.start = +start || +target || 0;
|
||||||
|
// If a +=/-= token was provided, we're doing a relative animation
|
||||||
|
tween.end = parts[ 1 ] ?
|
||||||
|
start + ( parts[ 1 ] + 1 ) * parts[ 2 ] :
|
||||||
|
+parts[ 2 ];
|
||||||
|
}
|
||||||
|
|
||||||
return tween;
|
return tween;
|
||||||
}]
|
}]
|
||||||
};
|
};
|
||||||
@ -55,19 +62,18 @@ function createFxNow() {
|
|||||||
return ( fxNow = jQuery.now() );
|
return ( fxNow = jQuery.now() );
|
||||||
}
|
}
|
||||||
|
|
||||||
function createTweens( animation, props ) {
|
function createTween( value, prop, animation ) {
|
||||||
jQuery.each( props, function( prop, value ) {
|
var tween,
|
||||||
var collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ),
|
collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ),
|
||||||
index = 0,
|
index = 0,
|
||||||
length = collection.length;
|
length = collection.length;
|
||||||
for ( ; index < length; index++ ) {
|
for ( ; index < length; index++ ) {
|
||||||
if ( collection[ index ].call( animation, prop, value ) ) {
|
if ( (tween = collection[ index ].call( animation, prop, value )) ) {
|
||||||
|
|
||||||
// we're done with this property
|
// we're done with this property
|
||||||
return;
|
return tween;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function Animation( elem, properties, options ) {
|
function Animation( elem, properties, options ) {
|
||||||
@ -153,7 +159,7 @@ function Animation( elem, properties, options ) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
createTweens( animation, props );
|
jQuery.map( props, createTween, animation );
|
||||||
|
|
||||||
if ( jQuery.isFunction( animation.opts.start ) ) {
|
if ( jQuery.isFunction( animation.opts.start ) ) {
|
||||||
animation.opts.start.call( elem, animation );
|
animation.opts.start.call( elem, animation );
|
||||||
@ -243,12 +249,12 @@ jQuery.Animation = jQuery.extend( Animation, {
|
|||||||
|
|
||||||
function defaultPrefilter( elem, props, opts ) {
|
function defaultPrefilter( elem, props, opts ) {
|
||||||
/* jshint validthis: true */
|
/* jshint validthis: true */
|
||||||
var index, prop, value, length, dataShow, toggle, tween, hooks, oldfire,
|
var index, prop, value, toggle, tween, hooks, oldfire,
|
||||||
anim = this,
|
anim = this,
|
||||||
style = elem.style,
|
|
||||||
orig = {},
|
orig = {},
|
||||||
handled = [],
|
style = elem.style,
|
||||||
hidden = elem.nodeType && isHidden( elem );
|
hidden = elem.nodeType && isHidden( elem ),
|
||||||
|
dataShow = data_priv.get( elem, "fxshow" );
|
||||||
|
|
||||||
// handle queue: false promises
|
// handle queue: false promises
|
||||||
if ( !opts.queue ) {
|
if ( !opts.queue ) {
|
||||||
@ -304,7 +310,6 @@ function defaultPrefilter( elem, props, opts ) {
|
|||||||
|
|
||||||
|
|
||||||
// show/hide pass
|
// show/hide pass
|
||||||
dataShow = data_priv.get( elem, "fxshow" );
|
|
||||||
for ( index in props ) {
|
for ( index in props ) {
|
||||||
value = props[ index ];
|
value = props[ index ];
|
||||||
if ( rfxtypes.exec( value ) ) {
|
if ( rfxtypes.exec( value ) ) {
|
||||||
@ -313,21 +318,23 @@ function defaultPrefilter( elem, props, opts ) {
|
|||||||
if ( value === ( hidden ? "hide" : "show" ) ) {
|
if ( value === ( hidden ? "hide" : "show" ) ) {
|
||||||
|
|
||||||
// If there is dataShow left over from a stopped hide or show and we are going to proceed with show, we should pretend to be hidden
|
// If there is dataShow left over from a stopped hide or show and we are going to proceed with show, we should pretend to be hidden
|
||||||
if( value === "show" && dataShow !== undefined && dataShow[ index ] !== undefined ) {
|
if ( value === "show" && dataShow && dataShow[ index ] !== undefined ) {
|
||||||
hidden = true;
|
hidden = true;
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
handled.push( index );
|
orig[ index ] = dataShow && dataShow[ index ] || jQuery.style( elem, index );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
length = handled.length;
|
if ( !jQuery.isEmptyObject( orig ) ) {
|
||||||
if ( length ) {
|
if ( dataShow ) {
|
||||||
dataShow = data_priv.get( elem, "fxshow" ) || data_priv.access( elem, "fxshow", {} );
|
if ( "hidden" in dataShow ) {
|
||||||
if ( "hidden" in dataShow ) {
|
hidden = dataShow.hidden;
|
||||||
hidden = dataShow.hidden;
|
}
|
||||||
|
} else {
|
||||||
|
dataShow = data_priv.access( elem, "fxshow", {} );
|
||||||
}
|
}
|
||||||
|
|
||||||
// store state if its toggle - enables .stop().toggle() to "reverse"
|
// store state if its toggle - enables .stop().toggle() to "reverse"
|
||||||
@ -349,10 +356,8 @@ function defaultPrefilter( elem, props, opts ) {
|
|||||||
jQuery.style( elem, prop, orig[ prop ] );
|
jQuery.style( elem, prop, orig[ prop ] );
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
for ( index = 0 ; index < length ; index++ ) {
|
for ( prop in orig ) {
|
||||||
prop = handled[ index ];
|
tween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );
|
||||||
tween = anim.createTween( prop, hidden ? dataShow[ prop ] : 0 );
|
|
||||||
orig[ prop ] = dataShow[ prop ] || jQuery.style( elem, prop );
|
|
||||||
|
|
||||||
if ( !( prop in dataShow ) ) {
|
if ( !( prop in dataShow ) ) {
|
||||||
dataShow[ prop ] = tween.start;
|
dataShow[ prop ] = tween.start;
|
||||||
|
38
test/unit/effects.js
vendored
38
test/unit/effects.js
vendored
@ -1371,6 +1371,44 @@ test("Do not append px to 'fill-opacity' #9548", 1, function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("line-height animates correctly (#13855)", function() {
|
||||||
|
expect( 12 );
|
||||||
|
stop();
|
||||||
|
|
||||||
|
var
|
||||||
|
animated = jQuery(
|
||||||
|
"<p style='line-height: 4;'>unitless</p>" +
|
||||||
|
"<p style='line-height: 50px;'>px</p>" +
|
||||||
|
"<p style='line-height: 120%;'>percent</p>" +
|
||||||
|
"<p style='line-height: 1.5em;'>em</p>"
|
||||||
|
).appendTo("#qunit-fixture"),
|
||||||
|
initialHeight = jQuery.map( animated, function( el ) {
|
||||||
|
return jQuery( el ).height();
|
||||||
|
});
|
||||||
|
|
||||||
|
animated.animate( { "line-height": "hide" }, 1500 );
|
||||||
|
setTimeout(function() {
|
||||||
|
animated.each(function( i ) {
|
||||||
|
var label = jQuery.text( this ),
|
||||||
|
initial = initialHeight[ i ],
|
||||||
|
height = jQuery( this ).height();
|
||||||
|
ok( height < initial, "hide " + label + ": upper bound" );
|
||||||
|
ok( height > initial / 2, "hide " + label + ": lower bound" );
|
||||||
|
});
|
||||||
|
animated.stop( true, true ).hide().animate( { "line-height": "show" }, 1500 );
|
||||||
|
setTimeout(function() {
|
||||||
|
animated.each(function( i ) {
|
||||||
|
var label = jQuery.text( this ),
|
||||||
|
initial = initialHeight[ i ],
|
||||||
|
height = jQuery( this ).height();
|
||||||
|
ok( height < initial / 2, "show " + label + ": upper bound" );
|
||||||
|
});
|
||||||
|
animated.stop( true, true );
|
||||||
|
start();
|
||||||
|
}, 400 );
|
||||||
|
}, 400 );
|
||||||
|
});
|
||||||
|
|
||||||
// Start 1.8 Animation tests
|
// Start 1.8 Animation tests
|
||||||
asyncTest( "jQuery.Animation( object, props, opts )", 4, function() {
|
asyncTest( "jQuery.Animation( object, props, opts )", 4, function() {
|
||||||
var animation,
|
var animation,
|
||||||
|
Loading…
Reference in New Issue
Block a user