11import { PortalHost , Portal } from '../portal/portal' ;
22import { OverlayState } from './overlay-state' ;
3+ import { Observable } from 'rxjs/Observable' ;
4+ import { Subject } from 'rxjs/Subject' ;
5+
36
47/**
58 * Reference to an overlay that has been created with the Overlay service.
69 * Used to manipulate or dispose of said overlay.
710 */
811export class OverlayRef implements PortalHost {
12+ private _backdropElement : HTMLElement = null ;
13+ private _backdropClick : Subject < any > = new Subject ( ) ;
14+
915 constructor (
1016 private _portalHost : PortalHost ,
1117 private _pane : HTMLElement ,
1218 private _state : OverlayState ) { }
1319
1420 attach ( portal : Portal < any > ) : any {
21+ if ( this . _state . hasBackdrop ) {
22+ this . _attachBackdrop ( ) ;
23+ }
24+
1525 let attachResult = this . _portalHost . attach ( portal ) ;
1626 this . updatePosition ( ) ;
1727
1828 return attachResult ;
1929 }
2030
2131 detach ( ) : Promise < any > {
32+ this . _detatchBackdrop ( ) ;
2233 return this . _portalHost . detach ( ) ;
2334 }
2435
2536 dispose ( ) : void {
37+ this . _detatchBackdrop ( ) ;
2638 this . _portalHost . dispose ( ) ;
2739 }
2840
2941 hasAttached ( ) : boolean {
3042 return this . _portalHost . hasAttached ( ) ;
3143 }
3244
45+ backdropClick ( ) : Observable < void > {
46+ return this . _backdropClick . asObservable ( ) ;
47+ }
48+
3349 /** Gets the current state config of the overlay. */
3450 getState ( ) {
3551 return this . _state ;
@@ -42,5 +58,40 @@ export class OverlayRef implements PortalHost {
4258 }
4359 }
4460
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+ }
4697}
0 commit comments