diff options
| -rw-r--r-- | src/ngAnimate/animate.js | 9 | ||||
| -rw-r--r-- | test/ngAnimate/animateSpec.js | 57 | 
2 files changed, 60 insertions, 6 deletions
| diff --git a/src/ngAnimate/animate.js b/src/ngAnimate/animate.js index 0e5fda98..4b35d5fd 100644 --- a/src/ngAnimate/animate.js +++ b/src/ngAnimate/animate.js @@ -1252,7 +1252,14 @@ angular.module('ngAnimate', ['ng'])          if(transitionDuration > 0) {            blockTransitions(element, className, isCurrentlyAnimating);          } -        if(animationDuration > 0) { + +        //staggering keyframe animations work by adjusting the `animation-delay` CSS property +        //on the given element, however, the delay value can only calculated after the reflow +        //since by that time $animate knows how many elements are being animated. Therefore, +        //until the reflow occurs the element needs to be blocked (where the keyframe animation +        //is set to `none 0s`). This blocking mechanism should only be set for when a stagger +        //animation is detected and when the element item index is greater than 0. +        if(animationDuration > 0 && stagger.animationDelay > 0 && stagger.animationDuration === 0) {            blockKeyframeAnimations(element);          } diff --git a/test/ngAnimate/animateSpec.js b/test/ngAnimate/animateSpec.js index 9179eb2b..eaed757e 100644 --- a/test/ngAnimate/animateSpec.js +++ b/test/ngAnimate/animateSpec.js @@ -841,6 +841,49 @@ describe("ngAnimate", function() {            })); +          it("should block and unblock keyframe animations when a stagger animation kicks in while skipping the first element", +            inject(function($animate, $rootScope, $compile, $sniffer, $timeout, $document, $rootElement) { + +            if(!$sniffer.animations) return; + +            $animate.enabled(true); + +            ss.addRule('.blocked-animation.ng-enter', +              '-webkit-animation:my_animation 1s;' + +              'animation:my_animation 1s;'); + +            ss.addRule('.blocked-animation.ng-enter-stagger', +              '-webkit-animation-delay:0.2s;' + +              'animation-delay:0.2s;'); + +            var container = $compile(html('<div></div>'))($rootScope); + +            var elements = []; +            for(var i = 0; i < 4; i++) { +              var newScope = $rootScope.$new(); +              var element = $compile('<div class="blocked-animation"></div>')(newScope); +              $animate.enter(element, container); +              elements.push(element); +            }; + +            $rootScope.$digest(); + +            expect(elements[0].attr('style')).toBeUndefined(); +            expect(elements[1].attr('style')).toMatch(/animation:.*?none/); +            expect(elements[2].attr('style')).toMatch(/animation:.*?none/); +            expect(elements[3].attr('style')).toMatch(/animation:.*?none/); + +            $animate.triggerReflow(); + +            expect(elements[0].attr('style')).toBeUndefined(); +            expect(elements[1].attr('style')).not.toMatch(/animation:.*?none/); +            expect(elements[1].attr('style')).toMatch(/animation-delay: 0.2\d*s/); +            expect(elements[2].attr('style')).not.toMatch(/animation:.*?none/); +            expect(elements[2].attr('style')).toMatch(/animation-delay: 0.4\d*s/); +            expect(elements[3].attr('style')).not.toMatch(/animation:.*?none/); +            expect(elements[3].attr('style')).toMatch(/animation-delay: 0.6\d*s/); +          })); +            it("should stagger items when multiple animation durations/delays are defined",              inject(function($animate, $rootScope, $compile, $sniffer, $timeout, $document, $rootElement) { @@ -3013,7 +3056,7 @@ describe("ngAnimate", function() {      })); -    it('should block and unblock keyframe animations around the reflow operation', +    it('should not block keyframe animations around the reflow operation',        inject(function($rootScope, $compile, $rootElement, $document, $animate, $sniffer, $timeout) {        if (!$sniffer.animations) return; @@ -3032,15 +3075,19 @@ describe("ngAnimate", function() {        $animate.addClass(element, 'trigger-class'); -      expect(node.style[animationKey]).toContain('none'); +      expect(node.style[animationKey]).not.toContain('none');        $animate.triggerReflow();        expect(node.style[animationKey]).not.toContain('none'); + +      browserTrigger(element, 'animationend', { timeStamp: Date.now() + 1000, elapsedTime: 1 }); + +      expect(node.style[animationKey]).not.toContain('none');      })); -    it('should block and unblock keyframe animations before the followup JS animation occurs', function() { +    it('should not block keyframe animations at anytime before a followup JS animation occurs', function() {        module(function($animateProvider) {          $animateProvider.register('.special', function($sniffer, $window) {            var prop = $sniffer.vendorPrefix == 'Webkit' ? 'WebkitAnimation' : 'animation'; @@ -3076,8 +3123,8 @@ describe("ngAnimate", function() {          var prop = $sniffer.vendorPrefix == 'Webkit' ? 'WebkitAnimation' : 'animation'; -        expect(element[0].style[prop]).toContain('none'); -        expect($window.getComputedStyle(element[0])[prop + 'Duration']).toBe('0s'); +        expect(element[0].style[prop]).not.toContain('none'); +        expect($window.getComputedStyle(element[0])[prop + 'Duration']).toBe('1s');          $animate.triggerReflow();        }); | 
