From b9c9b94b579c306fced379cc59731bf354eb6e53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matias=20Niemel=C3=A4?= Date: Fri, 29 Aug 2014 14:23:25 -0400 Subject: [PATCH] fix($animate): wait two until two digests are over until enabling animations Even when no remote templates are to be downloaded, wait until the end of the post digest queue before enabling animations since all $animate-triggered animation events perform a post digest before running animations. Closes #8844 --- src/ngAnimate/animate.js | 39 +++++++++++++++----------------- test/ng/directive/ngClassSpec.js | 5 +++- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/ngAnimate/animate.js b/src/ngAnimate/animate.js index d8c65712ca79..cccb5d875ef8 100644 --- a/src/ngAnimate/animate.js +++ b/src/ngAnimate/animate.js @@ -411,34 +411,31 @@ angular.module('ngAnimate', ['ng']) $rootElement.data(NG_ANIMATE_STATE, rootAnimateState); - // disable animations during bootstrap, but once we bootstrapped, wait again - // for another digest until enabling animations. Enter, leave and move require - // a follow-up digest so having a watcher here is enough to let both digests pass. - // However, when any directive or view templates are downloaded then we need to - // handle postpone enabling animations until they are fully completed and then... - var watchFn = $rootScope.$watch( + // Wait until all directive and route-related templates are downloaded and + // compiled. The $templateRequest.totalPendingRequests variable keeps track of + // all of the remote templates being currently downloaded. If there are no + // templates currently downloading then the watcher will still fire anyway. + var deregisterWatch = $rootScope.$watch( function() { return $templateRequest.totalPendingRequests; }, function(val, oldVal) { - if (oldVal === 0) { - if (val === 0) { - $rootScope.$$postDigest(onApplicationReady); - } - } else if(val === 0) { - // ...when the template has been downloaded we digest twice again until the - // animations are set to enabled (since enter, leave and move require a - // follow-up). + if (val !== 0) return; + deregisterWatch(); + + // Now that all templates have been downloaded, $animate will wait until + // the post digest queue is empty before enabling animations. By having two + // calls to $postDigest calls we can ensure that the flag is enabled at the + // very end of the post digest queue. Since all of the animations in $animate + // use $postDigest, it's important that the code below executes at the end. + // This basically means that the page is fully downloaded and compiled before + // any animations are triggered. + $rootScope.$$postDigest(function() { $rootScope.$$postDigest(function() { - $rootScope.$$postDigest(onApplicationReady); + rootAnimateState.running = false; }); - } + }); } ); - function onApplicationReady() { - rootAnimateState.running = false; - watchFn(); - } - var globalAnimationCounter = 0; var classNameFilter = $animateProvider.classNameFilter(); var isAnimatableClassName = !classNameFilter diff --git a/test/ng/directive/ngClassSpec.js b/test/ng/directive/ngClassSpec.js index b2c2e70016f1..ab97afb5b42d 100644 --- a/test/ng/directive/ngClassSpec.js +++ b/test/ng/directive/ngClassSpec.js @@ -434,7 +434,10 @@ describe('ngClass animations', function() { }); inject(function($compile, $rootScope, $browser, $rootElement, $animate, $timeout, $document) { - // Animations are enabled right away since there are no remote HTTP template requests + // Animations need to digest twice in order to be enabled regardless if there are no template HTTP requests. + $rootScope.$digest(); + digestQueue.shift()(); + $rootScope.$digest(); digestQueue.shift()();