Skip to content

Commit

Permalink
animationComplete: Fix context for timeout/no support
Browse files Browse the repository at this point in the history
  • Loading branch information
Gabriel Schulhof authored and kakul committed Apr 14, 2015
1 parent d79a044 commit 045bd60
Show file tree
Hide file tree
Showing 2 changed files with 163 additions and 11 deletions.
27 changes: 19 additions & 8 deletions js/animationComplete.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
});
Expand Down Expand Up @@ -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" ) ) {
Expand All @@ -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;
}

Expand All @@ -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;
}
};

Expand Down
147 changes: 144 additions & 3 deletions tests/integration/animation-complete/animationComplete.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@
transitionComplete = true;
}, "transition" );

$( "animation-test" ).addClass( "in" ).animationComplete( function() {
$( "#animation-test" ).addClass( "in" ).animationComplete( function() {
animationComplete = true;
});

Expand Down Expand Up @@ -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 );
Expand Down Expand Up @@ -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 045bd60

Please sign in to comment.