Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

1.8 effects special easing #750

Closed
wants to merge 2 commits into from

4 participants

@gibson042
Collaborator

@gnarf37's explanation of the "special easing" issue from #731 inspired me to dig a little deeper. Subsequent investigation revealed that the counterintuitive behavior would actually result in a bug if one tried to animate a compound property like .animate({ borderWidth: [ 10, "linear" ]}). This changeset fixes the bug by moving the relevant logic in front of CSS compound property expansion.

Pull now and you'll get a bonus size reduction PLUS the ability to handle array-valued properties with all prefilters¹!

jQuery Size - compared to 54fab31

  253601    (+40) jquery.js
   94059    (-16) jquery.min.js
   33503     (-1) jquery.min.js.gz

¹ Provided you use this.originalProperties and remember to cleanup like this.opts.specialEasing[ jQuery.camelCase( prop ) ] = this.originalOptions.specialEasing[ prop ]

@mikesherov
Collaborator

Pretty cool... can you also provide a unit test for this behavior?

@gnarf
Owner

:+1: - I think now that this part of the first prefilter is in the propFilter, we might be able to move the other part of that first prefilter (the overflow on width/height) into the show/hide prefilter to maybe save some size. Also, we can maybe define the prefilter as a named function that is put into the animationPrefilters automatically rather than using the Animate.prefilter()

@gibson042
Collaborator

@mikesherov, I'll try to slip in a unit test today
@gnarf37, I was thinking the same thing :)

@gibson042
Collaborator

jQuery Size - compared to 54fab31

  253538    (-23) jquery.js
   94014    (-61) jquery.min.js
   33477    (-27) jquery.min.js.gz
@mikesherov
Collaborator

of course you snuck another 27 bytes out. Of course.

@mikesherov
Collaborator

What nice here is that this is a simple change with big benefits. Good eye as usual.

@dmethvin dmethvin closed this in afb34fe
@markelog markelog referenced this pull request from a commit in markelog/jquery
@gibson042 gibson042 Scalarize [value, easing] before css-expanding; closes gh-750. 842d503
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Apr 24, 2012
  1. @gibson042
Commits on Apr 26, 2012
  1. @gibson042
This page is out of date. Refresh to see the latest.
Showing with 77 additions and 34 deletions.
  1. +30 −34 src/effects.js
  2. +47 −0 test/unit/effects.js
