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; |
