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: {
|
||||
"columnCount": true,
|
||||
"fillOpacity": true,
|
||||
|
117
src/effects.js
vendored
117
src/effects.js
vendored
@ -5,44 +5,51 @@ var fxNow, timerId,
|
||||
animationPrefilters = [ defaultPrefilter ],
|
||||
tweeners = {
|
||||
"*": [function( prop, value ) {
|
||||
var end, unit,
|
||||
tween = this.createTween( prop, value ),
|
||||
parts = rfxnum.exec( value ),
|
||||
var tween = this.createTween( prop, value ),
|
||||
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,
|
||||
maxIterations = 20;
|
||||
|
||||
if ( parts ) {
|
||||
end = +parts[2];
|
||||
unit = parts[3] || ( jQuery.cssNumber[ prop ] ? "" : "px" );
|
||||
if ( start && start[ 3 ] !== unit ) {
|
||||
// Trust units reported by jQuery.css
|
||||
unit = unit || start[ 3 ];
|
||||
|
||||
// We need to compute starting value
|
||||
if ( unit !== "px" && start ) {
|
||||
// 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;
|
||||
// Make sure we update the tween properties later on
|
||||
parts = parts || [];
|
||||
|
||||
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";
|
||||
// Iteratively approximate from a nonzero starting point
|
||||
start = +target || 1;
|
||||
|
||||
// Adjust and apply
|
||||
start = start / scale;
|
||||
jQuery.style( tween.elem, prop, start + unit );
|
||||
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";
|
||||
|
||||
// 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 );
|
||||
}
|
||||
// Adjust and apply
|
||||
start = start / scale;
|
||||
jQuery.style( tween.elem, prop, start + unit );
|
||||
|
||||
tween.unit = unit;
|
||||
tween.start = start;
|
||||
// If a +=/-= token was provided, we're doing a relative animation
|
||||
tween.end = parts[1] ? start + ( parts[1] + 1 ) * end : end;
|
||||
// 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 ) {
|
||||
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;
|
||||
}]
|
||||
};
|
||||
@ -55,19 +62,18 @@ function createFxNow() {
|
||||
return ( fxNow = jQuery.now() );
|
||||
}
|
||||
|
||||
function createTweens( animation, props ) {
|
||||
jQuery.each( props, function( prop, value ) {
|
||||
var collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ),
|
||||
index = 0,
|
||||
length = collection.length;
|
||||
for ( ; index < length; index++ ) {
|
||||
if ( collection[ index ].call( animation, prop, value ) ) {
|
||||
function createTween( value, prop, animation ) {
|
||||
var tween,
|
||||
collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ),
|
||||
index = 0,
|
||||
length = collection.length;
|
||||
for ( ; index < length; index++ ) {
|
||||
if ( (tween = collection[ index ].call( animation, prop, value )) ) {
|
||||
|
||||
// we're done with this property
|
||||
return;
|
||||
}
|
||||
// we're done with this property
|
||||
return tween;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
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 ) ) {
|
||||
animation.opts.start.call( elem, animation );
|
||||
@ -243,12 +249,12 @@ jQuery.Animation = jQuery.extend( Animation, {
|
||||
|
||||
function defaultPrefilter( elem, props, opts ) {
|
||||
/* jshint validthis: true */
|
||||
var index, prop, value, length, dataShow, toggle, tween, hooks, oldfire,
|
||||
var index, prop, value, toggle, tween, hooks, oldfire,
|
||||
anim = this,
|
||||
style = elem.style,
|
||||
orig = {},
|
||||
handled = [],
|
||||
hidden = elem.nodeType && isHidden( elem );
|
||||
style = elem.style,
|
||||
hidden = elem.nodeType && isHidden( elem ),
|
||||
dataShow = data_priv.get( elem, "fxshow" );
|
||||
|
||||
// handle queue: false promises
|
||||
if ( !opts.queue ) {
|
||||
@ -304,7 +310,6 @@ function defaultPrefilter( elem, props, opts ) {
|
||||
|
||||
|
||||
// show/hide pass
|
||||
dataShow = data_priv.get( elem, "fxshow" );
|
||||
for ( index in props ) {
|
||||
value = props[ index ];
|
||||
if ( rfxtypes.exec( value ) ) {
|
||||
@ -313,21 +318,23 @@ function defaultPrefilter( elem, props, opts ) {
|
||||
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( value === "show" && dataShow !== undefined && dataShow[ index ] !== undefined ) {
|
||||
if ( value === "show" && dataShow && dataShow[ index ] !== undefined ) {
|
||||
hidden = true;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
handled.push( index );
|
||||
orig[ index ] = dataShow && dataShow[ index ] || jQuery.style( elem, index );
|
||||
}
|
||||
}
|
||||
|
||||
length = handled.length;
|
||||
if ( length ) {
|
||||
dataShow = data_priv.get( elem, "fxshow" ) || data_priv.access( elem, "fxshow", {} );
|
||||
if ( "hidden" in dataShow ) {
|
||||
hidden = dataShow.hidden;
|
||||
if ( !jQuery.isEmptyObject( orig ) ) {
|
||||
if ( dataShow ) {
|
||||
if ( "hidden" in dataShow ) {
|
||||
hidden = dataShow.hidden;
|
||||
}
|
||||
} else {
|
||||
dataShow = data_priv.access( elem, "fxshow", {} );
|
||||
}
|
||||
|
||||
// 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 ] );
|
||||
}
|
||||
});
|
||||
for ( index = 0 ; index < length ; index++ ) {
|
||||
prop = handled[ index ];
|
||||
tween = anim.createTween( prop, hidden ? dataShow[ prop ] : 0 );
|
||||
orig[ prop ] = dataShow[ prop ] || jQuery.style( elem, prop );
|
||||
for ( prop in orig ) {
|
||||
tween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );
|
||||
|
||||
if ( !( prop in dataShow ) ) {
|
||||
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
|
||||
asyncTest( "jQuery.Animation( object, props, opts )", 4, function() {
|
||||
var animation,
|
||||
|
Loading…
Reference in New Issue
Block a user