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

Commit db246eb

Browse files
committed
fix(ngAnimate): close follow-up class-based animations when the same class is added/removed when removed/added
This patch ensures that if the same CSS class is added/removed within a follow-up digest then the previous class-based animation is cancelled beforehand. Closes #11717
1 parent 72edd4d commit db246eb

File tree

2 files changed

+50
-0
lines changed

2 files changed

+50
-0
lines changed

src/ngAnimate/animateQueue.js

+9
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,14 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
5858
return currentAnimation.state === RUNNING_STATE && newAnimation.structural;
5959
});
6060

61+
rules.cancel.push(function(element, newAnimation, currentAnimation) {
62+
var nO = newAnimation.options;
63+
var cO = currentAnimation.options;
64+
65+
// if the exact same CSS class is added/removed then it's safe to cancel it
66+
return (nO.addClass && nO.addClass === cO.removeClass) || (nO.removeClass && nO.removeClass === cO.addClass);
67+
});
68+
6169
this.$get = ['$$rAF', '$rootScope', '$rootElement', '$document', '$$HashMap',
6270
'$$animation', '$$AnimateRunner', '$templateRequest', '$$jqLite',
6371
function($$rAF, $rootScope, $rootElement, $document, $$HashMap,
@@ -358,6 +366,7 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
358366

359367
if (!isValidAnimation) {
360368
close();
369+
clearElementAnimationState(element);
361370
return runner;
362371
}
363372

test/ngAnimate/animateSpec.js

+41
Original file line numberDiff line numberDiff line change
@@ -976,6 +976,47 @@ describe("animations", function() {
976976
expect(enterDone).toHaveBeenCalled();
977977
}));
978978

979+
it('should cancel the previously running addClass animation if a follow-up removeClass animation is using the same class value',
980+
inject(function($animate, $rootScope, $$rAF) {
981+
982+
parent.append(element);
983+
var runner = $animate.addClass(element, 'active-class');
984+
$rootScope.$digest();
985+
986+
var doneHandler = jasmine.createSpy('addClass done');
987+
runner.done(doneHandler);
988+
989+
$$rAF.flush();
990+
991+
expect(doneHandler).not.toHaveBeenCalled();
992+
993+
$animate.removeClass(element, 'active-class');
994+
$rootScope.$digest();
995+
996+
expect(doneHandler).toHaveBeenCalled();
997+
}));
998+
999+
it('should cancel the previously running removeClass animation if a follow-up addClass animation is using the same class value',
1000+
inject(function($animate, $rootScope, $$rAF) {
1001+
1002+
element.addClass('active-class');
1003+
parent.append(element);
1004+
var runner = $animate.removeClass(element, 'active-class');
1005+
$rootScope.$digest();
1006+
1007+
var doneHandler = jasmine.createSpy('addClass done');
1008+
runner.done(doneHandler);
1009+
1010+
$$rAF.flush();
1011+
1012+
expect(doneHandler).not.toHaveBeenCalled();
1013+
1014+
$animate.addClass(element, 'active-class');
1015+
$rootScope.$digest();
1016+
1017+
expect(doneHandler).toHaveBeenCalled();
1018+
}));
1019+
9791020
it('should skip the class-based animation entirely if there is an active structural animation',
9801021
inject(function($animate, $rootScope) {
9811022

0 commit comments

Comments
 (0)