@@ -484,12 +484,12 @@ angular.module('ngAnimate', ['ng'])
484484 // the matching CSS class.
485485 if ( status < 0 ) {
486486 //does it have the class or will it have the class
487- if ( hasClass || matchingAnimation . event == 'addClass' ) {
487+ if ( hasClass || matchingAnimation . event == 'addClass' ) {
488488 toRemove . push ( className ) ;
489489 }
490490 } else if ( status > 0 ) {
491491 //is the class missing or will it be removed?
492- if ( ! hasClass || matchingAnimation . event == 'removeClass' ) {
492+ if ( ! hasClass || matchingAnimation . event == 'removeClass' ) {
493493 toAdd . push ( className ) ;
494494 }
495495 }
@@ -544,7 +544,7 @@ angular.module('ngAnimate', ['ng'])
544544 if ( ! classNameAdd ) {
545545 className = classNameRemove ;
546546 animationEvent = 'removeClass' ;
547- } else if ( ! classNameRemove ) {
547+ } else if ( ! classNameRemove ) {
548548 className = classNameAdd ;
549549 animationEvent = 'addClass' ;
550550 } else {
@@ -1101,6 +1101,7 @@ angular.module('ngAnimate', ['ng'])
11011101 var totalActiveAnimations = ngAnimateState . totalActive || 0 ;
11021102 var lastAnimation = ngAnimateState . last ;
11031103 var skipAnimation = false ;
1104+
11041105 if ( totalActiveAnimations > 0 ) {
11051106 var animationsToCancel = [ ] ;
11061107 if ( ! runner . isClassBased ) {
@@ -1384,6 +1385,7 @@ angular.module('ngAnimate', ['ng'])
13841385 var PROPERTY_KEY = 'Property' ;
13851386 var DELAY_KEY = 'Delay' ;
13861387 var ANIMATION_ITERATION_COUNT_KEY = 'IterationCount' ;
1388+ var ANIMATION_PLAYSTATE_KEY = 'PlayState' ;
13871389 var NG_ANIMATE_PARENT_KEY = '$$ngAnimateKey' ;
13881390 var NG_ANIMATE_CSS_DATA_KEY = '$$ngAnimateCSS3Data' ;
13891391 var ELAPSED_TIME_MAX_DECIMAL_PLACES = 3 ;
@@ -1455,47 +1457,33 @@ angular.module('ngAnimate', ['ng'])
14551457 var transitionDelay = 0 ;
14561458 var animationDuration = 0 ;
14571459 var animationDelay = 0 ;
1458- var transitionDelayStyle ;
1459- var animationDelayStyle ;
1460- var transitionDurationStyle ;
1461- var transitionPropertyStyle ;
14621460
14631461 //we want all the styles defined before and after
14641462 forEach ( element , function ( element ) {
14651463 if ( element . nodeType == ELEMENT_NODE ) {
14661464 var elementStyles = $window . getComputedStyle ( element ) || { } ;
14671465
1468- transitionDurationStyle = elementStyles [ TRANSITION_PROP + DURATION_KEY ] ;
1469-
1466+ var transitionDurationStyle = elementStyles [ TRANSITION_PROP + DURATION_KEY ] ;
14701467 transitionDuration = Math . max ( parseMaxTime ( transitionDurationStyle ) , transitionDuration ) ;
14711468
1472- transitionPropertyStyle = elementStyles [ TRANSITION_PROP + PROPERTY_KEY ] ;
1473-
1474- transitionDelayStyle = elementStyles [ TRANSITION_PROP + DELAY_KEY ] ;
1475-
1469+ var transitionDelayStyle = elementStyles [ TRANSITION_PROP + DELAY_KEY ] ;
14761470 transitionDelay = Math . max ( parseMaxTime ( transitionDelayStyle ) , transitionDelay ) ;
14771471
1478- animationDelayStyle = elementStyles [ ANIMATION_PROP + DELAY_KEY ] ;
1479-
1480- animationDelay = Math . max ( parseMaxTime ( animationDelayStyle ) , animationDelay ) ;
1472+ var animationDelayStyle = elementStyles [ ANIMATION_PROP + DELAY_KEY ] ;
1473+ animationDelay = Math . max ( parseMaxTime ( elementStyles [ ANIMATION_PROP + DELAY_KEY ] ) , animationDelay ) ;
14811474
14821475 var aDuration = parseMaxTime ( elementStyles [ ANIMATION_PROP + DURATION_KEY ] ) ;
14831476
14841477 if ( aDuration > 0 ) {
14851478 aDuration *= parseInt ( elementStyles [ ANIMATION_PROP + ANIMATION_ITERATION_COUNT_KEY ] , 10 ) || 1 ;
14861479 }
1487-
14881480 animationDuration = Math . max ( aDuration , animationDuration ) ;
14891481 }
14901482 } ) ;
14911483 data = {
14921484 total : 0 ,
1493- transitionPropertyStyle : transitionPropertyStyle ,
1494- transitionDurationStyle : transitionDurationStyle ,
1495- transitionDelayStyle : transitionDelayStyle ,
14961485 transitionDelay : transitionDelay ,
14971486 transitionDuration : transitionDuration ,
1498- animationDelayStyle : animationDelayStyle ,
14991487 animationDelay : animationDelay ,
15001488 animationDuration : animationDuration
15011489 } ;
@@ -1571,18 +1559,17 @@ angular.module('ngAnimate', ['ng'])
15711559 running : formerData . running || 0 ,
15721560 itemIndex : itemIndex ,
15731561 blockTransition : blockTransition ,
1574- blockAnimation : blockAnimation ,
15751562 closeAnimationFns : closeAnimationFns
15761563 } ) ;
15771564
15781565 var node = extractElementNode ( element ) ;
15791566
15801567 if ( blockTransition ) {
1581- node . style [ TRANSITION_PROP + PROPERTY_KEY ] = 'none' ;
1568+ blockTransitions ( node , true ) ;
15821569 }
15831570
15841571 if ( blockAnimation ) {
1585- node . style [ ANIMATION_PROP ] = 'none 0s' ;
1572+ blockAnimations ( node , true ) ;
15861573 }
15871574
15881575 return true ;
@@ -1597,22 +1584,43 @@ angular.module('ngAnimate', ['ng'])
15971584 }
15981585
15991586 if ( elementData . blockTransition ) {
1600- node . style [ TRANSITION_PROP + PROPERTY_KEY ] = '' ;
1601- }
1602-
1603- if ( elementData . blockAnimation ) {
1604- node . style [ ANIMATION_PROP ] = '' ;
1587+ blockTransitions ( node , false ) ;
16051588 }
16061589
16071590 var activeClassName = '' ;
1591+ var pendingClassName = '' ;
16081592 forEach ( className . split ( ' ' ) , function ( klass , i ) {
1609- activeClassName += ( i > 0 ? ' ' : '' ) + klass + '-active' ;
1593+ var prefix = ( i > 0 ? ' ' : '' ) + klass ;
1594+ activeClassName += prefix + '-active' ;
1595+ pendingClassName += prefix + '-pending' ;
16101596 } ) ;
16111597
1612- element . addClass ( activeClassName ) ;
1598+ var style = '' ;
1599+ var appliedStyles = [ ] ;
1600+ var itemIndex = elementData . itemIndex ;
1601+ var stagger = elementData . stagger ;
1602+ var staggerTime = 0 ;
1603+ if ( itemIndex > 0 ) {
1604+ var transitionStaggerDelay = 0 ;
1605+ if ( stagger . transitionDelay > 0 && stagger . transitionDuration === 0 ) {
1606+ transitionStaggerDelay = stagger . transitionDelay * itemIndex ;
1607+ }
1608+
1609+ var animationStaggerDelay = 0 ;
1610+ if ( stagger . animationDelay > 0 && stagger . animationDuration === 0 ) {
1611+ animationStaggerDelay = stagger . animationDelay * itemIndex ;
1612+ appliedStyles . push ( CSS_PREFIX + 'animation-play-state' ) ;
1613+ }
1614+
1615+ staggerTime = Math . round ( Math . max ( transitionStaggerDelay , animationStaggerDelay ) * 100 ) / 100 ;
1616+ }
1617+
1618+ if ( ! staggerTime ) {
1619+ element . addClass ( activeClassName ) ;
1620+ }
1621+
16131622 var eventCacheKey = elementData . cacheKey + ' ' + activeClassName ;
16141623 var timings = getElementAnimationDetails ( element , eventCacheKey ) ;
1615-
16161624 var maxDuration = Math . max ( timings . transitionDuration , timings . animationDuration ) ;
16171625 if ( maxDuration === 0 ) {
16181626 element . removeClass ( activeClassName ) ;
@@ -1622,57 +1630,43 @@ angular.module('ngAnimate', ['ng'])
16221630 }
16231631
16241632 var maxDelay = Math . max ( timings . transitionDelay , timings . animationDelay ) ;
1625- var stagger = elementData . stagger ;
1626- var itemIndex = elementData . itemIndex ;
16271633 var maxDelayTime = maxDelay * ONE_SECOND ;
16281634
1629- var style = '' , appliedStyles = [ ] ;
1630- if ( timings . transitionDuration > 0 ) {
1631- var propertyStyle = timings . transitionPropertyStyle ;
1632- if ( propertyStyle . indexOf ( 'all' ) == - 1 ) {
1633- style += CSS_PREFIX + 'transition-property: ' + propertyStyle + ';' ;
1634- style += CSS_PREFIX + 'transition-duration: ' + timings . transitionDurationStyle + ';' ;
1635- appliedStyles . push ( CSS_PREFIX + 'transition-property' ) ;
1636- appliedStyles . push ( CSS_PREFIX + 'transition-duration' ) ;
1637- }
1638- }
1639-
1640- if ( itemIndex > 0 ) {
1641- if ( stagger . transitionDelay > 0 && stagger . transitionDuration === 0 ) {
1642- var delayStyle = timings . transitionDelayStyle ;
1643- style += CSS_PREFIX + 'transition-delay: ' +
1644- prepareStaggerDelay ( delayStyle , stagger . transitionDelay , itemIndex ) + '; ' ;
1645- appliedStyles . push ( CSS_PREFIX + 'transition-delay' ) ;
1646- }
1647-
1648- if ( stagger . animationDelay > 0 && stagger . animationDuration === 0 ) {
1649- style += CSS_PREFIX + 'animation-delay: ' +
1650- prepareStaggerDelay ( timings . animationDelayStyle , stagger . animationDelay , itemIndex ) + '; ' ;
1651- appliedStyles . push ( CSS_PREFIX + 'animation-delay' ) ;
1652- }
1653- }
1654-
16551635 if ( appliedStyles . length > 0 ) {
16561636 //the element being animated may sometimes contain comment nodes in
16571637 //the jqLite object, so we're safe to use a single variable to house
16581638 //the styles since there is always only one element being animated
16591639 var oldStyle = node . getAttribute ( 'style' ) || '' ;
1660- node . setAttribute ( 'style' , oldStyle + '; ' + style ) ;
1640+ if ( oldStyle . charAt ( oldStyle . length - 1 ) !== ';' ) {
1641+ oldStyle += ';' ;
1642+ }
1643+ node . setAttribute ( 'style' , oldStyle + ' ' + style ) ;
16611644 }
16621645
16631646 var startTime = Date . now ( ) ;
16641647 var css3AnimationEvents = ANIMATIONEND_EVENT + ' ' + TRANSITIONEND_EVENT ;
1648+ var animationTime = ( maxDelay + maxDuration ) * CLOSING_TIME_BUFFER ;
1649+ var totalTime = ( staggerTime + animationTime ) * ONE_SECOND ;
1650+
1651+ var staggerTimeout ;
1652+ if ( staggerTime > 0 ) {
1653+ element . addClass ( pendingClassName ) ;
1654+ staggerTimeout = $timeout ( function ( ) {
1655+ staggerTimeout = null ;
1656+ element . addClass ( activeClassName ) ;
1657+ element . removeClass ( pendingClassName ) ;
1658+ if ( timings . animationDuration > 0 ) {
1659+ blockAnimations ( node , false ) ;
1660+ }
1661+ } , staggerTime * ONE_SECOND , false ) ;
1662+ }
16651663
16661664 element . on ( css3AnimationEvents , onAnimationProgress ) ;
16671665 elementData . closeAnimationFns . push ( function ( ) {
16681666 onEnd ( ) ;
16691667 activeAnimationComplete ( ) ;
16701668 } ) ;
16711669
1672- var staggerTime = itemIndex * ( Math . max ( stagger . animationDelay , stagger . transitionDelay ) || 0 ) ;
1673- var animationTime = ( maxDelay + maxDuration ) * CLOSING_TIME_BUFFER ;
1674- var totalTime = ( staggerTime + animationTime ) * ONE_SECOND ;
1675-
16761670 elementData . running ++ ;
16771671 animationCloseHandler ( element , totalTime ) ;
16781672 return onEnd ;
@@ -1683,6 +1677,10 @@ angular.module('ngAnimate', ['ng'])
16831677 function onEnd ( cancelled ) {
16841678 element . off ( css3AnimationEvents , onAnimationProgress ) ;
16851679 element . removeClass ( activeClassName ) ;
1680+ element . removeClass ( pendingClassName ) ;
1681+ if ( staggerTimeout ) {
1682+ $timeout . cancel ( staggerTimeout ) ;
1683+ }
16861684 animateClose ( element , className ) ;
16871685 var node = extractElementNode ( element ) ;
16881686 for ( var i in appliedStyles ) {
@@ -1712,13 +1710,12 @@ angular.module('ngAnimate', ['ng'])
17121710 }
17131711 }
17141712
1715- function prepareStaggerDelay ( delayStyle , staggerDelay , index ) {
1716- var style = '' ;
1717- forEach ( delayStyle . split ( ',' ) , function ( val , i ) {
1718- style += ( i > 0 ? ',' : '' ) +
1719- ( index * staggerDelay + parseInt ( val , 10 ) ) + 's' ;
1720- } ) ;
1721- return style ;
1713+ function blockTransitions ( node , bool ) {
1714+ node . style [ TRANSITION_PROP + PROPERTY_KEY ] = bool ? 'none' : '' ;
1715+ }
1716+
1717+ function blockAnimations ( node , bool ) {
1718+ node . style [ ANIMATION_PROP + ANIMATION_PLAYSTATE_KEY ] = bool ? 'paused' : '' ;
17221719 }
17231720
17241721 function animateBefore ( animationEvent , element , className , calculationDecorator ) {
0 commit comments