1
1
import { PortalHost , Portal } from '../portal/portal' ;
2
2
import { OverlayState } from './overlay-state' ;
3
+ import { Observable } from 'rxjs/Observable' ;
4
+ import { Subject } from 'rxjs/Subject' ;
5
+
3
6
4
7
/**
5
8
* Reference to an overlay that has been created with the Overlay service.
6
9
* Used to manipulate or dispose of said overlay.
7
10
*/
8
11
export class OverlayRef implements PortalHost {
12
+ private _backdropElement : HTMLElement = null ;
13
+ private _backdropClick : Subject < any > = new Subject ( ) ;
14
+
9
15
constructor (
10
16
private _portalHost : PortalHost ,
11
17
private _pane : HTMLElement ,
12
18
private _state : OverlayState ) { }
13
19
14
20
attach ( portal : Portal < any > ) : any {
21
+ if ( this . _state . hasBackdrop ) {
22
+ this . _attachBackdrop ( ) ;
23
+ }
24
+
15
25
let attachResult = this . _portalHost . attach ( portal ) ;
16
26
this . updatePosition ( ) ;
17
27
18
28
return attachResult ;
19
29
}
20
30
21
31
detach ( ) : Promise < any > {
32
+ this . _detatchBackdrop ( ) ;
22
33
return this . _portalHost . detach ( ) ;
23
34
}
24
35
25
36
dispose ( ) : void {
37
+ this . _detatchBackdrop ( ) ;
26
38
this . _portalHost . dispose ( ) ;
27
39
}
28
40
29
41
hasAttached ( ) : boolean {
30
42
return this . _portalHost . hasAttached ( ) ;
31
43
}
32
44
45
+ backdropClick ( ) : Observable < void > {
46
+ return this . _backdropClick . asObservable ( ) ;
47
+ }
48
+
33
49
/** Gets the current state config of the overlay. */
34
50
getState ( ) {
35
51
return this . _state ;
@@ -42,5 +58,40 @@ export class OverlayRef implements PortalHost {
42
58
}
43
59
}
44
60
45
- // TODO(jelbourn): add additional methods for manipulating the overlay.
61
+ /** Attaches a backdrop for this overlay. */
62
+ private _attachBackdrop ( ) {
63
+ this . _backdropElement = document . createElement ( 'div' ) ;
64
+ this . _backdropElement . classList . add ( 'md-overlay-backdrop' ) ;
65
+ this . _pane . parentElement . appendChild ( this . _backdropElement ) ;
66
+
67
+ // Forward backdrop clicks such that the consumer of the overlay can perform whatever
68
+ // action desired when such a click occurs (usually closing the overlay).
69
+ this . _backdropElement . addEventListener ( 'click' , ( ) => {
70
+ this . _backdropClick . next ( null ) ;
71
+ } ) ;
72
+
73
+ // Add class to fade-in the backdrop after one frame.
74
+ requestAnimationFrame ( ( ) => {
75
+ this . _backdropElement . classList . add ( 'md-overlay-backdrop-showing' ) ;
76
+ } ) ;
77
+ }
78
+
79
+ /** Detaches the backdrop (if any) associated with the overlay. */
80
+ private _detatchBackdrop ( ) : void {
81
+ let backdropToDetach = this . _backdropElement ;
82
+
83
+ if ( backdropToDetach ) {
84
+ backdropToDetach . classList . remove ( 'md-overlay-backdrop-showing' ) ;
85
+ backdropToDetach . addEventListener ( 'transitionend' , ( ) => {
86
+ backdropToDetach . parentNode . removeChild ( backdropToDetach ) ;
87
+
88
+ // It is possible that a new portal has been attached to this overlay since we started
89
+ // removing the backdrop. If that is the case, only clear the backdrop reference if it
90
+ // is still the same instance that we started to remove.
91
+ if ( this . _backdropElement == backdropToDetach ) {
92
+ this . _backdropElement = null ;
93
+ }
94
+ } ) ;
95
+ }
96
+ }
46
97
}
0 commit comments