From 2efe82309ac8ff4f67df8b6e40a539ea31e15804 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matias=20Niemel=C3=A4?= Date: Sat, 23 Nov 2013 21:44:14 -0500 Subject: [PATCH] fix($animate): ensure blocked keyframe animations are unblocked before the DOM operation Closes #5106 --- src/ngAnimate/animate.js | 10 +++++--- test/ngAnimate/animateSpec.js | 43 +++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/src/ngAnimate/animate.js b/src/ngAnimate/animate.js index 26d48012218c..fde8a7fa99d6 100644 --- a/src/ngAnimate/animate.js +++ b/src/ngAnimate/animate.js @@ -1032,7 +1032,10 @@ angular.module('ngAnimate', ['ng']) } function unblockKeyframeAnimations(element) { - element[0].style[ANIMATION_PROP] = ''; + var node = element[0], prop = ANIMATION_PROP; + if(node.style[prop] && node.style[prop].length > 0) { + element[0].style[prop] = ''; + } } function animateRun(element, className, activeAnimationComplete) { @@ -1063,8 +1066,6 @@ angular.module('ngAnimate', ['ng']) appliedStyles.push(CSS_PREFIX + 'transition-property'); appliedStyles.push(CSS_PREFIX + 'transition-duration'); } - } else { - unblockKeyframeAnimations(element); } if(ii > 0) { @@ -1167,6 +1168,7 @@ angular.module('ngAnimate', ['ng']) var cancel = preReflowCancellation; afterReflow(function() { unblockTransitions(element); + unblockKeyframeAnimations(element); //once the reflow is complete then we point cancel to //the new cancellation function which will remove all of the //animation properties from the active animation @@ -1232,6 +1234,7 @@ angular.module('ngAnimate', ['ng']) if(cancellationMethod) { afterReflow(function() { unblockTransitions(element); + unblockKeyframeAnimations(element); animationCompleted(); }); return cancellationMethod; @@ -1248,6 +1251,7 @@ angular.module('ngAnimate', ['ng']) if(cancellationMethod) { afterReflow(function() { unblockTransitions(element); + unblockKeyframeAnimations(element); animationCompleted(); }); return cancellationMethod; diff --git a/test/ngAnimate/animateSpec.js b/test/ngAnimate/animateSpec.js index c585e72b822f..9f3245628824 100644 --- a/test/ngAnimate/animateSpec.js +++ b/test/ngAnimate/animateSpec.js @@ -2771,4 +2771,47 @@ describe("ngAnimate", function() { expect(node.style[animationKey]).not.toContain('none'); })); + + it('should block and unblock keyframe animations before the followup JS animation occurs', function() { + module(function($animateProvider) { + $animateProvider.register('.special', function($sniffer, $window) { + var prop = $sniffer.vendorPrefix == 'Webkit' ? 'WebkitAnimation' : 'animation'; + return { + beforeAddClass : function(element, className, done) { + expect(element[0].style[prop]).not.toContain('none'); + expect($window.getComputedStyle(element[0])[prop + 'Duration']).toBe('1s'); + done(); + }, + addClass : function(element, className, done) { + expect(element[0].style[prop]).not.toContain('none'); + expect($window.getComputedStyle(element[0])[prop + 'Duration']).toBe('1s'); + done(); + } + } + }); + }); + inject(function($rootScope, $compile, $rootElement, $document, $animate, $sniffer, $timeout, $window) { + if (!$sniffer.animations) return; + + $animate.enabled(true); + + ss.addRule('.special', '-webkit-animation:1s special_animation;' + + 'animation:1s special_animation;'); + + var capturedProperty = 'none'; + + var element = $compile('
')($rootScope); + $rootElement.append(element); + jqLite($document[0].body).append($rootElement); + + $animate.addClass(element, 'some-klass'); + + var prop = $sniffer.vendorPrefix == 'Webkit' ? 'WebkitAnimation' : 'animation'; + + expect(element[0].style[prop]).toContain('none'); + expect($window.getComputedStyle(element[0])[prop + 'Duration']).toBe('0s'); + + $timeout.flush(); + }); + }); });