Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

fix($animate): ensure blocked keyframe animations are unblocked before the DOM operation #5107

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions src/ngAnimate/animate.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -1232,6 +1234,7 @@ angular.module('ngAnimate', ['ng'])
if(cancellationMethod) {
afterReflow(function() {
unblockTransitions(element);
unblockKeyframeAnimations(element);
animationCompleted();
});
return cancellationMethod;
Expand All @@ -1248,6 +1251,7 @@ angular.module('ngAnimate', ['ng'])
if(cancellationMethod) {
afterReflow(function() {
unblockTransitions(element);
unblockKeyframeAnimations(element);
animationCompleted();
});
return cancellationMethod;
Expand Down
43 changes: 43 additions & 0 deletions test/ngAnimate/animateSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -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('<div class="special"></div>')($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();
});
});
});