aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatias Niemelä2013-11-18 16:20:22 -0500
committerMatias Niemelä2013-11-21 20:48:07 -0500
commit062fbed8fc3f7bc55433f8c6915c27520e6f63c5 (patch)
treec8c376acfdf2629fa18369a747a1ea88d920df71
parent76e4db6f3d15199ac1fbe85f9cfa6079a1c4fa56 (diff)
downloadangular.js-062fbed8fc3f7bc55433f8c6915c27520e6f63c5.tar.bz2
fix($animate): ensure transition animations are unblocked before the dom operation occurs
Transitions are blocked when the base CSS class is added at the start of the animation. This causes an issue if the followup CSS class contains animatable-styles. Now, once the animation active state is triggered (when the animation CSS dom operation occurs) the animation itself will always trigger an animate without a quick jump. Closes #5014 Closes #4265
-rw-r--r--src/ngAnimate/animate.js26
-rw-r--r--test/ngAnimate/animateSpec.js33
2 files changed, 54 insertions, 5 deletions
diff --git a/src/ngAnimate/animate.js b/src/ngAnimate/animate.js
index ab7c5816..1956d54c 100644
--- a/src/ngAnimate/animate.js
+++ b/src/ngAnimate/animate.js
@@ -1001,7 +1001,7 @@ angular.module('ngAnimate', ['ng'])
if(timings.transitionDuration > 0) {
element.addClass(NG_ANIMATE_FALLBACK_CLASS_NAME);
activeClassName += NG_ANIMATE_FALLBACK_ACTIVE_CLASS_NAME + ' ';
- node.style[TRANSITION_PROP + PROPERTY_KEY] = 'none';
+ blockTransitions(element);
}
forEach(className.split(' '), function(klass, i) {
@@ -1021,6 +1021,17 @@ angular.module('ngAnimate', ['ng'])
return true;
}
+ function blockTransitions(element) {
+ element[0].style[TRANSITION_PROP + PROPERTY_KEY] = 'none';
+ }
+
+ function unblockTransitions(element) {
+ var node = element[0], prop = TRANSITION_PROP + PROPERTY_KEY;
+ if(node.style[prop] && node.style[prop].length > 0) {
+ node.style[prop] = '';
+ }
+ }
+
function animateRun(element, className, activeAnimationComplete) {
var data = element.data(NG_ANIMATE_CSS_DATA_KEY);
if(!element.hasClass(className) || !data) {
@@ -1041,8 +1052,6 @@ angular.module('ngAnimate', ['ng'])
var applyFallbackStyle, style = '';
if(timings.transitionDuration > 0) {
- node.style[TRANSITION_PROP + PROPERTY_KEY] = '';
-
var propertyStyle = timings.transitionPropertyStyle;
if(propertyStyle.indexOf('all') == -1) {
applyFallbackStyle = true;
@@ -1150,6 +1159,7 @@ angular.module('ngAnimate', ['ng'])
//happen in the first place
var cancel = preReflowCancellation;
afterReflow(function() {
+ unblockTransitions(element);
//once the reflow is complete then we point cancel to
//the new cancellation function which will remove all of the
//animation properties from the active animation
@@ -1213,7 +1223,10 @@ angular.module('ngAnimate', ['ng'])
beforeAddClass : function(element, className, animationCompleted) {
var cancellationMethod = animateBefore(element, suffixClasses(className, '-add'));
if(cancellationMethod) {
- afterReflow(animationCompleted);
+ afterReflow(function() {
+ unblockTransitions(element);
+ animationCompleted();
+ });
return cancellationMethod;
}
animationCompleted();
@@ -1226,7 +1239,10 @@ angular.module('ngAnimate', ['ng'])
beforeRemoveClass : function(element, className, animationCompleted) {
var cancellationMethod = animateBefore(element, suffixClasses(className, '-remove'));
if(cancellationMethod) {
- afterReflow(animationCompleted);
+ afterReflow(function() {
+ unblockTransitions(element);
+ animationCompleted();
+ });
return cancellationMethod;
}
animationCompleted();
diff --git a/test/ngAnimate/animateSpec.js b/test/ngAnimate/animateSpec.js
index b9b7f9ed..2362576a 100644
--- a/test/ngAnimate/animateSpec.js
+++ b/test/ngAnimate/animateSpec.js
@@ -2663,4 +2663,37 @@ describe("ngAnimate", function() {
expect(element.hasClass('base-class')).toBe(true);
}));
+ it('should block and unblock transitions before the dom operation occurs',
+ inject(function($rootScope, $compile, $rootElement, $document, $animate, $sniffer, $timeout) {
+
+ if (!$sniffer.transitions) return;
+
+ $animate.enabled(true);
+
+ ss.addRule('.cross-animation', '-webkit-transition:1s linear all;' +
+ 'transition:1s linear all;');
+
+ var capturedProperty = 'none';
+
+ var element = $compile('<div class="cross-animation"></div>')($rootScope);
+ $rootElement.append(element);
+ jqLite($document[0].body).append($rootElement);
+
+ var node = element[0];
+ node._setAttribute = node.setAttribute;
+ node.setAttribute = function(prop, val) {
+ if(prop == 'class' && val.indexOf('trigger-class') >= 0) {
+ var propertyKey = ($sniffer.vendorPrefix == 'Webkit' ? '-webkit-' : '') + 'transition-property';
+ capturedProperty = element.css(propertyKey);
+ }
+ node._setAttribute(prop, val);
+ };
+
+ $animate.addClass(element, 'trigger-class');
+
+ $timeout.flush();
+
+ expect(capturedProperty).not.toBe('none');
+ }));
+
});