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

Commit ed53100

Browse files
committed
fix($animate): ensure the final closing timeout respects staggering animations
1 parent 6df598d commit ed53100

File tree

2 files changed

+56
-10
lines changed

2 files changed

+56
-10
lines changed

src/ngAnimate/animate.js

+13-9
Original file line numberDiff line numberDiff line change
@@ -930,8 +930,12 @@ angular.module('ngAnimate', ['ng'])
930930
animationElementQueue.push(element);
931931

932932
var elementData = element.data(NG_ANIMATE_CSS_DATA_KEY);
933-
closingAnimationTime = Math.max(closingAnimationTime,
934-
(elementData.maxDelay + elementData.maxDuration) * CLOSING_TIME_BUFFER * ONE_SECOND);
933+
934+
var stagger = elementData.stagger;
935+
var staggerTime = elementData.itemIndex * (Math.max(stagger.animationDelay, stagger.transitionDelay) || 0);
936+
937+
var animationTime = (elementData.maxDelay + elementData.maxDuration) * CLOSING_TIME_BUFFER;
938+
closingAnimationTime = Math.max(closingAnimationTime, (staggerTime + animationTime) * ONE_SECOND);
935939

936940
//by placing a counter we can avoid an accidental
937941
//race condition which may close an animation when
@@ -1058,9 +1062,9 @@ angular.module('ngAnimate', ['ng'])
10581062
var cacheKey = getCacheKey(element);
10591063
var eventCacheKey = cacheKey + ' ' + className;
10601064
var stagger = {};
1061-
var ii = lookupCache[eventCacheKey] ? ++lookupCache[eventCacheKey].total : 0;
1065+
var itemIndex = lookupCache[eventCacheKey] ? ++lookupCache[eventCacheKey].total : 0;
10621066

1063-
if(ii > 0) {
1067+
if(itemIndex > 0) {
10641068
var staggerClassName = className + '-stagger';
10651069
var staggerCacheKey = cacheKey + ' ' + staggerClassName;
10661070
var applyClasses = !lookupCache[staggerCacheKey];
@@ -1113,7 +1117,7 @@ angular.module('ngAnimate', ['ng'])
11131117
classes : className + ' ' + activeClassName,
11141118
timings : timings,
11151119
stagger : stagger,
1116-
ii : ii
1120+
itemIndex : itemIndex
11171121
});
11181122

11191123
return true;
@@ -1158,7 +1162,7 @@ angular.module('ngAnimate', ['ng'])
11581162
var maxDelayTime = Math.max(timings.transitionDelay, timings.animationDelay) * ONE_SECOND;
11591163
var startTime = Date.now();
11601164
var css3AnimationEvents = ANIMATIONEND_EVENT + ' ' + TRANSITIONEND_EVENT;
1161-
var ii = elementData.ii;
1165+
var itemIndex = elementData.itemIndex;
11621166

11631167
var style = '', appliedStyles = [];
11641168
if(timings.transitionDuration > 0) {
@@ -1171,17 +1175,17 @@ angular.module('ngAnimate', ['ng'])
11711175
}
11721176
}
11731177

1174-
if(ii > 0) {
1178+
if(itemIndex > 0) {
11751179
if(stagger.transitionDelay > 0 && stagger.transitionDuration === 0) {
11761180
var delayStyle = timings.transitionDelayStyle;
11771181
style += CSS_PREFIX + 'transition-delay: ' +
1178-
prepareStaggerDelay(delayStyle, stagger.transitionDelay, ii) + '; ';
1182+
prepareStaggerDelay(delayStyle, stagger.transitionDelay, itemIndex) + '; ';
11791183
appliedStyles.push(CSS_PREFIX + 'transition-delay');
11801184
}
11811185

11821186
if(stagger.animationDelay > 0 && stagger.animationDuration === 0) {
11831187
style += CSS_PREFIX + 'animation-delay: ' +
1184-
prepareStaggerDelay(timings.animationDelayStyle, stagger.animationDelay, ii) + '; ';
1188+
prepareStaggerDelay(timings.animationDelayStyle, stagger.animationDelay, itemIndex) + '; ';
11851189
appliedStyles.push(CSS_PREFIX + 'animation-delay');
11861190
}
11871191
}

test/ngAnimate/animateSpec.js

+43-1
Original file line numberDiff line numberDiff line change
@@ -1155,7 +1155,7 @@ describe("ngAnimate", function() {
11551155
}));
11561156

11571157

1158-
it("apply a closing timeout to close all pending transitions",
1158+
it("should apply a closing timeout to close all pending transitions",
11591159
inject(function($animate, $rootScope, $compile, $sniffer, $timeout) {
11601160

11611161
if (!$sniffer.transitions) return;
@@ -1174,6 +1174,48 @@ describe("ngAnimate", function() {
11741174
expect(element.hasClass('some-class-add-active')).toBe(false);
11751175
}));
11761176

1177+
it("apply a closing timeout with respect to a staggering animation",
1178+
inject(function($animate, $rootScope, $compile, $sniffer, $timeout) {
1179+
1180+
if (!$sniffer.transitions) return;
1181+
1182+
ss.addRule('.entering-element.ng-enter',
1183+
'-webkit-transition:5s linear all;' +
1184+
'transition:5s linear all;');
1185+
1186+
ss.addRule('.entering-element.ng-enter-stagger',
1187+
'-webkit-transition-delay:0.5s;' +
1188+
'transition-delay:0.5s;');
1189+
1190+
element = $compile(html('<div></div>'))($rootScope);
1191+
var kids = [];
1192+
for(var i = 0; i < 5; i++) {
1193+
kids.push(angular.element('<div class="entering-element"></div>'));
1194+
$animate.enter(kids[i], element);
1195+
}
1196+
$rootScope.$digest();
1197+
1198+
$timeout.flush(10); //reflow
1199+
expect(element.children().length).toBe(5);
1200+
1201+
for(var i = 0; i < 5; i++) {
1202+
expect(kids[i].hasClass('ng-enter-active')).toBe(true);
1203+
}
1204+
1205+
$timeout.flush(7500);
1206+
1207+
for(var i = 0; i < 5; i++) {
1208+
expect(kids[i].hasClass('ng-enter-active')).toBe(true);
1209+
}
1210+
1211+
//(stagger * index) + (duration + delay) * 150%
1212+
$timeout.flush(9500); //0.5 * 4 + 5 * 1.5 = 9500;
1213+
1214+
for(var i = 0; i < 5; i++) {
1215+
expect(kids[i].hasClass('ng-enter-active')).toBe(false);
1216+
}
1217+
}));
1218+
11771219

11781220
it("should not allow the closing animation to close off a successive animation midway",
11791221
inject(function($animate, $rootScope, $compile, $sniffer, $timeout) {

0 commit comments

Comments
 (0)