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

refactor($animate): use CSS3 transition/animation events instead of $timeouts to track ongoing animations #3882

Merged
merged 1 commit into from
Sep 6, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 18 additions & 13 deletions src/ngAnimate/animate.js
Original file line number Diff line number Diff line change
Expand Up @@ -549,13 +549,16 @@ angular.module('ngAnimate', ['ng'])
//one day all browsers will have these properties
var w3cAnimationProp = 'animation';
var w3cTransitionProp = 'transition';
var w3cAnimationEvent = 'animationend';
var w3cTransitionEvent = 'transitionend';

//but some still use vendor-prefixed styles
var vendorAnimationProp = $sniffer.vendorPrefix + 'Animation';
var vendorTransitionProp = $sniffer.vendorPrefix + 'Transition';
var vendorAnimationEvent = $sniffer.vendorPrefix.toLowerCase() + 'AnimationEnd';
var vendorTransitionEvent = $sniffer.vendorPrefix.toLowerCase() + 'TransitionEnd';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not just use transitionendEvent variable defined as follows:

var transitionendEvent = window.ontransitionend !== undefined ?
    'transitionend' :
    window.onwebkittransitionend !== undefined ? 'webkitTransitionEnd' : undefined;

similarly with animationend? All the detection would be in one place, it would eliminate further duplication.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@matsko This is a good point. Can we simplify this in future PR?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mhevery Sure, if that's easier for you. :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mhevery By "we" did you mean that sb has plans to do that or did you ask me to create a PR with a change? :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mhevery nvm, I'm on it :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mhevery @matsko Here you are: #3908


var durationKey = 'Duration',
delayKey = 'Delay',
propertyKey = 'Property',
animationIterationCountKey = 'IterationCount',
ELEMENT_NODE = 1;
Expand Down Expand Up @@ -584,17 +587,12 @@ angular.module('ngAnimate', ['ng'])
element.addClass(className);

//we want all the styles defined before and after
var duration = 0;
var transitionTime = 0,
animationTime = 0;
forEach(element, function(element) {
if (element.nodeType == ELEMENT_NODE) {
var elementStyles = $window.getComputedStyle(element) || {};

var transitionDelay = Math.max(parseMaxTime(elementStyles[w3cTransitionProp + delayKey]),
parseMaxTime(elementStyles[vendorTransitionProp + delayKey]));

var animationDelay = Math.max(parseMaxTime(elementStyles[w3cAnimationProp + delayKey]),
parseMaxTime(elementStyles[vendorAnimationProp + delayKey]));

var transitionDuration = Math.max(parseMaxTime(elementStyles[w3cTransitionProp + durationKey]),
parseMaxTime(elementStyles[vendorTransitionProp + durationKey]));

Expand All @@ -607,16 +605,16 @@ angular.module('ngAnimate', ['ng'])
1);
}

duration = Math.max(animationDelay + animationDuration,
transitionDelay + transitionDuration,
duration);
transitionTime = Math.max(transitionDuration, transitionTime);
animationTime = Math.max(animationDuration, animationTime);
}
});

/* there is no point in performing a reflow if the animation
timeout is empty (this would cause a flicker bug normally
in the page */
if(duration > 0) {
var totalTime = Math.max(transitionTime,animationTime);
if(totalTime > 0) {
var node = element[0];

//temporarily disable the transition so that the enter styles
Expand All @@ -635,12 +633,15 @@ angular.module('ngAnimate', ['ng'])
node.style[vendorTransitionProp + propertyKey] = '';
element.addClass(activeClassName);

$timeout(done, duration * 1000, false);
var css3AnimationEvents = [w3cAnimationEvent, vendorAnimationEvent,
w3cTransitionEvent, vendorTransitionEvent].join(' ');
element.on(css3AnimationEvents, onAnimationProgress);

//this will automatically be called by $animate so
//there is no need to attach this internally to the
//timeout done method
return function onEnd(cancelled) {
element.off(css3AnimationEvents, onAnimationProgress);
element.removeClass(className);
element.removeClass(activeClassName);

Expand All @@ -657,6 +658,10 @@ angular.module('ngAnimate', ['ng'])
done();
}

function onAnimationProgress(event) {
event.originalEvent.elapsedTime >= totalTime && done();
}

function parseMaxTime(str) {
var total = 0, values = angular.isString(str) ? str.split(/\s*,\s*/) : [];
forEach(values, function(value) {
Expand Down
Loading