@@ -28,6 +28,7 @@ import {OverlayConfig} from './overlay-config';
28
28
import { coerceCssPixelValue , coerceArray } from '@angular/cdk/coercion' ;
29
29
import { PositionStrategy } from './position/position-strategy' ;
30
30
import { ScrollStrategy } from './scroll' ;
31
+ import { BackdropRef } from './backdrop-ref' ;
31
32
32
33
/** An object where all of its properties cannot be written. */
33
34
export type ImmutableObject < T > = {
@@ -39,16 +40,13 @@ export type ImmutableObject<T> = {
39
40
* Used to manipulate or dispose of said overlay.
40
41
*/
41
42
export class OverlayRef implements PortalOutlet {
42
- private _backdropElement : HTMLElement | null = null ;
43
- private _backdropTimeout : ReturnType < typeof setTimeout > | undefined ;
44
43
private readonly _backdropClick = new Subject < MouseEvent > ( ) ;
45
44
private readonly _attachments = new Subject < void > ( ) ;
46
45
private readonly _detachments = new Subject < void > ( ) ;
47
46
private _positionStrategy : PositionStrategy | undefined ;
48
47
private _scrollStrategy : ScrollStrategy | undefined ;
49
48
private _locationChanges : SubscriptionLike = Subscription . EMPTY ;
50
- private _cleanupBackdropClick : ( ( ) => void ) | undefined ;
51
- private _cleanupBackdropTransitionEnd : ( ( ) => void ) | undefined ;
49
+ private _backdropRef : BackdropRef | null = null ;
52
50
53
51
/**
54
52
* Reference to the parent of the `_host` at the time it was detached. Used to restore
@@ -110,7 +108,7 @@ export class OverlayRef implements PortalOutlet {
110
108
111
109
/** The overlay's backdrop HTML element. */
112
110
get backdropElement ( ) : HTMLElement | null {
113
- return this . _backdropElement ;
111
+ return this . _backdropRef ?. element || null ;
114
112
}
115
113
116
114
/**
@@ -265,7 +263,7 @@ export class OverlayRef implements PortalOutlet {
265
263
}
266
264
267
265
this . _disposeScrollStrategy ( ) ;
268
- this . _disposeBackdrop ( this . _backdropElement ) ;
266
+ this . _backdropRef ?. dispose ( ) ;
269
267
this . _locationChanges . unsubscribe ( ) ;
270
268
this . _keyboardDispatcher . remove ( this ) ;
271
269
this . _portalOutlet . dispose ( ) ;
@@ -276,8 +274,7 @@ export class OverlayRef implements PortalOutlet {
276
274
this . _outsideClickDispatcher . remove ( this ) ;
277
275
this . _host ?. remove ( ) ;
278
276
this . _afterNextRenderRef ?. destroy ( ) ;
279
-
280
- this . _previousHostParent = this . _pane = this . _host = null ! ;
277
+ this . _previousHostParent = this . _pane = this . _host = this . _backdropRef = null ! ;
281
278
282
279
if ( isAttached ) {
283
280
this . _detachments . next ( ) ;
@@ -432,41 +429,30 @@ export class OverlayRef implements PortalOutlet {
432
429
private _attachBackdrop ( ) {
433
430
const showingClass = 'cdk-overlay-backdrop-showing' ;
434
431
435
- this . _backdropElement = this . _document . createElement ( 'div' ) ;
436
- this . _backdropElement . classList . add ( 'cdk-overlay-backdrop' ) ;
432
+ this . _backdropRef ?. dispose ( ) ;
433
+ this . _backdropRef = new BackdropRef ( this . _document , this . _renderer , this . _ngZone , event => {
434
+ this . _backdropClick . next ( event ) ;
435
+ } ) ;
437
436
438
437
if ( this . _animationsDisabled ) {
439
- this . _backdropElement . classList . add ( 'cdk-overlay-backdrop-noop-animation' ) ;
438
+ this . _backdropRef . element . classList . add ( 'cdk-overlay-backdrop-noop-animation' ) ;
440
439
}
441
440
442
441
if ( this . _config . backdropClass ) {
443
- this . _toggleClasses ( this . _backdropElement , this . _config . backdropClass , true ) ;
442
+ this . _toggleClasses ( this . _backdropRef . element , this . _config . backdropClass , true ) ;
444
443
}
445
444
446
445
// Insert the backdrop before the pane in the DOM order,
447
446
// in order to handle stacked overlays properly.
448
- this . _host . parentElement ! . insertBefore ( this . _backdropElement , this . _host ) ;
449
-
450
- // Forward backdrop clicks such that the consumer of the overlay can perform whatever
451
- // action desired when such a click occurs (usually closing the overlay).
452
- this . _cleanupBackdropClick ?.( ) ;
453
- this . _cleanupBackdropClick = this . _renderer . listen (
454
- this . _backdropElement ,
455
- 'click' ,
456
- ( event : MouseEvent ) => this . _backdropClick . next ( event ) ,
457
- ) ;
447
+ this . _host . parentElement ! . insertBefore ( this . _backdropRef . element , this . _host ) ;
458
448
459
449
// Add class to fade-in the backdrop after one frame.
460
450
if ( ! this . _animationsDisabled && typeof requestAnimationFrame !== 'undefined' ) {
461
451
this . _ngZone . runOutsideAngular ( ( ) => {
462
- requestAnimationFrame ( ( ) => {
463
- if ( this . _backdropElement ) {
464
- this . _backdropElement . classList . add ( showingClass ) ;
465
- }
466
- } ) ;
452
+ requestAnimationFrame ( ( ) => this . _backdropRef ?. element . classList . add ( showingClass ) ) ;
467
453
} ) ;
468
454
} else {
469
- this . _backdropElement . classList . add ( showingClass ) ;
455
+ this . _backdropRef . element . classList . add ( showingClass ) ;
470
456
}
471
457
}
472
458
@@ -485,42 +471,12 @@ export class OverlayRef implements PortalOutlet {
485
471
486
472
/** Detaches the backdrop (if any) associated with the overlay. */
487
473
detachBackdrop ( ) : void {
488
- const backdropToDetach = this . _backdropElement ;
489
-
490
- if ( ! backdropToDetach ) {
491
- return ;
492
- }
493
-
494
474
if ( this . _animationsDisabled ) {
495
- this . _disposeBackdrop ( backdropToDetach ) ;
496
- return ;
475
+ this . _backdropRef ?. dispose ( ) ;
476
+ this . _backdropRef = null ;
477
+ } else {
478
+ this . _backdropRef ?. detach ( ) ;
497
479
}
498
-
499
- backdropToDetach . classList . remove ( 'cdk-overlay-backdrop-showing' ) ;
500
-
501
- this . _ngZone . runOutsideAngular ( ( ) => {
502
- this . _cleanupBackdropTransitionEnd ?.( ) ;
503
- this . _cleanupBackdropTransitionEnd = this . _renderer . listen (
504
- backdropToDetach ,
505
- 'transitionend' ,
506
- ( event : TransitionEvent ) => {
507
- this . _disposeBackdrop ( event . target as HTMLElement | null ) ;
508
- } ,
509
- ) ;
510
- } ) ;
511
-
512
- // If the backdrop doesn't have a transition, the `transitionend` event won't fire.
513
- // In this case we make it unclickable and we try to remove it after a delay.
514
- backdropToDetach . style . pointerEvents = 'none' ;
515
-
516
- // Run this outside the Angular zone because there's nothing that Angular cares about.
517
- // If it were to run inside the Angular zone, every test that used Overlay would have to be
518
- // either async or fakeAsync.
519
- this . _backdropTimeout = this . _ngZone . runOutsideAngular ( ( ) =>
520
- setTimeout ( ( ) => {
521
- this . _disposeBackdrop ( backdropToDetach ) ;
522
- } , 500 ) ,
523
- ) ;
524
480
}
525
481
526
482
/** Toggles a single CSS class or an array of classes on an element. */
@@ -565,36 +521,8 @@ export class OverlayRef implements PortalOutlet {
565
521
/** Disposes of a scroll strategy. */
566
522
private _disposeScrollStrategy ( ) {
567
523
const scrollStrategy = this . _scrollStrategy ;
568
-
569
- if ( scrollStrategy ) {
570
- scrollStrategy . disable ( ) ;
571
-
572
- if ( scrollStrategy . detach ) {
573
- scrollStrategy . detach ( ) ;
574
- }
575
- }
576
- }
577
-
578
- /** Removes a backdrop element from the DOM. */
579
- private _disposeBackdrop ( backdrop : HTMLElement | null ) {
580
- this . _cleanupBackdropClick ?.( ) ;
581
- this . _cleanupBackdropTransitionEnd ?.( ) ;
582
-
583
- if ( backdrop ) {
584
- backdrop . remove ( ) ;
585
-
586
- // It is possible that a new portal has been attached to this overlay since we started
587
- // removing the backdrop. If that is the case, only clear the backdrop reference if it
588
- // is still the same instance that we started to remove.
589
- if ( this . _backdropElement === backdrop ) {
590
- this . _backdropElement = null ;
591
- }
592
- }
593
-
594
- if ( this . _backdropTimeout ) {
595
- clearTimeout ( this . _backdropTimeout ) ;
596
- this . _backdropTimeout = undefined ;
597
- }
524
+ scrollStrategy ?. disable ( ) ;
525
+ scrollStrategy ?. detach ?.( ) ;
598
526
}
599
527
}
600
528
0 commit comments