diff --git a/src/vaadin-date-picker-overlay-content.html b/src/vaadin-date-picker-overlay-content.html index ab80632f..a4845477 100644 --- a/src/vaadin-date-picker-overlay-content.html +++ b/src/vaadin-date-picker-overlay-content.html @@ -384,18 +384,22 @@ /** * Scrolls the month and year scrollers enough to reveal the given date. */ - revealDate(date) { + revealDate(date, animate = true) { if (date) { - var diff = this._differenceInMonths(date, this._originDate); - var scrolledAboveViewport = this.$.monthScroller.position > diff; + const diff = this._differenceInMonths(date, this._originDate); + const scrolledAboveViewport = this.$.monthScroller.position > diff; - var visibleItems = this.$.monthScroller.clientHeight / this.$.monthScroller.itemHeight; - var scrolledBelowViewport = this.$.monthScroller.position + visibleItems - 1 < diff; + const visibleArea = Math.max( + this.$.monthScroller.itemHeight, + this.$.monthScroller.clientHeight - this.$.monthScroller.bufferOffset * 2 + ); + const visibleItems = visibleArea / this.$.monthScroller.itemHeight; + const scrolledBelowViewport = this.$.monthScroller.position + visibleItems - 1 < diff; if (scrolledAboveViewport) { - this._scrollToPosition(diff, true); + this._scrollToPosition(diff, animate); } else if (scrolledBelowViewport) { - this._scrollToPosition(diff - visibleItems + 1, true); + this._scrollToPosition(diff - visibleItems + 1, animate); } } } diff --git a/src/vaadin-infinite-scroller.html b/src/vaadin-infinite-scroller.html index e7d54c93..04266046 100644 --- a/src/vaadin-infinite-scroller.html +++ b/src/vaadin-infinite-scroller.html @@ -189,9 +189,9 @@ } // Check if we scrolled enough to translate the buffer positions. - var bufferOffset = this.root.querySelector('.buffer').offsetTop; - var upperThresholdReached = scrollTop > this._buffers[1].translateY + this.itemHeight + bufferOffset; - var lowerThresholdReached = scrollTop < this._buffers[0].translateY + this.itemHeight + bufferOffset; + const offset = this.itemHeight + this.bufferOffset; + const upperThresholdReached = scrollTop > this._buffers[1].translateY + offset; + const lowerThresholdReached = scrollTop < this._buffers[0].translateY + offset; if (upperThresholdReached || lowerThresholdReached) { this._translateBuffer(lowerThresholdReached); @@ -243,6 +243,13 @@ } + /** + * @return {number} + */ + get bufferOffset() { + return this._buffers[0].offsetTop; + } + /** * @private */ diff --git a/test/overlay.html b/test/overlay.html index 4a282da1..94100ff3 100644 --- a/test/overlay.html +++ b/test/overlay.html @@ -368,7 +368,7 @@ function touchstart(node) { const event = new CustomEvent('touchstart', {bubbles: true, cancelable: true}); - + const nodeRect = node.getBoundingClientRect(); const clientX = nodeRect.left; const clientY = nodeRect.top; @@ -382,9 +382,9 @@ const dialogOverlay = dialog.$.overlay; const datePicker = dialog.$.overlay.querySelector('vaadin-date-picker'); const datePickerOverlay = datePicker.$.overlay; - + datePicker.opened = true; - + datePicker.dispatchEvent(new CustomEvent('mousedown', {bubbles: true, composed: true})); requestAnimationFrame(() => { expect(datePickerOverlay._last).to.be.true; @@ -407,6 +407,106 @@ }); }); }); + + describe('revealDate', () => { + let overlay, monthScroller; + + function fixtureOverlayContent({monthScrollerItems, monthScrollerOffset}, done) { + overlay = fixture('overlay'); + monthScroller = overlay.$.monthScroller; + monthScroller.style.setProperty('--vaadin-infinite-scroller-buffer-offset', monthScrollerOffset); + monthScroller.updateStyles({'--vaadin-infinite-scroller-buffer-offset': monthScrollerOffset}); + monthScroller.style.height = `${270 * monthScrollerItems}px`; + overlay.i18n = getDefaultI18n(); + overlay.$.monthScroller.bufferSize = 3; + overlay.$.yearScroller.bufferSize = 3; + overlay.initialPosition = new Date(2021, 1, 1); + setTimeout(() => { + Polymer.RenderStatus.afterNextRender(overlay, done); + }, 1); + } + + describe('height(visible area) < height(item)', () => { + beforeEach((done) => { + fixtureOverlayContent({ + monthScrollerItems: 0.5, + monthScrollerOffset: 0 + }, done); + }); + + it('should scroll when the month is above the visible area', () => { + const position = monthScroller.position; + overlay.revealDate(new Date(2021, 0, 1), false); + expect(monthScroller.position).to.equal(position - 1); + }); + + it('should not scroll when the month is the same', () => { + const position = monthScroller.position; + overlay.revealDate(new Date(2021, 1, 10), false); + expect(monthScroller.position).to.equal(position); + }); + + it('should scroll when the month is below the visible area', () => { + const position = monthScroller.position; + overlay.revealDate(new Date(2021, 2, 1), false); + expect(monthScroller.position).to.equal(position + 1); + }); + }); + + describe('height(visible area) > height(item)', () => { + beforeEach((done) => { + fixtureOverlayContent({ + monthScrollerItems: 2, + monthScrollerOffset: 0 + }, done); + }); + + it('should scroll when the month is above the visible area', () => { + const position = monthScroller.position; + overlay.revealDate(new Date(2021, 0, 1), false); + expect(monthScroller.position).to.equal(position - 1); + }); + + it('should not scroll when the month is within the visible area', () => { + const position = monthScroller.position; + overlay.revealDate(new Date(2021, 2, 1), false); + expect(monthScroller.position).to.equal(position); + }); + + it('should scroll when the month is below the visible area', () => { + const position = monthScroller.position; + overlay.revealDate(new Date(2021, 3, 1), false); + expect(monthScroller.position).to.equal(position + 1); + }); + }); + + describe('offset', () => { + beforeEach((done) => { + fixtureOverlayContent({ + monthScrollerItems: 3, + monthScrollerOffset: '10%' + }, done); + }); + + it('should scroll when the month is above the visible area', () => { + const position = monthScroller.position; + overlay.revealDate(new Date(2021, 0, 1), false); + expect(monthScroller.position).to.equal(position - 1 /* The top 10% offset is ensured by CSS */); + }); + + it('should not scroll when the month is within the visible area', () => { + const position = monthScroller.position; + overlay.revealDate(new Date(2021, 2, 1), false); + expect(monthScroller.position).to.equal(position); + }); + + it('should scroll when the month is below the visible area', () => { + const position = monthScroller.position; + overlay.revealDate(new Date(2021, 3, 1), false); + expect(monthScroller.position).to.equal(position + 0.6 /* The bottom 10% offset is ensured by JS */); + }); + }); + }); diff --git a/test/visual/screens/vaadin-date-picker/dropdown-lumo/week-numbers/chrome.png b/test/visual/screens/vaadin-date-picker/dropdown-lumo/week-numbers/chrome.png index b3776ebb..f1c2eb8c 100644 Binary files a/test/visual/screens/vaadin-date-picker/dropdown-lumo/week-numbers/chrome.png and b/test/visual/screens/vaadin-date-picker/dropdown-lumo/week-numbers/chrome.png differ