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

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 #5014
Closes #4265
  • Loading branch information
matsko committed Nov 22, 2013
1 parent 76e4db6 commit 062fbed
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 062fbed

Please sign in to comment.