From 05721f11e1672170fb46c72c38843133ce6d93d6 Mon Sep 17 00:00:00 2001 From: crisbeto Date: Sat, 17 Mar 2018 13:33:46 +0100 Subject: [PATCH] fix(overlay): incorrect bounding box bottom position when page is scrolled and content is flowing upwards * Fixes the bounding box position and height being calculated incorrectly when the overlay's content is flowing upwards and the page has been scrolled down. * Fixes the "when scrolled" tests not scrolling the page down. --- ...exible-connected-position-strategy.spec.ts | 38 +++++++++++++++++-- .../flexible-connected-position-strategy.ts | 4 +- 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/src/cdk/overlay/position/flexible-connected-position-strategy.spec.ts b/src/cdk/overlay/position/flexible-connected-position-strategy.spec.ts index 5d1b625276a7..92fabd413b50 100644 --- a/src/cdk/overlay/position/flexible-connected-position-strategy.spec.ts +++ b/src/cdk/overlay/position/flexible-connected-position-strategy.spec.ts @@ -159,17 +159,15 @@ describe('FlexibleConnectedPositionStrategy', () => { // Scroll the page such that the origin element is roughly in the // center of the visible viewport (2500 - 1024/2, 2500 - 768/2). document.body.appendChild(veryLargeElement); - document.body.scrollTop = 2100; - document.body.scrollLeft = 2100; + window.scroll(2100, 2100); originElement.style.top = `${ORIGIN_TOP}px`; originElement.style.left = `${ORIGIN_LEFT}px`; }); afterEach(() => { + window.scroll(0, 0); document.body.removeChild(veryLargeElement); - document.body.scrollTop = 0; - document.body.scrollLeft = 0; }); // Preconditions are set, now just run the full set of simple position tests. @@ -1119,6 +1117,38 @@ describe('FlexibleConnectedPositionStrategy', () => { expect(Math.floor(overlayRect.height)).toBe(OVERLAY_HEIGHT); }); + it('should calculate the `bottom` value correctly with upward-flowing content ' + + 'and a scrolled page', () => { + const veryLargeElement = document.createElement('div'); + + originElement.style.left = '200px'; + originElement.style.top = `200px`; + + veryLargeElement.style.width = '100%'; + veryLargeElement.style.height = '2000px'; + document.body.appendChild(veryLargeElement); + window.scroll(0, 50); + + positionStrategy + .withFlexibleHeight() + .withPositions([{ + overlayY: 'bottom', + overlayX: 'start', + originY: 'bottom', + originX: 'start' + }]); + + attachOverlay({positionStrategy}); + + const overlayRect = overlayRef.overlayElement.getBoundingClientRect(); + const originRect = originElement.getBoundingClientRect(); + + expect(Math.floor(overlayRect.bottom)).toBe(Math.floor(originRect.bottom)); + + window.scroll(0, 0); + document.body.removeChild(veryLargeElement); + }); + }); describe('onPositionChange with scrollable view properties', () => { diff --git a/src/cdk/overlay/position/flexible-connected-position-strategy.ts b/src/cdk/overlay/position/flexible-connected-position-strategy.ts index 696cf6ce313e..8b17f2123ea9 100644 --- a/src/cdk/overlay/position/flexible-connected-position-strategy.ts +++ b/src/cdk/overlay/position/flexible-connected-position-strategy.ts @@ -557,8 +557,8 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy { height = viewport.bottom - origin.y; } else if (position.overlayY === 'bottom') { // Overlay is opening "upward" and thus is bound by the top viewport edge. - bottom = viewport.bottom - origin.y + this._viewportMargin; - height = origin.y - viewport.top; + bottom = viewport.height - origin.y + this._viewportMargin; + height = viewport.height - bottom; } else { // If neither top nor bottom, it means that the overlay // is vertically centered on the origin point.