diff options
| -rw-r--r-- | src/ngAnimate/animate.js | 80 |
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(); } |
