@@ -542,21 +542,35 @@ angular.module('ngAnimate', ['ng'])
542
542
}
543
543
} ] ) ;
544
544
545
- $animateProvider . register ( '' , [ '$window' , '$sniffer' , '$timeout' , function ( $window , $sniffer , $timeout ) {
546
- var noop = angular . noop ;
545
+ $animateProvider . register ( '' , [ '$window' , '$sniffer' , function ( $window , $sniffer ) {
547
546
var forEach = angular . forEach ;
548
547
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
+ }
554
566
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
+ }
560
574
561
575
var durationKey = 'Duration' ,
562
576
propertyKey = 'Property' ,
@@ -574,8 +588,7 @@ angular.module('ngAnimate', ['ng'])
574
588
forEach ( element , function ( element ) {
575
589
if ( element . nodeType == ELEMENT_NODE ) {
576
590
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 ] ) ,
579
592
existingDuration ) ;
580
593
}
581
594
} ) ;
@@ -594,22 +607,16 @@ angular.module('ngAnimate', ['ng'])
594
607
if ( element . nodeType == ELEMENT_NODE ) {
595
608
var elementStyles = $window . getComputedStyle ( element ) || { } ;
596
609
597
- var transitionDelay = Math . max ( parseMaxTime ( elementStyles [ w3cTransitionProp + delayKey ] ) ,
598
- parseMaxTime ( elementStyles [ vendorTransitionProp + delayKey ] ) ) ;
610
+ var transitionDelay = parseMaxTime ( elementStyles [ transitionProp + delayKey ] ) ;
599
611
600
- var animationDelay = Math . max ( parseMaxTime ( elementStyles [ w3cAnimationProp + delayKey ] ) ,
601
- parseMaxTime ( elementStyles [ vendorAnimationProp + delayKey ] ) ) ;
612
+ var animationDelay = parseMaxTime ( elementStyles [ animationProp + delayKey ] ) ;
602
613
603
- var transitionDuration = Math . max ( parseMaxTime ( elementStyles [ w3cTransitionProp + durationKey ] ) ,
604
- parseMaxTime ( elementStyles [ vendorTransitionProp + durationKey ] ) ) ;
614
+ var transitionDuration = parseMaxTime ( elementStyles [ transitionProp + durationKey ] ) ;
605
615
606
- var animationDuration = Math . max ( parseMaxTime ( elementStyles [ w3cAnimationProp + durationKey ] ) ,
607
- parseMaxTime ( elementStyles [ vendorAnimationProp + durationKey ] ) ) ;
616
+ var animationDuration = parseMaxTime ( elementStyles [ animationProp + durationKey ] ) ;
608
617
609
618
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 ;
613
620
}
614
621
615
622
transitionTime = Math . max ( transitionDelay + transitionDuration , transitionTime ) ;
@@ -628,38 +635,35 @@ angular.module('ngAnimate', ['ng'])
628
635
//temporarily disable the transition so that the enter styles
629
636
//don't animate twice (this is here to avoid a bug in Chrome/FF).
630
637
if ( transitionTime > 0 ) {
631
- node . style [ w3cTransitionProp + propertyKey ] = 'none' ;
632
- node . style [ vendorTransitionProp + propertyKey ] = 'none' ;
638
+ node . style [ transitionProp + propertyKey ] = 'none' ;
633
639
}
634
640
635
641
var activeClassName = '' ;
636
642
forEach ( className . split ( ' ' ) , function ( klass , i ) {
637
643
activeClassName += ( i > 0 ? ' ' : '' ) + klass + '-active' ;
638
644
} ) ;
639
645
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.
641
647
element . prop ( 'clientWidth' ) ;
642
648
if ( transitionTime > 0 ) {
643
- node . style [ w3cTransitionProp + propertyKey ] = '' ;
644
- node . style [ vendorTransitionProp + propertyKey ] = '' ;
649
+ node . style [ transitionProp + propertyKey ] = '' ;
645
650
}
646
651
element . addClass ( activeClassName ) ;
647
652
648
- var css3AnimationEvents = [ w3cAnimationEvent , vendorAnimationEvent ,
649
- w3cTransitionEvent , vendorTransitionEvent ] . join ( ' ' ) ;
653
+ var css3AnimationEvents = animationendEvent + ' ' + transitionendEvent ;
650
654
element . on ( css3AnimationEvents , onAnimationProgress ) ;
651
655
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.
655
659
return function onEnd ( cancelled ) {
656
660
element . off ( css3AnimationEvents , onAnimationProgress ) ;
657
661
element . removeClass ( className ) ;
658
662
element . removeClass ( activeClassName ) ;
659
663
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.
663
667
if ( cancelled ) {
664
668
done ( ) ;
665
669
}
0 commit comments