Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit 062fbed

Browse files
committed
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
1 parent 76e4db6 commit 062fbed

File tree

2 files changed

+54
-5
lines changed

2 files changed

+54
-5
lines changed

src/ngAnimate/animate.js

+21-5
Original file line numberDiff line numberDiff line change
@@ -1001,7 +1001,7 @@ angular.module('ngAnimate', ['ng'])
10011001
if(timings.transitionDuration > 0) {
10021002
element.addClass(NG_ANIMATE_FALLBACK_CLASS_NAME);
10031003
activeClassName += NG_ANIMATE_FALLBACK_ACTIVE_CLASS_NAME + ' ';
1004-
node.style[TRANSITION_PROP + PROPERTY_KEY] = 'none';
1004+
blockTransitions(element);
10051005
}
10061006

10071007
forEach(className.split(' '), function(klass, i) {
@@ -1021,6 +1021,17 @@ angular.module('ngAnimate', ['ng'])
10211021
return true;
10221022
}
10231023

1024+
function blockTransitions(element) {
1025+
element[0].style[TRANSITION_PROP + PROPERTY_KEY] = 'none';
1026+
}
1027+
1028+
function unblockTransitions(element) {
1029+
var node = element[0], prop = TRANSITION_PROP + PROPERTY_KEY;
1030+
if(node.style[prop] && node.style[prop].length > 0) {
1031+
node.style[prop] = '';
1032+
}
1033+
}
1034+
10241035
function animateRun(element, className, activeAnimationComplete) {
10251036
var data = element.data(NG_ANIMATE_CSS_DATA_KEY);
10261037
if(!element.hasClass(className) || !data) {
@@ -1041,8 +1052,6 @@ angular.module('ngAnimate', ['ng'])
10411052

10421053
var applyFallbackStyle, style = '';
10431054
if(timings.transitionDuration > 0) {
1044-
node.style[TRANSITION_PROP + PROPERTY_KEY] = '';
1045-
10461055
var propertyStyle = timings.transitionPropertyStyle;
10471056
if(propertyStyle.indexOf('all') == -1) {
10481057
applyFallbackStyle = true;
@@ -1150,6 +1159,7 @@ angular.module('ngAnimate', ['ng'])
11501159
//happen in the first place
11511160
var cancel = preReflowCancellation;
11521161
afterReflow(function() {
1162+
unblockTransitions(element);
11531163
//once the reflow is complete then we point cancel to
11541164
//the new cancellation function which will remove all of the
11551165
//animation properties from the active animation
@@ -1213,7 +1223,10 @@ angular.module('ngAnimate', ['ng'])
12131223
beforeAddClass : function(element, className, animationCompleted) {
12141224
var cancellationMethod = animateBefore(element, suffixClasses(className, '-add'));
12151225
if(cancellationMethod) {
1216-
afterReflow(animationCompleted);
1226+
afterReflow(function() {
1227+
unblockTransitions(element);
1228+
animationCompleted();
1229+
});
12171230
return cancellationMethod;
12181231
}
12191232
animationCompleted();
@@ -1226,7 +1239,10 @@ angular.module('ngAnimate', ['ng'])
12261239
beforeRemoveClass : function(element, className, animationCompleted) {
12271240
var cancellationMethod = animateBefore(element, suffixClasses(className, '-remove'));
12281241
if(cancellationMethod) {
1229-
afterReflow(animationCompleted);
1242+
afterReflow(function() {
1243+
unblockTransitions(element);
1244+
animationCompleted();
1245+
});
12301246
return cancellationMethod;
12311247
}
12321248
animationCompleted();

test/ngAnimate/animateSpec.js

+33
Original file line numberDiff line numberDiff line change
@@ -2663,4 +2663,37 @@ describe("ngAnimate", function() {
26632663
expect(element.hasClass('base-class')).toBe(true);
26642664
}));
26652665

2666+
it('should block and unblock transitions before the dom operation occurs',
2667+
inject(function($rootScope, $compile, $rootElement, $document, $animate, $sniffer, $timeout) {
2668+
2669+
if (!$sniffer.transitions) return;
2670+
2671+
$animate.enabled(true);
2672+
2673+
ss.addRule('.cross-animation', '-webkit-transition:1s linear all;' +
2674+
'transition:1s linear all;');
2675+
2676+
var capturedProperty = 'none';
2677+
2678+
var element = $compile('<div class="cross-animation"></div>')($rootScope);
2679+
$rootElement.append(element);
2680+
jqLite($document[0].body).append($rootElement);
2681+
2682+
var node = element[0];
2683+
node._setAttribute = node.setAttribute;
2684+
node.setAttribute = function(prop, val) {
2685+
if(prop == 'class' && val.indexOf('trigger-class') >= 0) {
2686+
var propertyKey = ($sniffer.vendorPrefix == 'Webkit' ? '-webkit-' : '') + 'transition-property';
2687+
capturedProperty = element.css(propertyKey);
2688+
}
2689+
node._setAttribute(prop, val);
2690+
};
2691+
2692+
$animate.addClass(element, 'trigger-class');
2693+
2694+
$timeout.flush();
2695+
2696+
expect(capturedProperty).not.toBe('none');
2697+
}));
2698+
26662699
});

0 commit comments

Comments
 (0)