diff options
| -rw-r--r-- | src/ngAnimate/animate.js | 47 | ||||
| -rw-r--r-- | test/ngAnimate/animateSpec.js | 116 | 
2 files changed, 151 insertions, 12 deletions
| diff --git a/src/ngAnimate/animate.js b/src/ngAnimate/animate.js index ad192a5b..3bb6ff31 100644 --- a/src/ngAnimate/animate.js +++ b/src/ngAnimate/animate.js @@ -789,7 +789,8 @@ angular.module('ngAnimate', ['ng'])          var data = cacheKey ? lookupCache[cacheKey] : null;          if(!data) {            var transitionDuration = 0, transitionDelay = 0, -              animationDuration = 0, animationDelay = 0; +              animationDuration = 0, animationDelay = 0, +              transitionDelayStyle, animationDelayStyle;            //we want all the styles defined before and after            forEach(element, function(element) { @@ -799,9 +800,13 @@ angular.module('ngAnimate', ['ng'])                transitionDuration = Math.max(parseMaxTime(elementStyles[transitionProp + durationKey]), transitionDuration);                if(!onlyCheckTransition) { -                transitionDelay  = Math.max(parseMaxTime(elementStyles[transitionProp + delayKey]), transitionDelay); +                transitionDelayStyle = elementStyles[transitionProp + delayKey]; -                animationDelay   = Math.max(parseMaxTime(elementStyles[animationProp + delayKey]), animationDelay); +                transitionDelay  = Math.max(parseMaxTime(transitionDelayStyle), transitionDelay); + +                animationDelayStyle = elementStyles[animationProp + delayKey]; + +                animationDelay   = Math.max(parseMaxTime(animationDelayStyle), animationDelay);                  var aDuration  = parseMaxTime(elementStyles[animationProp + durationKey]); @@ -815,9 +820,11 @@ angular.module('ngAnimate', ['ng'])            });            data = {              total : 0, +            transitionDelayStyle: transitionDelayStyle,              transitionDelay : transitionDelay, -            animationDelay : animationDelay,              transitionDuration : transitionDuration, +            animationDelayStyle: animationDelayStyle, +            animationDelay : animationDelay,              animationDuration : animationDuration            };            if(cacheKey) { @@ -905,16 +912,25 @@ angular.module('ngAnimate', ['ng'])              if(timings.transitionDuration > 0) {                node.style[transitionProp + propertyKey] = ''; -              if(ii > 0 && stagger.transitionDelay > 0 && stagger.transitionDuration === 0) { -                formerStyle = applyStyle(node, prefix + 'transition-delay: ' + -                  (ii * stagger.transitionDelay + timings.transitionDelay) + 's'); -              }              } -            if(ii > 0 && stagger.animationDelay > 0 && stagger.animationDuration === 0) { -              formerStyle = applyStyle(node, prefix + 'animation-delay: ' + -                (ii * stagger.animationDelay + timings.animationDelay) + 's'); +            if(ii > 0) { +              var staggerStyle = ''; +              if(stagger.transitionDelay > 0 && stagger.transitionDuration === 0) { +                staggerStyle += prefix + 'transition-delay: ' + +                                prepareStaggerDelay(timings.transitionDelayStyle, stagger.transitionDelay, ii) + '; '; +              } + +              if(stagger.animationDelay > 0 && stagger.animationDuration === 0) { +                staggerStyle += prefix + 'animation-delay: ' + +                                prepareStaggerDelay(timings.animationDelayStyle, stagger.animationDelay, ii) + '; '; +              } + +              if(staggerStyle.length > 0) { +                formerStyle = applyStyle(node, staggerStyle); +              }              } +              element.addClass(activeClassName);            }); @@ -948,6 +964,15 @@ angular.module('ngAnimate', ['ng'])            done();          } +        function prepareStaggerDelay(delayStyle, staggerDelay, index) { +          var style = ''; +          angular.forEach(delayStyle.split(','), function(val, i) { +            style += (i > 0 ? ',' : '') + +                     (index * staggerDelay + parseInt(val, 10)) + 's'; +          }); +          return style; +        } +          function onAnimationProgress(event) {            event.stopPropagation();            var ev = event.originalEvent || event; diff --git a/test/ngAnimate/animateSpec.js b/test/ngAnimate/animateSpec.js index ec37d8c3..f3523692 100644 --- a/test/ngAnimate/animateSpec.js +++ b/test/ngAnimate/animateSpec.js @@ -697,7 +697,7 @@ describe("ngAnimate", function() {            ss.addRule('.ani.ng-enter, .ani.ng-leave, .ani-fake.ng-enter, .ani-fake.ng-leave',              '-webkit-animation:1s my_animation;' +  -            'transition:1s my_animation;'); +            'animation:1s my_animation;');            ss.addRule('.ani.ng-enter-stagger, .ani.ng-leave-stagger',              '-webkit-animation-delay:0.1s;' + @@ -747,6 +747,40 @@ describe("ngAnimate", function() {            expect(elements[3].attr('style')).not.toMatch(/animation-delay: 0\.3\d*s/);            expect(elements[4].attr('style')).not.toMatch(/animation-delay: 0\.4\d*s/);          })); + +        it("should stagger items when multiple animation durations/delays are defined", +          inject(function($animate, $rootScope, $compile, $sniffer, $timeout, $document, $rootElement) { + +          if(!$sniffer.transitions) return; + +          $animate.enabled(true); + +          ss.addRule('.ani.ng-enter, .ani.ng-leave', +            '-webkit-animation:my_animation 1s 1s, your_animation 1s 2s;' +  +            'animation:my_animation 1s 1s, your_animation 1s 2s;'); + +          ss.addRule('.ani.ng-enter-stagger, .ani.ng-leave-stagger', +            '-webkit-animation-delay:0.1s;' + +            'animation-delay:0.1s;'); + +          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="ani"></div>')(newScope); +            $animate.enter(element, container); +            elements.push(element); +          }; + +          $rootScope.$digest(); +          $timeout.flush(); + +          expect(elements[0].attr('style')).toBeFalsy(); +          expect(elements[1].attr('style')).toMatch(/animation-delay: 1\.1\d*s,\s*2\.1\d*s/); +          expect(elements[2].attr('style')).toMatch(/animation-delay: 1\.2\d*s,\s*2\.2\d*s/); +          expect(elements[3].attr('style')).toMatch(/animation-delay: 1\.3\d*s,\s*2\.3\d*s/); +        }));        });        describe("Transitions", function() { @@ -950,7 +984,87 @@ describe("ngAnimate", function() {            expect(elements[3].attr('style')).not.toMatch(/transition-delay: 0\.3\d*s/);            expect(elements[4].attr('style')).not.toMatch(/transition-delay: 0\.4\d*s/);          })); + +        it("should stagger items when multiple transition durations/delays are defined", +          inject(function($animate, $rootScope, $compile, $sniffer, $timeout, $document, $rootElement) { + +          if(!$sniffer.transitions) return; + +          $animate.enabled(true); + +          ss.addRule('.ani.ng-enter, .ani.ng-leave', +            '-webkit-transition:1s linear color 2s, 3s linear font-size 4s;' +  +            'transition:1s linear color 2s, 3s linear font-size 4s;'); + +          ss.addRule('.ani.ng-enter-stagger, .ani.ng-leave-stagger', +            '-webkit-transition-delay:0.1s;' + +            'transition-delay:0.1s;'); + +          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="ani"></div>')(newScope); +            $animate.enter(element, container); +            elements.push(element); +          }; + +          $rootScope.$digest(); +          $timeout.flush(); + +          expect(elements[0].attr('style')).toBeFalsy(); +          expect(elements[1].attr('style')).toMatch(/transition-delay: 2\.1\d*s,\s*4\.1\d*s/); +          expect(elements[2].attr('style')).toMatch(/transition-delay: 2\.2\d*s,\s*4\.2\d*s/); +          expect(elements[3].attr('style')).toMatch(/transition-delay: 2\.3\d*s,\s*4\.3\d*s/); +        }));        }); + +      it("should apply staggering to both transitions and keyframe animations when used within the same animation", +        inject(function($animate, $rootScope, $compile, $sniffer, $timeout, $document, $rootElement) { + +        if(!$sniffer.transitions) return; + +        $animate.enabled(true); + +        ss.addRule('.ani.ng-enter, .ani.ng-leave', +          '-webkit-animation:my_animation 1s 1s, your_animation 1s 2s;' +  +          'animation:my_animation 1s 1s, your_animation 1s 2s;' + +          '-webkit-transition:1s linear all 0s;' +  +          'transition:1s linear all 1s;'); + +        ss.addRule('.ani.ng-enter-stagger, .ani.ng-leave-stagger', +          '-webkit-transition-delay:0.1s;' + +          'transition-delay:0.1s;' + +          '-webkit-animation-delay:0.2s;' + +          'animation-delay:0.2s;'); + +        var container = $compile(html('<div></div>'))($rootScope); + +        var elements = []; +        for(var i = 0; i < 3; i++) { +          var newScope = $rootScope.$new(); +          var element = $compile('<div class="ani"></div>')(newScope); +          $animate.enter(element, container); +          elements.push(element); +        }; + +        $rootScope.$digest(); +        $timeout.flush(); + +        expect(elements[0].attr('style')).toBeFalsy(); + +        expect(elements[1].attr('style')).toMatch(/transition-delay:\s+1.1\d*/); +        expect(elements[1].attr('style')).toMatch(/animation-delay: 1\.2\d*s,\s*2\.2\d*s/); + +        expect(elements[2].attr('style')).toMatch(/transition-delay:\s+1.2\d*/); +        expect(elements[2].attr('style')).toMatch(/animation-delay: 1\.4\d*s,\s*2\.4\d*s/); + +        for(var i = 0; i < 3; i++) { +          browserTrigger(elements[i],'transitionend', { timeStamp: Date.now() + 22000, elapsedTime: 22000 }); +          expect(elements[i].attr('style')).toBeFalsy(); +        } +      }));      });      describe('animation evaluation', function () { | 
