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

Closes #5106
This commit is contained in:
Matias Niemelä 2013-11-23 21:44:14 -05:00
parent a090400f09
commit 2efe82309a
2 changed files with 50 additions and 3 deletions

View file

@ -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;

View file

@ -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();
});
});
});