View
64 src/effects.js
@@ -5,7 +5,7 @@ var fxNow, timerId, iframe, iframeDoc,
rfxtypes = /^(?:toggle|show|hide)$/,
rfxnum = /^([\-+]=)?((?:\d*\.)?\d+)([a-z%]*)$/i,
rrun = /\.run$/,
- animationPrefilters = [],
+ animationPrefilters = [ defaultPrefilter ],
tweeners = {
"*": [function( prop, value ) {
var end, unit,
@@ -73,10 +73,10 @@ function Animation( elem, properties, options ) {
}),
animation = deferred.promise({
elem: elem,
+ props: jQuery.extend( {}, properties ),
+ opts: jQuery.extend( true, { specialEasing: {} }, options ),
originalProperties: properties,
originalOptions: options,
- props: jQuery.extend( {}, properties ),
- opts: jQuery.extend( {}, options ),
startTime: fxNow || createFxNow(),
duration: options.duration,
finish: finished.done,
@@ -120,7 +120,7 @@ function Animation( elem, properties, options ) {
}),
props = animation.props;
- propFilter( props );
+ propFilter( props, animation.opts.specialEasing );
for ( ; index < length ; index++ ) {
result = animationPrefilters[ index ].call( animation,
@@ -142,30 +142,39 @@ function Animation( elem, properties, options ) {
return animation;
}
-function propFilter( props ) {
- var index, name, hooks, replace;
+function propFilter( props, specialEasing ) {
+ var index, name, easing, value, hooks;
- // camelCase and expand cssHook pass
+ // camelCase, specialEasing and expand cssHook pass
for ( index in props ) {
name = jQuery.camelCase( index );
+ easing = specialEasing[ name ];
+ value = props[ index ];
+ if ( jQuery.isArray( value ) ) {
+ easing = value[ 1 ];
+ value = props[ index ] = value[ 0 ];
+ }
+
if ( index !== name ) {
- props[ name ] = props[ index ];
+ props[ name ] = value;
delete props[ index ];
}
hooks = jQuery.cssHooks[ name ];
if ( hooks && "expand" in hooks ) {
- replace = hooks.expand( props[ name ] );
+ value = hooks.expand( value );
delete props[ name ];
// not quite $.extend, this wont overwrite keys already present.
// also - reusing 'index' from above because we have the correct "name"
- for ( index in replace ) {
- if ( index in props ) {
- continue;
+ for ( index in value ) {
+ if ( !( index in props ) ) {
+ props[ index ] = value[ index ];
+ specialEasing[ index ] = easing;
}
- props[ index ] = replace[ index ];
}
+ } else {
+ specialEasing[ name ] = easing;
}
}
}
@@ -200,19 +209,12 @@ jQuery.Animation = jQuery.extend( Animation, {
}
});
-Animation.prefilter(function( elem, props, opts ) {
- var index, value,
- style = elem.style;
-
- // custom easing pass
- opts.specialEasing = opts.specialEasing || {};
- for ( index in props ) {
- value = props[ index ];
- if ( jQuery.isArray( value ) ) {
- opts.specialEasing[ index ] = value[ 1 ];
- value = props[ index ] = value[ 0 ];
- }
- }
+function defaultPrefilter( elem, props, opts ) {
+ var index, prop, value, length, dataShow, tween,
+ style = elem.style,
+ orig = {},
+ handled = [],
+ hidden = jQuery( elem ).is(":hidden");
// height/width overflow pass
if ( elem.nodeType === 1 && ( props.height || props.width ) ) {
@@ -246,15 +248,9 @@ Animation.prefilter(function( elem, props, opts ) {
style.overflowY = opts.overflow[ 2 ];
});
}
-});
-// special case show/hide prefilter
-Animation.prefilter(function( elem, props, opts ) {
- var index, prop, value, length, dataShow, tween,
- orig = {},
- handled = [],
- hidden = jQuery( elem ).is(":hidden");
+ // show/hide pass
for ( index in props ) {
value = props[ index ];
if ( rfxtypes.exec( value ) ) {
@@ -297,7 +293,7 @@ Animation.prefilter(function( elem, props, opts ) {
}
}
}
-});
+}
function Tween( elem, options, prop, end, easing ) {
return new Tween.prototype.init( elem, options, prop, end, easing );
View
47 test/unit/effects.js
@@ -1248,6 +1248,53 @@ test("animate with per-property easing", function(){
});
+test("animate with CSS shorthand properties", function(){
+ expect(11);
+ stop();
+
+ var _default_count = 0,
+ _special_count = 0,
+ propsBasic = { padding: "10 20 30" },
+ propsSpecial = { padding: [ "1 2 3", "_special" ] };
+
+ jQuery.easing["_default"] = function(p) {
+ if ( p >= 1 ) {
+ _default_count++;
+ }
+ return p;
+ };
+
+ jQuery.easing["_special"] = function(p) {
+ if ( p >= 1 ) {
+ _special_count++;
+ }
+ return p;
+ };
+
+ jQuery("#foo")
+ .animate( propsBasic, 200, "_default", function() {
+ equal( this.style.paddingTop, "10px", "padding-top was animated" );
+ equal( this.style.paddingLeft, "20px", "padding-left was animated" );
+ equal( this.style.paddingRight, "20px", "padding-right was animated" );
+ equal( this.style.paddingBottom, "30px", "padding-bottom was animated" );
+ equal( _default_count, 4, "per-animation default easing called for each property" );
+ _default_count = 0;
+ })
+ .animate( propsSpecial, 200, "_default", function() {
+ equal( this.style.paddingTop, "1px", "padding-top was animated again" );
+ equal( this.style.paddingLeft, "2px", "padding-left was animated again" );
+ equal( this.style.paddingRight, "2px", "padding-right was animated again" );
+ equal( this.style.paddingBottom, "3px", "padding-bottom was animated again" );
+ equal( _default_count, 0, "per-animation default easing not called" );
+ equal( _special_count, 4, "special easing called for each property" );
+
+ jQuery(this).css("padding", "0");
+ delete jQuery.easing["_default"];
+ delete jQuery.easing["_special"];
+ start();
+ });
+});
+
test("hide hidden elements (bug #7141)", function() {
expect(3);
QUnit.reset();
Something went wrong with that request. Please try again.