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

Commit f316c31

Browse files
mgolmatsko
authored andcommitted
refactor($ngAnimate): simplify the animation event rewrite
To avoid code duplication, use single variables for keeping properties/events names to use. Also, fix some errors that have happened after the rewrite from moment ago.
1 parent 4033cf2 commit f316c31

File tree

1 file changed

+42
-38
lines changed

1 file changed

+42
-38
lines changed

src/ngAnimate/animate.js

+42-38
Original file line numberDiff line numberDiff line change
@@ -542,21 +542,35 @@ angular.module('ngAnimate', ['ng'])
542542
}
543543
}]);
544544

545-
$animateProvider.register('', ['$window','$sniffer', '$timeout', function($window, $sniffer, $timeout) {
546-
var noop = angular.noop;
545+
$animateProvider.register('', ['$window', '$sniffer', function($window, $sniffer) {
547546
var forEach = angular.forEach;
548547

549-
//one day all browsers will have these properties
550-
var w3cAnimationProp = 'animation';
551-
var w3cTransitionProp = 'transition';
552-
var w3cAnimationEvent = 'animationend';
553-
var w3cTransitionEvent = 'transitionend';
548+
// Detect proper transitionend/animationend event names.
549+
var transitionProp, transitionendEvent, animationProp, animationendEvent;
550+
551+
// If unprefixed events are not supported but webkit-prefixed are, use the latter.
552+
// Otherwise, just use W3C names, browsers not supporting them at all will just ignore them.
553+
// Note: Chrome implements `window.onwebkitanimationend` and doesn't implement `window.onanimationend`
554+
// but at the same time dispatches the `animationend` event and not `webkitAnimationEnd`.
555+
// Register both events in case `window.onanimationend` is not supported because of that,
556+
// do the same for `transitionend` as Safari is likely to exhibit similar behavior.
557+
// Also, the only modern browser that uses vendor prefixes for transitions/keyframes is webkit
558+
// therefore there is no reason to test anymore for other vendor prefixes: http://caniuse.com/#search=transition
559+
if (window.ontransitionend === undefined && window.onwebkittransitionend !== undefined) {
560+
transitionProp = 'WebkitTransition';
561+
transitionendEvent = 'webkitTransitionEnd transitionend';
562+
} else {
563+
transitionProp = 'transition';
564+
transitionendEvent = 'transitionend';
565+
}
554566

555-
//but some still use vendor-prefixed styles
556-
var vendorAnimationProp = $sniffer.vendorPrefix + 'Animation';
557-
var vendorTransitionProp = $sniffer.vendorPrefix + 'Transition';
558-
var vendorAnimationEvent = $sniffer.vendorPrefix.toLowerCase() + 'AnimationEnd';
559-
var vendorTransitionEvent = $sniffer.vendorPrefix.toLowerCase() + 'TransitionEnd';
567+
if (window.onanimationend === undefined && window.onwebkitanimationend !== undefined) {
568+
animationProp = 'WebkitAnimation';
569+
animationendEvent = 'webkitAnimationEnd animationend';
570+
} else {
571+
animationProp = 'animation';
572+
animationendEvent = 'animationend';
573+
}
560574

561575
var durationKey = 'Duration',
562576
propertyKey = 'Property',
@@ -574,8 +588,7 @@ angular.module('ngAnimate', ['ng'])
574588
forEach(element, function(element) {
575589
if (element.nodeType == ELEMENT_NODE) {
576590
var elementStyles = $window.getComputedStyle(element) || {};
577-
existingDuration = Math.max(parseMaxTime(elementStyles[w3cTransitionProp + durationKey]),
578-
parseMaxTime(elementStyles[vendorTransitionProp + durationKey]),
591+
existingDuration = Math.max(parseMaxTime(elementStyles[transitionProp + durationKey]),
579592
existingDuration);
580593
}
581594
});
@@ -594,22 +607,16 @@ angular.module('ngAnimate', ['ng'])
594607
if (element.nodeType == ELEMENT_NODE) {
595608
var elementStyles = $window.getComputedStyle(element) || {};
596609

597-
var transitionDelay = Math.max(parseMaxTime(elementStyles[w3cTransitionProp + delayKey]),
598-
parseMaxTime(elementStyles[vendorTransitionProp + delayKey]));
610+
var transitionDelay = parseMaxTime(elementStyles[transitionProp + delayKey]);
599611

600-
var animationDelay = Math.max(parseMaxTime(elementStyles[w3cAnimationProp + delayKey]),
601-
parseMaxTime(elementStyles[vendorAnimationProp + delayKey]));
612+
var animationDelay = parseMaxTime(elementStyles[animationProp + delayKey]);
602613

603-
var transitionDuration = Math.max(parseMaxTime(elementStyles[w3cTransitionProp + durationKey]),
604-
parseMaxTime(elementStyles[vendorTransitionProp + durationKey]));
614+
var transitionDuration = parseMaxTime(elementStyles[transitionProp + durationKey]);
605615

606-
var animationDuration = Math.max(parseMaxTime(elementStyles[w3cAnimationProp + durationKey]),
607-
parseMaxTime(elementStyles[vendorAnimationProp + durationKey]));
616+
var animationDuration = parseMaxTime(elementStyles[animationProp + durationKey]);
608617

609618
if(animationDuration > 0) {
610-
animationDuration *= Math.max(parseInt(elementStyles[w3cAnimationProp + animationIterationCountKey]) || 0,
611-
parseInt(elementStyles[vendorAnimationProp + animationIterationCountKey]) || 0,
612-
1);
619+
animationDuration *= parseInt(elementStyles[animationProp + animationIterationCountKey]) || 1;
613620
}
614621

615622
transitionTime = Math.max(transitionDelay + transitionDuration, transitionTime);
@@ -628,38 +635,35 @@ angular.module('ngAnimate', ['ng'])
628635
//temporarily disable the transition so that the enter styles
629636
//don't animate twice (this is here to avoid a bug in Chrome/FF).
630637
if(transitionTime > 0) {
631-
node.style[w3cTransitionProp + propertyKey] = 'none';
632-
node.style[vendorTransitionProp + propertyKey] = 'none';
638+
node.style[transitionProp + propertyKey] = 'none';
633639
}
634640

635641
var activeClassName = '';
636642
forEach(className.split(' '), function(klass, i) {
637643
activeClassName += (i > 0 ? ' ' : '') + klass + '-active';
638644
});
639645

640-
//this triggers a reflow which allows for the transition animation to kick in
646+
// This triggers a reflow which allows for the transition animation to kick in.
641647
element.prop('clientWidth');
642648
if(transitionTime > 0) {
643-
node.style[w3cTransitionProp + propertyKey] = '';
644-
node.style[vendorTransitionProp + propertyKey] = '';
649+
node.style[transitionProp + propertyKey] = '';
645650
}
646651
element.addClass(activeClassName);
647652

648-
var css3AnimationEvents = [w3cAnimationEvent, vendorAnimationEvent,
649-
w3cTransitionEvent, vendorTransitionEvent].join(' ');
653+
var css3AnimationEvents = animationendEvent + ' ' + transitionendEvent;
650654
element.on(css3AnimationEvents, onAnimationProgress);
651655

652-
//this will automatically be called by $animate so
653-
//there is no need to attach this internally to the
654-
//timeout done method
656+
// This will automatically be called by $animate so
657+
// there is no need to attach this internally to the
658+
// timeout done method.
655659
return function onEnd(cancelled) {
656660
element.off(css3AnimationEvents, onAnimationProgress);
657661
element.removeClass(className);
658662
element.removeClass(activeClassName);
659663

660-
//only when the animation is cancelled is the done()
661-
//function not called for this animation therefore
662-
//this must be also called
664+
// Only when the animation is cancelled is the done()
665+
// function not called for this animation therefore
666+
// this must be also called.
663667
if(cancelled) {
664668
done();
665669
}

0 commit comments

Comments
 (0)