Permalink
Browse files

animationComplete: Fix context for timeout/no support

Fixes gh-7916
Closes gh-7920
  • Loading branch information...
gabrielschulhof committed Jan 15, 2015
1 parent f8783db commit 1d6b53387f122e51525a813f8687a084bb156c5f
Showing with 163 additions and 11 deletions.
  1. +19 −8 js/animationComplete.js
  2. +144 −3 tests/integration/animation-complete/animationComplete.js
View
@@ -21,7 +21,7 @@ define( [
$.each( vendorPrefixes, function( j, prefix ) {
if ( testElement.style[ $.camelCase( prefix + testName ) ] !== undefined ) {
props[ test ][ "prefix" ] = prefix;
props[ test ][ "prefix" ] = prefix;
return false;
}
});
@@ -57,6 +57,10 @@ define( [
},
animationType = ( !type || type === "animation" ) ? "animation" : "transition";
if ( !this.length ) {
return this;
}
// Make sure selected type is supported by browser
if ( ( $.support.cssTransitions && animationType === "transition" ) ||
( $.support.cssAnimations && animationType === "animation" ) ) {
@@ -65,12 +69,12 @@ define( [
if ( fallbackTime === undefined ) {
// Make sure the was not bound to document before checking .css
if ( $( this ).context !== document ) {
if ( this.context !== document ) {
// Parse the durration since its in second multiple by 1000 for milliseconds
// Multiply by 3 to make sure we give the animation plenty of time.
duration = parseFloat(
$( this ).css( props[ animationType ].duration )
this.css( props[ animationType ].duration )
) * 3000;
}
@@ -82,18 +86,25 @@ define( [
// Sets up the fallback if event never comes
timer = setTimeout( function() {
$( that ).off( props[ animationType ].event, eventBinding );
callback.apply( that );
that
.off( props[ animationType ].event, eventBinding )
.each( function() {
callback.apply( this );
});
}, duration );
// Bind the event
return $( this ).one( props[ animationType ].event, eventBinding );
return this.one( props[ animationType ].event, eventBinding );
} else {
// CSS animation / transitions not supported
// Defer execution for consistency between webkit/non webkit
setTimeout( $.proxy( callback, this ), 0 );
return $( this );
setTimeout( function() {
that.each( function() {
callback.apply( this );
});
}, 0 );
return this;
}
};
@@ -127,7 +127,7 @@
transitionComplete = true;
}, "transition" );
$( "animation-test" ).addClass( "in" ).animationComplete( function() {
$( "#animation-test" ).addClass( "in" ).animationComplete( function() {
animationComplete = true;
});
@@ -159,10 +159,10 @@
animationComplete = true;
});
ok( Object.keys( $._data( $("#animation-test")[0], "events" ) ).length === 1,
"Only one animation event" );
"Only one animation event" );
ok( Object.keys( $._data( $("#transition-test")[0], "events" ) ).length === 1,
"Only one transition event" );
"Only one transition event" );
window.setTimeout( function(){
start();
}, 800 );
@@ -266,4 +266,145 @@
start();
}, 1200 );
});
var createContextChecker = function( expectedTransitionContext, expectedAnimationContext ) {
var actualAnimationContext, actualTransitionContext,
completeCount = 0,
maybeAssert = function() {
completeCount++;
if ( completeCount === 2 ) {
deepEqual( actualTransitionContext, expectedTransitionContext,
"Transition context is correct" );
deepEqual( actualAnimationContext, expectedAnimationContext,
"Animation context is correct" );
start();
}
};
return {
animationHandler: function() {
actualAnimationContext = this;
maybeAssert();
},
transitionHandler: function() {
actualTransitionContext = this;
maybeAssert();
}
};
};
module( "Callback context and return value: event", {
teardown: function() {
$( "#transition-test" )
.removeClass( "ui-panel-animate ui-panel-position-left ui-panel-display-overlay" );
$( "#animation-test" ).removeClass( "in" );
}
});
asyncTest( "Make sure context and return value is correct for event", function() {
expect( 4 );
var returnValue,
transitionTest = $( "#transition-test" ),
animationTest = $( "#animation-test" ),
checker = createContextChecker( transitionTest[ 0 ], animationTest[ 0 ] );
returnValue = transitionTest
.addClass( "ui-panel-animate ui-panel-position-left ui-panel-display-overlay" )
.animationComplete( checker.transitionHandler, "transition" );
deepEqual( returnValue, transitionTest,
"Returned jQuery object for transition is the one passed in" );
returnValue = animationTest
.addClass( "in" )
.animationComplete( checker.animationHandler );
deepEqual( returnValue, animationTest,
"Returned jQuery object for animation is the one passed in" );
});
module( "Callback context and return value: fallback" );
asyncTest( "Make sure context and return value is correct for fallback", function() {
expect( 4 );
var returnValue,
transitionTest = $( "#transition-test" ),
animationTest = $( "#animation-test" ),
checker = createContextChecker( transitionTest[ 0 ], animationTest[ 0 ] );
returnValue = transitionTest.animationComplete( checker.transitionHandler, "transition" );
deepEqual( returnValue, transitionTest,
"Returned jQuery object for transition is the one passed in" );
returnValue = animationTest.animationComplete( checker.animationHandler );
deepEqual( returnValue, animationTest,
"Returned jQuery object for animation is the one passed in" );
});
module( "Callback context and return value: no support", {
setup: function() {
oldTransitions = $.support.cssTransitions,
oldAnimations = $.support.cssAnimations;
$.support.cssAnimations = false;
$.support.cssTransitions = false;
},
teardown: function() {
$.support.cssTransitions = oldTransitions;
$.support.cssAnimations = oldAnimations;
$( "#transition-test" )
.removeClass( "ui-panel-animate ui-panel-position-left ui-panel-display-overlay" );
$( "#animation-test" ).removeClass( "in" );
}
});
asyncTest( "Make sure context and return value is correct for no support", function() {
expect( 4 );
var returnValue,
transitionTest = $( "#transition-test" ),
animationTest = $( "#animation-test" ),
checker = createContextChecker( transitionTest[ 0 ], animationTest[ 0 ] );
returnValue = transitionTest
.addClass( "ui-panel-animate ui-panel-position-left ui-panel-display-overlay" )
.animationComplete( checker.transitionHandler, "transition" );
deepEqual( returnValue, transitionTest,
"Returned jQuery object for transition is the one passed in" );
returnValue = animationTest
.addClass( "in" )
.animationComplete( checker.animationHandler );
deepEqual( returnValue, animationTest,
"Returned jQuery object for animation is the one passed in" );
});
module( "Empty jQuery object" );
asyncTest( "Make sure callback is not called on empty jQuery object", function() {
var transitionCallbackExecuted = false,
animationCallbackExecuted = false;
$([]).animationComplete( function() {
transitionCallbackExecuted = true;
}, "transition" );
$([]).animationComplete( function() {
animationCallbackExecuted = true;
});
setTimeout( function() {
deepEqual( transitionCallbackExecuted, false, "Transition callback was not run" );
deepEqual( animationCallbackExecuted, false, "Animation callback was not run" );
start();
}, $.fn.animationComplete.defaultDuration * 1.5 );
});
})( jQuery );

0 comments on commit 1d6b533

Please sign in to comment.