diff options
| author | Matias Niemelä | 2013-11-14 15:36:07 -0500 | 
|---|---|---|
| committer | Matias Niemelä | 2013-11-20 17:08:03 -0500 | 
| commit | 7067a8fb0b18d5b5489006e1960cee721a88b4d2 (patch) | |
| tree | f0a3a6d141bfec6a0c3bc3081f861ba3457ca9aa /src | |
| parent | c47abd0dd7490576f4b84ee51ebaca385c1036da (diff) | |
| download | angular.js-7067a8fb0b18d5b5489006e1960cee721a88b4d2.tar.bz2 | |
fix($animate): ensure the DOM operation isn't run twice
Depending on the animations placed on ngClass, the DOM operation may
run twice causing a race condition between addClass and removeClass.
Depending on what classes are removed and added via $compile this may
cause all CSS classes to be removed accidentally from the element
being animated.
Closes #4949
Diffstat (limited to 'src')
| -rw-r--r-- | src/ngAnimate/animate.js | 18 | 
1 files changed, 14 insertions, 4 deletions
| diff --git a/src/ngAnimate/animate.js b/src/ngAnimate/animate.js index 02706c2b..3b94a651 100644 --- a/src/ngAnimate/animate.js +++ b/src/ngAnimate/animate.js @@ -564,7 +564,7 @@ angular.module('ngAnimate', ['ng'])          //the animation if any matching animations are not found at all.          //NOTE: IE8 + IE9 should close properly (run closeAnimation()) in case a NO animation is not found.          if (animationsDisabled(element, parentElement) || matches.length === 0) { -          domOperation(); +          fireDOMOperation();            closeAnimation();            return;          } @@ -597,7 +597,7 @@ angular.module('ngAnimate', ['ng'])          //this would mean that an animation was not allowed so let the existing          //animation do it's thing and close this one early          if(animations.length === 0) { -          domOperation(); +          fireDOMOperation();            fireDoneCallbackAsync();            return;          } @@ -617,7 +617,7 @@ angular.module('ngAnimate', ['ng'])          //is so that the CSS classes present on the element can be properly examined.          if((animationEvent == 'addClass'    && element.hasClass(className)) ||             (animationEvent == 'removeClass' && !element.hasClass(className))) { -          domOperation(); +          fireDOMOperation();            fireDoneCallbackAsync();            return;          } @@ -628,6 +628,7 @@ angular.module('ngAnimate', ['ng'])          element.data(NG_ANIMATE_STATE, {            running:true, +          className:className,            structural:!isClassBased,            animations:animations,            done:onBeforeAnimationsComplete @@ -638,7 +639,7 @@ angular.module('ngAnimate', ['ng'])          invokeRegisteredAnimationFns(animations, 'before', onBeforeAnimationsComplete);          function onBeforeAnimationsComplete(cancelled) { -          domOperation(); +          fireDOMOperation();            if(cancelled === true) {              closeAnimation();              return; @@ -696,6 +697,15 @@ angular.module('ngAnimate', ['ng'])            doneCallback && $timeout(doneCallback, 0, false);          } +        //it is less complicated to use a flag than managing and cancelling +        //timeouts containing multiple callbacks. +        function fireDOMOperation() { +          if(!fireDOMOperation.hasBeenRun) { +            fireDOMOperation.hasBeenRun = true; +            domOperation(); +          } +        } +          function closeAnimation() {            if(!closeAnimation.hasBeenRun) {              closeAnimation.hasBeenRun = true; | 
