Skip to content

Commit

Permalink
fix($animate): ensure transition animations are unblocked before the …
Browse files Browse the repository at this point in the history
…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 angular#5014
Closes angular#4265
  • Loading branch information
matsko authored and jamesdaily committed Jan 27, 2014
1 parent 7d8d0a4 commit 9e2cee2
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 5 deletions.
26 changes: 21 additions & 5 deletions src/ngAnimate/animate.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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) {
Expand All @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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();
Expand All @@ -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();
Expand Down
33 changes: 33 additions & 0 deletions test/ngAnimate/animateSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');
}));

});

0 comments on commit 9e2cee2

Please sign in to comment.