Skip to content

Commit 46f5ec1

Browse files
committed
use overlay for clipping instead of trigger
1 parent 8c62fb2 commit 46f5ec1

File tree

5 files changed

+25
-13
lines changed

5 files changed

+25
-13
lines changed

src/lib/core/overlay/position/connected-position-strategy.ts

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ export class ConnectedPositionStrategy implements PositionStrategy {
3535
private _offsetY: number = 0;
3636

3737
/** The Scrollable containers that may cause the overlay's connectedTo element to be clipped */
38-
private scrollables: Scrollable[];
38+
private scrollables: Scrollable[] = [];
3939

4040
/** Whether the we're dealing with an RTL context */
4141
get _isRtl() {
@@ -102,7 +102,7 @@ export class ConnectedPositionStrategy implements PositionStrategy {
102102
// If the overlay in the calculated position fits on-screen, put it there and we're done.
103103
if (overlayPoint.fitsInViewport) {
104104
this._setElementPosition(element, overlayPoint);
105-
const isClipped = this.isConnectedToElementClipped();
105+
const isClipped = this.isOverlayElementClipped(element);
106106
this._onPositionChange.next(new ConnectedOverlayPositionChange(pos, isClipped));
107107
return Promise.resolve(null);
108108
} else if (!fallbackPoint || fallbackPoint.visibleArea < overlayPoint.visibleArea) {
@@ -243,6 +243,21 @@ export class ConnectedPositionStrategy implements PositionStrategy {
243243
return {x, y, fitsInViewport, visibleArea};
244244
}
245245

246+
/** Whether the overlay element is clipped out of view of one of the scrollable containers. */
247+
private isOverlayElementClipped(element: HTMLElement): boolean {
248+
const elementBounds = this._getElementBounds(element);
249+
return this.scrollables.some((scrollable: Scrollable) => {
250+
const scrollingContainerBounds = this._getElementBounds(scrollable.getElementRef().nativeElement);
251+
252+
const clippedAbove = elementBounds.top < scrollingContainerBounds.top;
253+
const clippedBelow = elementBounds.bottom > scrollingContainerBounds.bottom;
254+
const clippedLeft = elementBounds.left < scrollingContainerBounds.left;
255+
const clippedRight = elementBounds.right > scrollingContainerBounds.right;
256+
257+
return clippedAbove || clippedBelow || clippedLeft || clippedRight;
258+
});
259+
}
260+
246261
/**
247262
* Physically positions the overlay element to the given coordinate.
248263
* @param element
@@ -253,8 +268,8 @@ export class ConnectedPositionStrategy implements PositionStrategy {
253268
element.style.top = overlayPoint.y + 'px';
254269
}
255270

256-
private _getElementBounds(element: ElementRef): ElementBoundingPositions {
257-
const boundingClientRect = element.nativeElement.getBoundingClientRect();
271+
private _getElementBounds(element: HTMLElement): ElementBoundingPositions {
272+
const boundingClientRect = element.getBoundingClientRect();
258273
return {
259274
top: boundingClientRect.top,
260275
right: boundingClientRect.left + boundingClientRect.width,

src/lib/core/overlay/position/connected-position.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,5 @@ export class ConnectionPositionPair {
3434

3535
/** The change event emitted by the strategy when a fallback position is used. */
3636
export class ConnectedOverlayPositionChange {
37-
constructor(public connectionPair: ConnectionPositionPair,
38-
public isConnectedToElementClipped: boolean) {}
37+
constructor(public connectionPair: ConnectionPositionPair, public isClipped: boolean) {}
3938
}

src/lib/core/overlay/scroll/scroll-dispatcher.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ export class ScrollDispatcher {
5555
}
5656

5757
/** Returns all registered Scrollables that contain the provided element. */
58-
getScrollableContainers(elementRef: ElementRef): Scrollable[] {
58+
getScrollContainers(elementRef: ElementRef): Scrollable[] {
5959
const scrollingContainers: Scrollable[] = [];
6060

6161
this.scrollableReferences.forEach((subscription: Subscription, scrollable: Scrollable) => {

src/lib/tooltip/tooltip.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -182,13 +182,10 @@ export class MdTooltip implements OnInit, OnDestroy {
182182
let position = this._getOverlayPosition();
183183

184184
// Create connected strategy that listens for scroll events to reposition. After position
185-
// changes occur, check if the scrolling trigger has been clipped and close the tooltip.
185+
// changes occur and the overlay is clipped then close the tooltip.
186186
let strategy = this._overlay.position().connectedTo(this._elementRef, origin, position);
187-
strategy.withScrollableContainers(
188-
this._scrollDispatcher.getScrollableContainers(this._elementRef));
189-
strategy.onPositionChange.subscribe(change => {
190-
if (change.isConnectedToElementClipped) { this.hide(0); }
191-
});
187+
strategy.withScrollableContainers(this._scrollDispatcher.getScrollContainers(this._elementRef));
188+
strategy.onPositionChange.subscribe(change => { if (change.isClipped) { this.hide(0); } });
192189

193190
let config = new OverlayState();
194191
config.positionStrategy = strategy;

tools/gulp/tasks/components.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ task(':build:components:rollup', () => {
8080
'rxjs/add/operator/finally': 'Rx.Observable.prototype',
8181
'rxjs/add/operator/catch': 'Rx.Observable.prototype',
8282
'rxjs/add/operator/first': 'Rx.Observable.prototype',
83+
'rxjs/add/operator/combineLatest': 'Rx.Observable.prototype',
8384
'rxjs/Observable': 'Rx'
8485
};
8586

0 commit comments

Comments
 (0)