Skip to content

Commit

Permalink
fix: ensure focused month is visible when receiving focus (#3219) (#799)
Browse files Browse the repository at this point in the history
  • Loading branch information
vursen authored May 10, 2022
1 parent cbc59b1 commit 0829079
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 13 deletions.
18 changes: 11 additions & 7 deletions src/vaadin-date-picker-overlay-content.html
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
}
Expand Down
13 changes: 10 additions & 3 deletions src/vaadin-infinite-scroller.html
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -243,6 +243,13 @@

}

/**
* @return {number}
*/
get bufferOffset() {
return this._buffers[0].offsetTop;
}

/**
* @private
*/
Expand Down
106 changes: 103 additions & 3 deletions test/overlay.html
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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 */);
});
});
});
</script>

</body>
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 0829079

Please sign in to comment.