From ed53100a0dbc9119d5dfc8b7248845d4f6989df2 Mon Sep 17 00:00:00 2001 From: Matias Niemelä Date: Sat, 11 Jan 2014 23:44:43 -0500 Subject: fix($animate): ensure the final closing timeout respects staggering animations --- src/ngAnimate/animate.js | 22 +++++++++++++--------- test/ngAnimate/animateSpec.js | 44 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 56 insertions(+), 10 deletions(-) diff --git a/src/ngAnimate/animate.js b/src/ngAnimate/animate.js index f3a86f82..22a9dde7 100644 --- a/src/ngAnimate/animate.js +++ b/src/ngAnimate/animate.js @@ -930,8 +930,12 @@ angular.module('ngAnimate', ['ng']) animationElementQueue.push(element); var elementData = element.data(NG_ANIMATE_CSS_DATA_KEY); - closingAnimationTime = Math.max(closingAnimationTime, - (elementData.maxDelay + elementData.maxDuration) * CLOSING_TIME_BUFFER * ONE_SECOND); + + var stagger = elementData.stagger; + var staggerTime = elementData.itemIndex * (Math.max(stagger.animationDelay, stagger.transitionDelay) || 0); + + var animationTime = (elementData.maxDelay + elementData.maxDuration) * CLOSING_TIME_BUFFER; + closingAnimationTime = Math.max(closingAnimationTime, (staggerTime + animationTime) * ONE_SECOND); //by placing a counter we can avoid an accidental //race condition which may close an animation when @@ -1058,9 +1062,9 @@ angular.module('ngAnimate', ['ng']) var cacheKey = getCacheKey(element); var eventCacheKey = cacheKey + ' ' + className; var stagger = {}; - var ii = lookupCache[eventCacheKey] ? ++lookupCache[eventCacheKey].total : 0; + var itemIndex = lookupCache[eventCacheKey] ? ++lookupCache[eventCacheKey].total : 0; - if(ii > 0) { + if(itemIndex > 0) { var staggerClassName = className + '-stagger'; var staggerCacheKey = cacheKey + ' ' + staggerClassName; var applyClasses = !lookupCache[staggerCacheKey]; @@ -1113,7 +1117,7 @@ angular.module('ngAnimate', ['ng']) classes : className + ' ' + activeClassName, timings : timings, stagger : stagger, - ii : ii + itemIndex : itemIndex }); return true; @@ -1158,7 +1162,7 @@ angular.module('ngAnimate', ['ng']) var maxDelayTime = Math.max(timings.transitionDelay, timings.animationDelay) * ONE_SECOND; var startTime = Date.now(); var css3AnimationEvents = ANIMATIONEND_EVENT + ' ' + TRANSITIONEND_EVENT; - var ii = elementData.ii; + var itemIndex = elementData.itemIndex; var style = '', appliedStyles = []; if(timings.transitionDuration > 0) { @@ -1171,17 +1175,17 @@ angular.module('ngAnimate', ['ng']) } } - if(ii > 0) { + if(itemIndex > 0) { if(stagger.transitionDelay > 0 && stagger.transitionDuration === 0) { var delayStyle = timings.transitionDelayStyle; style += CSS_PREFIX + 'transition-delay: ' + - prepareStaggerDelay(delayStyle, stagger.transitionDelay, ii) + '; '; + prepareStaggerDelay(delayStyle, stagger.transitionDelay, itemIndex) + '; '; appliedStyles.push(CSS_PREFIX + 'transition-delay'); } if(stagger.animationDelay > 0 && stagger.animationDuration === 0) { style += CSS_PREFIX + 'animation-delay: ' + - prepareStaggerDelay(timings.animationDelayStyle, stagger.animationDelay, ii) + '; '; + prepareStaggerDelay(timings.animationDelayStyle, stagger.animationDelay, itemIndex) + '; '; appliedStyles.push(CSS_PREFIX + 'animation-delay'); } } diff --git a/test/ngAnimate/animateSpec.js b/test/ngAnimate/animateSpec.js index 2a83f2d5..1bb818af 100644 --- a/test/ngAnimate/animateSpec.js +++ b/test/ngAnimate/animateSpec.js @@ -1155,7 +1155,7 @@ describe("ngAnimate", function() { })); - it("apply a closing timeout to close all pending transitions", + it("should apply a closing timeout to close all pending transitions", inject(function($animate, $rootScope, $compile, $sniffer, $timeout) { if (!$sniffer.transitions) return; @@ -1174,6 +1174,48 @@ describe("ngAnimate", function() { expect(element.hasClass('some-class-add-active')).toBe(false); })); + it("apply a closing timeout with respect to a staggering animation", + inject(function($animate, $rootScope, $compile, $sniffer, $timeout) { + + if (!$sniffer.transitions) return; + + ss.addRule('.entering-element.ng-enter', + '-webkit-transition:5s linear all;' + + 'transition:5s linear all;'); + + ss.addRule('.entering-element.ng-enter-stagger', + '-webkit-transition-delay:0.5s;' + + 'transition-delay:0.5s;'); + + element = $compile(html('
'))($rootScope); + var kids = []; + for(var i = 0; i < 5; i++) { + kids.push(angular.element('
')); + $animate.enter(kids[i], element); + } + $rootScope.$digest(); + + $timeout.flush(10); //reflow + expect(element.children().length).toBe(5); + + for(var i = 0; i < 5; i++) { + expect(kids[i].hasClass('ng-enter-active')).toBe(true); + } + + $timeout.flush(7500); + + for(var i = 0; i < 5; i++) { + expect(kids[i].hasClass('ng-enter-active')).toBe(true); + } + + //(stagger * index) + (duration + delay) * 150% + $timeout.flush(9500); //0.5 * 4 + 5 * 1.5 = 9500; + + for(var i = 0; i < 5; i++) { + expect(kids[i].hasClass('ng-enter-active')).toBe(false); + } + })); + it("should not allow the closing animation to close off a successive animation midway", inject(function($animate, $rootScope, $compile, $sniffer, $timeout) { -- cgit v1.2.3