diff options
| author | Matias Niemelä | 2014-02-13 14:59:25 -0500 | 
|---|---|---|
| committer | Igor Minar | 2014-02-14 16:28:34 -0800 | 
| commit | f288b8f010468237d238acf51ea3d8108138207a (patch) | |
| tree | e60cde5cfc2c64f4b54fd76c3ad05e77cf7c9806 | |
| parent | b7e4e92014a5fe7a2d8c896703498090d88793ce (diff) | |
| download | angular.js-f288b8f010468237d238acf51ea3d8108138207a.tar.bz2 | |
pref($animate): group all asynchronous requests into one shared buffer
| -rw-r--r-- | src/ngAnimate/animate.js | 40 | ||||
| -rw-r--r-- | test/ngAnimate/animateSpec.js | 39 | 
2 files changed, 59 insertions, 20 deletions
| diff --git a/src/ngAnimate/animate.js b/src/ngAnimate/animate.js index b1ea7d3d..99b42f38 100644 --- a/src/ngAnimate/animate.js +++ b/src/ngAnimate/animate.js @@ -268,6 +268,20 @@ angular.module('ngAnimate', ['ng'])      };    }]) +  .factory('$$asyncQueueBuffer', ['$timeout', function($timeout) { +    var timer, queue = []; +    return function(fn) { +      $timeout.cancel(timer); +      queue.push(fn); +      timer = $timeout(function() { +        for(var i = 0; i < queue.length; i++) { +          queue[i](); +        } +        queue = []; +      }, 0, false); +    }; +  }]) +    .config(['$provide', '$animateProvider', function($provide, $animateProvider) {      var noop = angular.noop;      var forEach = angular.forEach; @@ -291,9 +305,10 @@ angular.module('ngAnimate', ['ng'])        return extractElementNode(elm1) == extractElementNode(elm2);      } -    $provide.decorator('$animate', ['$delegate', '$injector', '$sniffer', '$rootElement', '$timeout', '$rootScope', '$document', -                            function($delegate,   $injector,   $sniffer,   $rootElement,   $timeout,   $rootScope,   $document) { +    $provide.decorator('$animate', ['$delegate', '$injector', '$sniffer', '$rootElement', '$$asyncQueueBuffer', '$rootScope', '$document', +                            function($delegate,   $injector,   $sniffer,   $rootElement,   $$asyncQueueBuffer,    $rootScope,   $document) { +      var globalAnimationCounter = 0;        $rootElement.data(NG_ANIMATE_STATE, rootAnimateState);        // disable animations during bootstrap, but once we bootstrapped, wait again @@ -315,10 +330,6 @@ angular.module('ngAnimate', ['ng'])                  return classNameFilter.test(className);                }; -      function async(fn) { -        return $timeout(fn, 0, false); -      } -        function lookup(name) {          if (name) {            var matches = [], @@ -685,7 +696,6 @@ angular.module('ngAnimate', ['ng'])          if(ngAnimateState.running) {            //if an animation is currently running on the element then lets take the steps            //to cancel that animation and fire any required callbacks -          $timeout.cancel(ngAnimateState.closeAnimationTimeout);            cleanup(element);            cancelAnimations(ngAnimateState.animations); @@ -736,12 +746,15 @@ angular.module('ngAnimate', ['ng'])          //parent animations to find and cancel child animations when needed          element.addClass(NG_ANIMATE_CLASS_NAME); +        var localAnimationCount = globalAnimationCounter++; +          element.data(NG_ANIMATE_STATE, {            running:true,            event:animationEvent,            className:className,            structural:!isClassBased,            animations:animations, +          index:localAnimationCount,            done:onBeforeAnimationsComplete          }); @@ -816,19 +829,19 @@ angular.module('ngAnimate', ['ng'])          }          function fireBeforeCallbackAsync() { -          async(function() { +          $$asyncQueueBuffer(function() {              fireDOMCallback('before');            });          }          function fireAfterCallbackAsync() { -          async(function() { +          $$asyncQueueBuffer(function() {              fireDOMCallback('after');            });          }          function fireDoneCallbackAsync() { -          async(function() { +          $$asyncQueueBuffer(function() {              fireDOMCallback('close');              doneCallback && doneCallback();            }); @@ -855,8 +868,11 @@ angular.module('ngAnimate', ['ng'])                if(isClassBased) {                  cleanup(element);                } else { -                data.closeAnimationTimeout = async(function() { -                  cleanup(element); +                $$asyncQueueBuffer(function() { +                  var data = element.data(NG_ANIMATE_STATE) || {}; +                  if(localAnimationCount == data.index) { +                    cleanup(element); +                  }                  });                  element.data(NG_ANIMATE_STATE, data);                } diff --git a/test/ngAnimate/animateSpec.js b/test/ngAnimate/animateSpec.js index d626d60e..41115e42 100644 --- a/test/ngAnimate/animateSpec.js +++ b/test/ngAnimate/animateSpec.js @@ -2563,8 +2563,9 @@ describe("ngAnimate", function() {      }); -    it("should disable all child animations on structural animations until the post animation timeout has passed", function() { -      var intercepted; +    it("should disable all child animations on structural animations until the post animation" + +       "timeout has passed as well as all structural animations", function() { +      var intercepted, continueAnimation;        module(function($animateProvider) {          $animateProvider.register('.animated', function() {            return { @@ -2578,7 +2579,10 @@ describe("ngAnimate", function() {            function ani(type) {              return function(element, className, done) {                intercepted = type; -              (done || className)(); +              continueAnimation = function() { +                continueAnimation = angular.noop; +                (done || className)(); +              }              }            }          }); @@ -2595,26 +2599,45 @@ describe("ngAnimate", function() {          var child2 = $compile('<div class="child2 animated">...</div>')($rootScope);          var container = $compile('<div class="container">...</div>')($rootScope); -        jqLite($document[0].body).append($rootElement); +        var body = angular.element($document[0].body); +        body.append($rootElement);          $rootElement.append(container);          element.append(child1);          element.append(child2); -        $animate.move(element, null, container); +        $animate.enter(element, container);          $rootScope.$digest(); -        expect(intercepted).toBe('move'); +        expect(intercepted).toBe('enter'); +        continueAnimation();          $animate.addClass(child1, 'test');          expect(child1.hasClass('test')).toBe(true); -        expect(intercepted).toBe('move'); +        expect(element.children().length).toBe(2); + +        expect(intercepted).toBe('enter');          $animate.leave(child1);          $rootScope.$digest(); +        expect(element.children().length).toBe(1); + +        expect(intercepted).toBe('enter'); + +        $animate.move(element, null, container); +        $rootScope.$digest(); +          expect(intercepted).toBe('move'); -        //reflow has passed +        //flush the enter reflow +        $timeout.flush(); + +        $animate.addClass(child2, 'testing'); +        expect(intercepted).toBe('move'); + +        continueAnimation(); + +        //flush the move reflow          $timeout.flush();          $animate.leave(child2); | 
