Skip to content

Commit 7f3b1bd

Browse files
committed
feat(overlay): add connected position strategy (#335)
1 parent dfe683b commit 7f3b1bd

18 files changed

+911
-63
lines changed

firebase.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,13 @@
99
"deploy",
1010
"typings"
1111
],
12+
"headers": [{
13+
"source": "*",
14+
"headers": [{
15+
"key": "Cache-Control",
16+
"value": "no-cache"
17+
}]
18+
}],
1219
"rewrites": [{
1320
"source": "/**/!(*.@(js|ts|html|css|json|svg|png|jpg|jpeg))",
1421
"destination": "/index.html"

src/core/overlay/overlay-ref.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,20 @@
11
import {PortalHost, Portal} from '../portal/portal';
2+
import {OverlayState} from './overlay-state';
23

34
/**
45
* Reference to an overlay that has been created with the Overlay service.
56
* Used to manipulate or dispose of said overlay.
67
*/
78
export class OverlayRef implements PortalHost {
8-
constructor(private _portalHost: PortalHost) { }
9+
constructor(
10+
private _portalHost: PortalHost,
11+
private _pane: HTMLElement,
12+
private _state: OverlayState) { }
913

1014
attach(portal: Portal<any>): Promise<any> {
11-
return this._portalHost.attach(portal);
15+
return this._portalHost.attach(portal).then(() => {
16+
this._updatePosition();
17+
});
1218
}
1319

1420
detach(): Promise<any> {
@@ -23,5 +29,12 @@ export class OverlayRef implements PortalHost {
2329
return this._portalHost.hasAttached();
2430
}
2531

32+
/** Updates the position of the overlay based on the position strategy. */
33+
private _updatePosition() {
34+
if (this._state.positionStrategy) {
35+
this._state.positionStrategy.apply(this._pane);
36+
}
37+
}
38+
2639
// TODO(jelbourn): add additional methods for manipulating the overlay.
2740
}

src/core/overlay/overlay.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,5 @@
1616
.md-overlay-pane {
1717
position: absolute;
1818
pointer-events: auto;
19+
box-sizing: border-box;
1920
}

src/core/overlay/overlay.spec.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ import {Overlay, OVERLAY_CONTAINER_TOKEN} from './overlay';
2020
import {OverlayRef} from './overlay-ref';
2121
import {OverlayState} from './overlay-state';
2222
import {PositionStrategy} from './position/position-strategy';
23+
import {OverlayPositionBuilder} from './position/overlay-position-builder';
24+
import {ViewportRuler} from './position/viewport-ruler';
2325

2426

2527
export function main() {
@@ -32,6 +34,8 @@ export function main() {
3234

3335
beforeEachProviders(() => [
3436
Overlay,
37+
OverlayPositionBuilder,
38+
ViewportRuler,
3539
provide(OVERLAY_CONTAINER_TOKEN, {useFactory: () => {
3640
overlayContainerElement = document.createElement('div');
3741
return overlayContainerElement;

src/core/overlay/overlay.ts

Lines changed: 19 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@ import {
33
OpaqueToken,
44
Inject,
55
Injectable,
6-
ElementRef
76
} from '@angular/core';
87
import {OverlayState} from './overlay-state';
98
import {DomPortalHost} from '../portal/dom-portal-host';
109
import {OverlayRef} from './overlay-ref';
11-
import {GlobalPositionStrategy} from './position/global-position-strategy';
12-
import {RelativePositionStrategy} from './position/relative-position-strategy';
10+
11+
import {OverlayPositionBuilder} from './position/overlay-position-builder';
12+
import {ViewportRuler} from './position/viewport-ruler';
1313

1414

1515
// Re-export overlay-related modules so they can be imported directly from here.
@@ -39,7 +39,8 @@ let defaultState = new OverlayState();
3939
export class Overlay {
4040
constructor(
4141
@Inject(OVERLAY_CONTAINER_TOKEN) private _overlayContainerElement: HTMLElement,
42-
private _dynamicComponentLoader: DynamicComponentLoader) {
42+
private _dynamicComponentLoader: DynamicComponentLoader,
43+
private _positionBuilder: OverlayPositionBuilder) {
4344
}
4445

4546
/**
@@ -48,44 +49,31 @@ export class Overlay {
4849
* @returns A reference to the created overlay.
4950
*/
5051
create(state: OverlayState = defaultState): Promise<OverlayRef> {
51-
return this._createPaneElement(state).then(pane => this._createOverlayRef(pane));
52+
return this._createPaneElement().then(pane => this._createOverlayRef(pane, state));
5253
}
5354

5455
/**
5556
* Returns a position builder that can be used, via fluent API,
5657
* to construct and configure a position strategy.
5758
*/
5859
position() {
59-
return POSITION_BUILDER;
60+
return this._positionBuilder;
6061
}
6162

6263
/**
63-
* Creates the DOM element for an overlay.
64-
* @param state State to apply to the created element.
64+
* Creates the DOM element for an overlay and appends it to the overlay container.
6565
* @returns Promise resolving to the created element.
6666
*/
67-
private _createPaneElement(state: OverlayState): Promise<HTMLElement> {
67+
private _createPaneElement(): Promise<HTMLElement> {
6868
var pane = document.createElement('div');
69-
pane.id = `md-overlay-${nextUniqueId++}`;
69+
pane.id = `md-overlay-${nextUniqueId++}`;
7070
pane.classList.add('md-overlay-pane');
7171

72-
this.applyState(pane, state);
7372
this._overlayContainerElement.appendChild(pane);
7473

7574
return Promise.resolve(pane);
7675
}
7776

78-
/**
79-
* Applies a given state to the given pane element.
80-
* @param pane The pane to modify.
81-
* @param state The state to apply.
82-
*/
83-
applyState(pane: HTMLElement, state: OverlayState) {
84-
if (state.positionStrategy != null) {
85-
state.positionStrategy.apply(pane);
86-
}
87-
}
88-
8977
/**
9078
* Create a DomPortalHost into which the overlay content can be loaded.
9179
* @param pane The DOM element to turn into a portal host.
@@ -100,26 +88,18 @@ export class Overlay {
10088
/**
10189
* Creates an OverlayRef for an overlay in the given DOM element.
10290
* @param pane DOM element for the overlay
91+
* @param state
10392
* @returns {OverlayRef}
10493
*/
105-
private _createOverlayRef(pane: HTMLElement): OverlayRef {
106-
return new OverlayRef(this._createPortalHost(pane));
94+
private _createOverlayRef(pane: HTMLElement, state: OverlayState): OverlayRef {
95+
return new OverlayRef(this._createPortalHost(pane), pane, state);
10796
}
10897
}
10998

11099

111-
/** Builder for overlay position strategy. */
112-
export class OverlayPositionBuilder {
113-
/** Creates a global position strategy. */
114-
global() {
115-
return new GlobalPositionStrategy();
116-
}
117-
118-
/** Creates a relative position strategy. */
119-
relativeTo(elementRef: ElementRef) {
120-
return new RelativePositionStrategy(elementRef);
121-
}
122-
}
123-
124-
// We only ever need one position builder.
125-
let POSITION_BUILDER: OverlayPositionBuilder = new OverlayPositionBuilder();
100+
/** Providers for Overlay and its related injectables. */
101+
export const OVERLAY_PROVIDERS = [
102+
ViewportRuler,
103+
OverlayPositionBuilder,
104+
Overlay,
105+
];

0 commit comments

Comments
 (0)