From ef1abfc92f3ed9bc6e97d2426c302b4c45c5d067 Mon Sep 17 00:00:00 2001 From: Gabriel Schulhof Date: Fri, 21 Mar 2014 15:25:25 +0200 Subject: [PATCH] animationComplete: Remove only the handler attached by us (cherry picked from commit 8a7451b105fc291727b7979f56117d5d0f435652) Closes gh-7267 Fixes gh-7265 --- js/jquery.mobile.animationComplete.js | 15 +++-- .../animation-complete/animationComplete.js | 65 ++++++++++++++++--- 2 files changed, 65 insertions(+), 15 deletions(-) diff --git a/js/jquery.mobile.animationComplete.js b/js/jquery.mobile.animationComplete.js index ef68db363ea..9e98563801c 100644 --- a/js/jquery.mobile.animationComplete.js +++ b/js/jquery.mobile.animationComplete.js @@ -49,6 +49,12 @@ define( [ $.fn.animationComplete = function( callback, type, fallbackTime ) { var timer, duration, that = this, + eventBinding = function() { + + // Clear the timer so we don't call callback twice + clearTimeout( timer ); + callback.apply( this, arguments ); + }, animationType = ( !type || type === "animation" ) ? "animation" : "transition"; // Make sure selected type is supported by browser @@ -76,17 +82,12 @@ define( [ // Sets up the fallback if event never comes timer = setTimeout( function() { - $( that ).off( props[ animationType ].event ); + $( that ).off( props[ animationType ].event, eventBinding ); callback.apply( that ); }, duration ); // Bind the event - return $( this ).one( props[ animationType ].event, function() { - - // Clear the timer so we dont call callback twice - clearTimeout( timer ); - callback.call( this, arguments ); - }); + return $( this ).one( props[ animationType ].event, eventBinding ); } else { // CSS animation / transitions not supported diff --git a/tests/integration/animation-complete/animationComplete.js b/tests/integration/animation-complete/animationComplete.js index ee5c5122274..90130a245cd 100644 --- a/tests/integration/animation-complete/animationComplete.js +++ b/tests/integration/animation-complete/animationComplete.js @@ -2,7 +2,50 @@ * mobile flipswitch unit tests */ (function($){ - var oldTransitions, oldAnimations; + var oldTransitions, oldAnimations, + countEvents = function( element, eventName ) { + var count = 0, + events = $._data( element, "events" ); + + if ( events && events[ eventName ] ) { + count = events[ eventName ].length; + } + + return count; + }, + events = ( function() { + var nameIndex, match, event, + names = [ + "animation", "transition", + "mozAnimation", "mozTransition", + "oAnimation", "oTransition", + "webkitAnimation", "webkitTransition" + ], + element = document.createElement( "a" ), + events = { + animation: { name: "animationend" }, + transition: { name: "transitionend" } + }; + + for( nameIndex in names ) { + if ( element.style[ names[ nameIndex ] ] !== undefined ) { + match = names[ nameIndex ].match( /(.*)(animation|transition)$/i ); + event = match[ 2 ].toLowerCase(); + + // Unprefixed is the best, so do not overwrite if we've already found an + // unprefixed version + if ( events[ event ].prefix !== "" ) { + events[ event ] = { + name: match[ 1 ] + match[ 2 ] + ( match[ 1 ] ? "End" : "end" ), + prefix: match[ 1 ] + }; + } + } + } + + return events; + })(); + module( "Callbacks: Event", { teardown: function() { $( "#transition-test" ) @@ -73,7 +116,7 @@ $( "#animation-test" ).removeClass( "in" ); } }); - asyncTest( "call back executes immeditly when animations not supported on device", function() { + asyncTest( "callback executes immediately when animations unsupported on device", function() { expect( 2 ); var transitionComplete = false, animationComplete = false; @@ -140,7 +183,7 @@ $( "#animation-test" ).removeClass( "in" ); } }); - asyncTest( "Make sure no bidnings when no cssanimation support", function() { + asyncTest( "Make sure no bindings when no cssanimation support", function() { expect( 2 ); var transitionComplete = false, animationComplete = false; @@ -167,7 +210,7 @@ $( "#animation-test" ).removeClass( "in" ); } }); - asyncTest( "Make sure no bidnings remain after event", function() { + asyncTest( "Make sure no bindings remain after event", function() { expect( 2 ); var transitionComplete = false, animationComplete = false; @@ -190,13 +233,19 @@ }, 800 ); }); module( "Event Removal: fallback", { + setup: function() { + $( "#transition-test" ).on( events.transition.name, $.noop ); + $( "#animation-test" ).on( events.animation.name, $.noop ); + }, teardown: function() { $( "#transition-test" ) .removeClass( "ui-panel-animate ui-panel-position-left ui-panel-display-overlay" ); $( "#animation-test" ).removeClass( "in" ); + $( "#transition-test" ).off( events.transition.name, $.noop ); + $( "#animation-test" ).off( events.animation.name, $.noop ); } }); - asyncTest( "Make sure no bidnings remain after fallback", function() { + asyncTest( "Make sure no bindings remain after fallback", function() { expect( 2 ); var transitionComplete = false, animationComplete = false; @@ -210,11 +259,11 @@ }); window.setTimeout( function(){ - ok( $._data( $("#animation-test")[0], "events" ) === undefined, + deepEqual( countEvents( $("#animation-test")[0], events.animation.name ), 1, "no animation bindings remain" ); - ok( $._data( $("#transition-test")[0], "events" ) === undefined, + deepEqual( countEvents( $("#transition-test")[0], events.transition.name ), 1, "no transition bindings remain" ); start(); }, 1200 ); }); -})( jQuery ); \ No newline at end of file +})( jQuery );