@@ -642,6 +642,10 @@ angular.module('ngAnimate', ['ng'])
642642 animationIterationCountKey = 'IterationCount' ,
643643 ELEMENT_NODE = 1 ;
644644
645+ var NG_ANIMATE_PARENT_KEY = '$ngAnimateKey' ;
646+ var lookupCache = { } ;
647+ var parentCounter = 0 ;
648+
645649 var animationReflowQueue = [ ] , animationTimer , timeOut = false ;
646650 function afterReflow ( callback ) {
647651 animationReflowQueue . push ( callback ) ;
@@ -652,65 +656,93 @@ angular.module('ngAnimate', ['ng'])
652656 } ) ;
653657 animationReflowQueue = [ ] ;
654658 animationTimer = null ;
659+ lookupCache = { } ;
655660 } , 10 , false ) ;
656661 }
657662
658- function animate ( element , className , done ) {
659- if ( [ 'ng-enter' , 'ng-leave' , 'ng-move' ] . indexOf ( className ) == - 1 ) {
660- var existingDuration = 0 ;
663+ function getElementAnimationDetails ( element , cacheKey , onlyCheckTransition ) {
664+ var data = lookupCache [ cacheKey ] ;
665+ if ( ! data ) {
666+ var transitionDuration = 0 , transitionDelay = 0 ,
667+ animationDuration = 0 , animationDelay = 0 ;
668+
669+ //we want all the styles defined before and after
661670 forEach ( element , function ( element ) {
662671 if ( element . nodeType == ELEMENT_NODE ) {
663672 var elementStyles = $window . getComputedStyle ( element ) || { } ;
664- existingDuration = Math . max ( parseMaxTime ( elementStyles [ transitionProp + durationKey ] ) ,
665- existingDuration ) ;
673+
674+ transitionDuration = Math . max ( parseMaxTime ( elementStyles [ transitionProp + durationKey ] ) , transitionDuration ) ;
675+
676+ if ( ! onlyCheckTransition ) {
677+ transitionDelay = Math . max ( parseMaxTime ( elementStyles [ transitionProp + delayKey ] ) , transitionDelay ) ;
678+
679+ animationDelay = Math . max ( parseMaxTime ( elementStyles [ animationProp + delayKey ] ) , animationDelay ) ;
680+
681+ var aDuration = parseMaxTime ( elementStyles [ animationProp + durationKey ] ) ;
682+
683+ if ( aDuration > 0 ) {
684+ aDuration *= parseInt ( elementStyles [ animationProp + animationIterationCountKey ] ) || 1 ;
685+ }
686+
687+ animationDuration = Math . max ( aDuration , animationDuration ) ;
688+ }
666689 }
667690 } ) ;
668- if ( existingDuration > 0 ) {
669- done ( ) ;
670- return ;
671- }
691+ data = {
692+ transitionDelay : transitionDelay ,
693+ animationDelay : animationDelay ,
694+ transitionDuration : transitionDuration ,
695+ animationDuration : animationDuration
696+ } ;
697+ lookupCache [ cacheKey ] = data ;
672698 }
699+ return data ;
700+ }
673701
674- element . addClass ( className ) ;
675-
676- //we want all the styles defined before and after
677- var transitionDuration = 0 ,
678- animationDuration = 0 ,
679- transitionDelay = 0 ,
680- animationDelay = 0 ;
681- forEach ( element , function ( element ) {
682- if ( element . nodeType == ELEMENT_NODE ) {
683- var elementStyles = $window . getComputedStyle ( element ) || { } ;
702+ function parseMaxTime ( str ) {
703+ var total = 0 , values = angular . isString ( str ) ? str . split ( / \s * , \s * / ) : [ ] ;
704+ forEach ( values , function ( value ) {
705+ total = Math . max ( parseFloat ( value ) || 0 , total ) ;
706+ } ) ;
707+ return total ;
708+ }
684709
685- transitionDelay = Math . max ( parseMaxTime ( elementStyles [ transitionProp + delayKey ] ) , transitionDelay ) ;
710+ function getCacheKey ( element ) {
711+ var parent = element . parent ( ) ;
712+ var parentID = parent . data ( NG_ANIMATE_PARENT_KEY ) ;
713+ if ( ! parentID ) {
714+ parent . data ( NG_ANIMATE_PARENT_KEY , ++ parentCounter ) ;
715+ parentID = parentCounter ;
716+ }
717+ return parentID + '-' + element [ 0 ] . className ;
718+ }
686719
687- animationDelay = Math . max ( parseMaxTime ( elementStyles [ animationProp + delayKey ] ) , animationDelay ) ;
720+ function animate ( element , className , done ) {
688721
689- transitionDuration = Math . max ( parseMaxTime ( elementStyles [ transitionProp + durationKey ] ) , transitionDuration ) ;
722+ var cacheKey = getCacheKey ( element ) ;
723+ if ( getElementAnimationDetails ( element , cacheKey , true ) . transitionDuration > 0 ) {
690724
691- var aDuration = parseMaxTime ( elementStyles [ animationProp + durationKey ] ) ;
725+ done ( ) ;
726+ return ;
727+ }
692728
693- if ( aDuration > 0 ) {
694- aDuration *= parseInt ( elementStyles [ animationProp + animationIterationCountKey ] ) || 1 ;
695- }
729+ element . addClass ( className ) ;
696730
697- animationDuration = Math . max ( aDuration , animationDuration ) ;
698- }
699- } ) ;
731+ var timings = getElementAnimationDetails ( element , cacheKey + ' ' + className ) ;
700732
701733 /* there is no point in performing a reflow if the animation
702734 timeout is empty (this would cause a flicker bug normally
703735 in the page. There is also no point in performing an animation
704736 that only has a delay and no duration */
705- var maxDuration = Math . max ( transitionDuration , animationDuration ) ;
737+ var maxDuration = Math . max ( timings . transitionDuration , timings . animationDuration ) ;
706738 if ( maxDuration > 0 ) {
707- var maxDelayTime = Math . max ( transitionDelay , animationDelay ) * 1000 ,
739+ var maxDelayTime = Math . max ( timings . transitionDelay , timings . animationDelay ) * 1000 ,
708740 startTime = Date . now ( ) ,
709741 node = element [ 0 ] ;
710742
711743 //temporarily disable the transition so that the enter styles
712744 //don't animate twice (this is here to avoid a bug in Chrome/FF).
713- if ( transitionDuration > 0 ) {
745+ if ( timings . transitionDuration > 0 ) {
714746 node . style [ transitionProp + propertyKey ] = 'none' ;
715747 }
716748
@@ -723,7 +755,7 @@ angular.module('ngAnimate', ['ng'])
723755 var css3AnimationEvents = animationendEvent + ' ' + transitionendEvent ;
724756
725757 afterReflow ( function ( ) {
726- if ( transitionDuration > 0 ) {
758+ if ( timings . transitionDuration > 0 ) {
727759 node . style [ transitionProp + propertyKey ] = '' ;
728760 }
729761 element . addClass ( activeClassName ) ;
@@ -768,13 +800,6 @@ angular.module('ngAnimate', ['ng'])
768800 }
769801 }
770802
771- function parseMaxTime ( str ) {
772- var total = 0 , values = angular . isString ( str ) ? str . split ( / \s * , \s * / ) : [ ] ;
773- forEach ( values , function ( value ) {
774- total = Math . max ( parseFloat ( value ) || 0 , total ) ;
775- } ) ;
776- return total ;
777- }
778803 }
779804
780805 return {
0 commit comments