5
5
* Use of this source code is governed by an MIT-style license that can be
6
6
* found in the LICENSE file at https://angular.io/license
7
7
*/
8
-
9
8
/* tslint:disable */
10
9
import { AUTO_STYLE , AnimationOptions , AnimationPlayer , NoopAnimationPlayer , ɵPRE_STYLE as PRE_STYLE , ɵStyleData } from '@angular/animations' ;
11
10
@@ -23,6 +22,11 @@ import {AnimationDriver} from '@angular/animations/browser/src/render/animation_
23
22
24
23
import { getOrSetAsInMap , listenOnPlayer , makeAnimationEvent , normalizeKeyframes , optimizeGroupPlayer } from "../render/shared" ;
25
24
25
+ const QUEUED_CLASSNAME = 'ng-animate-queued' ;
26
+ const QUEUED_SELECTOR = '.ng-animate-queued' ;
27
+ const DISABLED_CLASSNAME = 'ng-animate-disabled' ;
28
+ const DISABLED_SELECTOR = '.ng-animate-disabled' ;
29
+
26
30
const EMPTY_PLAYER_ARRAY : TransitionAnimationPlayer [ ] = [ ] ;
27
31
const NULL_REMOVAL_STATE : ElementAnimationState = {
28
32
namespaceId : '' ,
@@ -205,6 +209,16 @@ export class AnimationTransitionNamespace {
205
209
return player ;
206
210
}
207
211
212
+ const isRemoval = toState . value === VOID_VALUE ;
213
+
214
+ // normally this isn't reached by here, however, if an object expression
215
+ // is passed in then it may be a new object each time. Comparing the value
216
+ // is important since that will stay the same despite there being a new object.
217
+ // The removal arc here is special cased because the same element is triggered
218
+ // twice in the event that it contains animations on the outer/inner portions
219
+ // of the host container
220
+ if ( ! isRemoval && fromState . value === toState . value ) return ;
221
+
208
222
const playersOnElement : TransitionAnimationPlayer [ ] =
209
223
getOrSetAsInMap ( this . _engine . playersByElement , element , [ ] ) ;
210
224
playersOnElement . forEach ( player => {
@@ -230,12 +244,11 @@ export class AnimationTransitionNamespace {
230
244
{ element, triggerName, transition, fromState, toState, player, isFallbackTransition} ) ;
231
245
232
246
if ( ! isFallbackTransition ) {
233
- addClass ( element , NG_ANIMATING_CLASSNAME ) ;
247
+ addClass ( element , QUEUED_CLASSNAME ) ;
248
+ player . onStart ( ( ) => { removeClass ( element , QUEUED_CLASSNAME ) ; } ) ;
234
249
}
235
250
236
251
player . onDone ( ( ) => {
237
- removeClass ( element , NG_ANIMATING_CLASSNAME ) ;
238
-
239
252
let index = this . players . indexOf ( player ) ;
240
253
if ( index >= 0 ) {
241
254
this . players . splice ( index , 1 ) ;
@@ -259,7 +272,7 @@ export class AnimationTransitionNamespace {
259
272
deregister ( name : string ) {
260
273
delete this . _triggers [ name ] ;
261
274
262
- this . _engine . statesByElement . forEach ( ( stateMap , _element ) => { delete stateMap [ name ] ; } ) ;
275
+ this . _engine . statesByElement . forEach ( ( stateMap , element ) => { delete stateMap [ name ] ; } ) ;
263
276
264
277
this . _elementListeners . forEach ( ( listeners , element ) => {
265
278
this . _elementListeners . set (
@@ -392,7 +405,7 @@ export class AnimationTransitionNamespace {
392
405
}
393
406
}
394
407
395
- insertNode ( element : any , _parent : any ) : void { addClass ( element , this . _hostClassName ) ; }
408
+ insertNode ( element : any , parent : any ) : void { addClass ( element , this . _hostClassName ) ; }
396
409
397
410
drainQueuedTransitions ( microtaskId : number ) : QueueInstruction [ ] {
398
411
const instructions : QueueInstruction [ ] = [ ] ;
@@ -464,6 +477,8 @@ export class TransitionAnimationEngine {
464
477
public playersByElement = new Map < any , TransitionAnimationPlayer [ ] > ( ) ;
465
478
public playersByQueriedElement = new Map < any , TransitionAnimationPlayer [ ] > ( ) ;
466
479
public statesByElement = new Map < any , { [ triggerName : string ] : StateValue } > ( ) ;
480
+ public disabledNodes = new Set < any > ( ) ;
481
+
467
482
public totalAnimations = 0 ;
468
483
public totalQueuedPlayers = 0 ;
469
484
@@ -477,7 +492,7 @@ export class TransitionAnimationEngine {
477
492
public collectedLeaveElements : any [ ] = [ ] ;
478
493
479
494
// this method is designed to be overridden by the code that uses this engine
480
- public onRemovalComplete = ( _element : any , _context : any ) => { } ;
495
+ public onRemovalComplete = ( element : any , context : any ) => { } ;
481
496
482
497
_onRemovalComplete ( element : any , context : any ) { this . onRemovalComplete ( element , context ) ; }
483
498
@@ -605,6 +620,18 @@ export class TransitionAnimationEngine {
605
620
606
621
collectEnterElement ( element : any ) { this . collectedEnterElements . push ( element ) ; }
607
622
623
+ markElementAsDisabled ( element : any , value : boolean ) {
624
+ if ( value ) {
625
+ if ( ! this . disabledNodes . has ( element ) ) {
626
+ this . disabledNodes . add ( element ) ;
627
+ addClass ( element , DISABLED_CLASSNAME ) ;
628
+ }
629
+ } else if ( this . disabledNodes . has ( element ) ) {
630
+ this . disabledNodes . delete ( element ) ;
631
+ removeClass ( element , DISABLED_CLASSNAME ) ;
632
+ }
633
+ }
634
+
608
635
removeNode ( namespaceId : string , element : any , context : any , doNotRecurse ?: boolean ) : void {
609
636
if ( ! isElementNode ( element ) ) {
610
637
this . _onRemovalComplete ( element , context ) ;
@@ -702,6 +729,14 @@ export class TransitionAnimationEngine {
702
729
}
703
730
this . _onRemovalComplete ( element , details . setForRemoval ) ;
704
731
}
732
+
733
+ if ( this . driver . matchesElement ( element , DISABLED_SELECTOR ) ) {
734
+ this . markElementAsDisabled ( element , false ) ;
735
+ }
736
+
737
+ this . driver . query ( element , DISABLED_SELECTOR , true ) . forEach ( node => {
738
+ this . markElementAsDisabled ( element , false ) ;
739
+ } ) ;
705
740
}
706
741
707
742
flush ( microtaskId : number = - 1 ) {
@@ -759,6 +794,14 @@ export class TransitionAnimationEngine {
759
794
const allPreStyleElements = new Map < any , Set < string > > ( ) ;
760
795
const allPostStyleElements = new Map < any , Set < string > > ( ) ;
761
796
797
+ const disabledElementsSet = new Set < any > ( ) ;
798
+ this . disabledNodes . forEach ( node => {
799
+ const nodesThatAreDisabled = this . driver . query ( node , QUEUED_SELECTOR , true ) ;
800
+ for ( let i = 0 ; i < nodesThatAreDisabled . length ; i ++ ) {
801
+ disabledElementsSet . add ( nodesThatAreDisabled [ i ] ) ;
802
+ }
803
+ } ) ;
804
+
762
805
const bodyNode = getBodyNode ( ) ;
763
806
const allEnterNodes : any [ ] = this . collectedEnterElements . length ?
764
807
this . collectedEnterElements . filter ( createIsRootFilterFn ( this . collectedEnterElements ) ) :
@@ -808,7 +851,7 @@ export class TransitionAnimationEngine {
808
851
}
809
852
810
853
const instruction = this . _buildInstruction ( entry , subTimelines ) ! ;
811
- if ( ( < any > instruction ) . errors && ( < any > instruction ) . errors . length ) {
854
+ if ( instruction . errors && instruction . errors . length ) {
812
855
erroneousTransitions . push ( instruction ) ;
813
856
return ;
814
857
}
@@ -864,7 +907,7 @@ export class TransitionAnimationEngine {
864
907
let msg = `Unable to process animations due to the following failed trigger transitions\n` ;
865
908
erroneousTransitions . forEach ( instruction => {
866
909
msg += `@${ instruction . triggerName } has failed due to:\n` ;
867
- ( < any > instruction ) . errors ! . forEach ( error => { msg += `- ${ error } \n` ; } ) ;
910
+ instruction . errors ! . forEach ( error => { msg += `- ${ error } \n` ; } ) ;
868
911
} ) ;
869
912
870
913
allPlayers . forEach ( player => player . destroy ( ) ) ;
@@ -919,6 +962,11 @@ export class TransitionAnimationEngine {
919
962
// this means that it was never consumed by a parent animation which
920
963
// means that it is independent and therefore should be set for animation
921
964
if ( subTimelines . has ( element ) ) {
965
+ if ( disabledElementsSet . has ( element ) ) {
966
+ skippedPlayers . push ( player ) ;
967
+ return ;
968
+ }
969
+
922
970
const innerPlayer = this . _buildAnimation (
923
971
player . namespaceId , instruction , allPreviousPlayersMap , skippedPlayersMap , preStylesMap ,
924
972
postStylesMap ) ;
0 commit comments