Skip to content

Commit e86755d

Browse files
committed
use overlay for clipping instead of trigger
1 parent 8be6a50 commit e86755d

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() {
@@ -106,7 +106,7 @@ export class ConnectedPositionStrategy implements PositionStrategy {
106106
// If the overlay in the calculated position fits on-screen, put it there and we're done.
107107
if (overlayPoint.fitsInViewport) {
108108
this._setElementPosition(element, overlayPoint);
109-
const isClipped = this.isConnectedToElementClipped();
109+
const isClipped = this.isOverlayElementClipped(element);
110110
this._onPositionChange.next(new ConnectedOverlayPositionChange(pos, isClipped));
111111
return Promise.resolve(null);
112112
} else if (!fallbackPoint || fallbackPoint.visibleArea < overlayPoint.visibleArea) {
@@ -262,6 +262,21 @@ export class ConnectedPositionStrategy implements PositionStrategy {
262262
return {x, y, fitsInViewport, visibleArea};
263263
}
264264

265+
/** Whether the overlay element is clipped out of view of one of the scrollable containers. */
266+
private isOverlayElementClipped(element: HTMLElement): boolean {
267+
const elementBounds = this._getElementBounds(element);
268+
return this.scrollables.some((scrollable: Scrollable) => {
269+
const scrollingContainerBounds = this._getElementBounds(scrollable.getElementRef().nativeElement);
270+
271+
const clippedAbove = elementBounds.top < scrollingContainerBounds.top;
272+
const clippedBelow = elementBounds.bottom > scrollingContainerBounds.bottom;
273+
const clippedLeft = elementBounds.left < scrollingContainerBounds.left;
274+
const clippedRight = elementBounds.right > scrollingContainerBounds.right;
275+
276+
return clippedAbove || clippedBelow || clippedLeft || clippedRight;
277+
});
278+
}
279+
265280
/**
266281
* Physically positions the overlay element to the given coordinate.
267282
* @param element
@@ -272,8 +287,8 @@ export class ConnectedPositionStrategy implements PositionStrategy {
272287
element.style.top = overlayPoint.y + 'px';
273288
}
274289

275-
private _getElementBounds(element: ElementRef): ElementBoundingPositions {
276-
const boundingClientRect = element.nativeElement.getBoundingClientRect();
290+
private _getElementBounds(element: HTMLElement): ElementBoundingPositions {
291+
const boundingClientRect = element.getBoundingClientRect();
277292
return {
278293
top: boundingClientRect.top,
279294
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
@@ -59,7 +59,7 @@ export class ScrollDispatcher {
5959
}
6060

6161
/** Returns all registered Scrollables that contain the provided element. */
62-
getScrollableContainers(elementRef: ElementRef): Scrollable[] {
62+
getScrollContainers(elementRef: ElementRef): Scrollable[] {
6363
const scrollingContainers: Scrollable[] = [];
6464

6565
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
@@ -180,13 +180,10 @@ export class MdTooltip implements OnInit, OnDestroy {
180180
let position = this._getOverlayPosition();
181181

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

191188
let config = new OverlayState();
192189
config.positionStrategy = strategy;

tools/gulp/tasks/components.ts

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

0 commit comments

Comments
 (0)