aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/ngAnimate/animate.js80
1 files changed, 42 insertions, 38 deletions
diff --git a/src/ngAnimate/animate.js b/src/ngAnimate/animate.js
index 7f37f143..44b94563 100644
--- a/src/ngAnimate/animate.js
+++ b/src/ngAnimate/animate.js
@@ -542,21 +542,35 @@ angular.module('ngAnimate', ['ng'])
}
}]);
- $animateProvider.register('', ['$window','$sniffer', '$timeout', function($window, $sniffer, $timeout) {
- var noop = angular.noop;
+ $animateProvider.register('', ['$window', '$sniffer', function($window, $sniffer) {
var forEach = angular.forEach;
- //one day all browsers will have these properties
- var w3cAnimationProp = 'animation';
- var w3cTransitionProp = 'transition';
- var w3cAnimationEvent = 'animationend';
- var w3cTransitionEvent = 'transitionend';
+ // Detect proper transitionend/animationend event names.
+ var transitionProp, transitionendEvent, animationProp, animationendEvent;
+
+ // If unprefixed events are not supported but webkit-prefixed are, use the latter.
+ // Otherwise, just use W3C names, browsers not supporting them at all will just ignore them.
+ // Note: Chrome implements `window.onwebkitanimationend` and doesn't implement `window.onanimationend`
+ // but at the same time dispatches the `animationend` event and not `webkitAnimationEnd`.
+ // Register both events in case `window.onanimationend` is not supported because of that,
+ // do the same for `transitionend` as Safari is likely to exhibit similar behavior.
+ // Also, the only modern browser that uses vendor prefixes for transitions/keyframes is webkit
+ // therefore there is no reason to test anymore for other vendor prefixes: http://caniuse.com/#search=transition
+ if (window.ontransitionend === undefined && window.onwebkittransitionend !== undefined) {
+ transitionProp = 'WebkitTransition';
+ transitionendEvent = 'webkitTransitionEnd transitionend';
+ } else {
+ transitionProp = 'transition';
+ transitionendEvent = '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';
+ if (window.onanimationend === undefined && window.onwebkitanimationend !== undefined) {
+ animationProp = 'WebkitAnimation';
+ animationendEvent = 'webkitAnimationEnd animationend';
+ } else {
+ animationProp = 'animation';
+ animationendEvent = 'animationend';
+ }
var durationKey = 'Duration',
propertyKey = 'Property',
@@ -574,8 +588,7 @@ angular.module('ngAnimate', ['ng'])
forEach(element, function(element) {
if (element.nodeType == ELEMENT_NODE) {
var elementStyles = $window.getComputedStyle(element) || {};
- existingDuration = Math.max(parseMaxTime(elementStyles[w3cTransitionProp + durationKey]),
- parseMaxTime(elementStyles[vendorTransitionProp + durationKey]),
+ existingDuration = Math.max(parseMaxTime(elementStyles[transitionProp + durationKey]),
existingDuration);
}
});
@@ -594,22 +607,16 @@ angular.module('ngAnimate', ['ng'])
if (element.nodeType == ELEMENT_NODE) {
var elementStyles = $window.getComputedStyle(element) || {};
- var transitionDelay = Math.max(parseMaxTime(elementStyles[w3cTransitionProp + delayKey]),
- parseMaxTime(elementStyles[vendorTransitionProp + delayKey]));
+ var transitionDelay = parseMaxTime(elementStyles[transitionProp + delayKey]);
- var animationDelay = Math.max(parseMaxTime(elementStyles[w3cAnimationProp + delayKey]),
- parseMaxTime(elementStyles[vendorAnimationProp + delayKey]));
+ var animationDelay = parseMaxTime(elementStyles[animationProp + delayKey]);
- var transitionDuration = Math.max(parseMaxTime(elementStyles[w3cTransitionProp + durationKey]),
- parseMaxTime(elementStyles[vendorTransitionProp + durationKey]));
+ var transitionDuration = parseMaxTime(elementStyles[transitionProp + durationKey]);
- var animationDuration = Math.max(parseMaxTime(elementStyles[w3cAnimationProp + durationKey]),
- parseMaxTime(elementStyles[vendorAnimationProp + durationKey]));
+ var animationDuration = parseMaxTime(elementStyles[animationProp + durationKey]);
if(animationDuration > 0) {
- animationDuration *= Math.max(parseInt(elementStyles[w3cAnimationProp + animationIterationCountKey]) || 0,
- parseInt(elementStyles[vendorAnimationProp + animationIterationCountKey]) || 0,
- 1);
+ animationDuration *= parseInt(elementStyles[animationProp + animationIterationCountKey]) || 1;
}
transitionTime = Math.max(transitionDelay + transitionDuration, transitionTime);
@@ -628,8 +635,7 @@ angular.module('ngAnimate', ['ng'])
//temporarily disable the transition so that the enter styles
//don't animate twice (this is here to avoid a bug in Chrome/FF).
if(transitionTime > 0) {
- node.style[w3cTransitionProp + propertyKey] = 'none';
- node.style[vendorTransitionProp + propertyKey] = 'none';
+ node.style[transitionProp + propertyKey] = 'none';
}
var activeClassName = '';
@@ -637,29 +643,27 @@ angular.module('ngAnimate', ['ng'])
activeClassName += (i > 0 ? ' ' : '') + klass + '-active';
});
- //this triggers a reflow which allows for the transition animation to kick in
+ // This triggers a reflow which allows for the transition animation to kick in.
element.prop('clientWidth');
if(transitionTime > 0) {
- node.style[w3cTransitionProp + propertyKey] = '';
- node.style[vendorTransitionProp + propertyKey] = '';
+ node.style[transitionProp + propertyKey] = '';
}
element.addClass(activeClassName);
- var css3AnimationEvents = [w3cAnimationEvent, vendorAnimationEvent,
- w3cTransitionEvent, vendorTransitionEvent].join(' ');
+ var css3AnimationEvents = animationendEvent + ' ' + transitionendEvent;
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
+ // 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);
- //only when the animation is cancelled is the done()
- //function not called for this animation therefore
- //this must be also called
+ // Only when the animation is cancelled is the done()
+ // function not called for this animation therefore
+ // this must be also called.
if(cancelled) {
done();
}