Skip to content

Commit

Permalink
fix: manual virtual index adjustments
Browse files Browse the repository at this point in the history
  • Loading branch information
tomivirkki committed May 12, 2022
1 parent e2bd643 commit 90de528
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 0 deletions.
10 changes: 10 additions & 0 deletions packages/component-base/src/virtualizer-iron-list-adapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,16 @@ export class IronListAdapter {

super._scrollHandler();

if (this._scrollTop === 0) {
// When scrolled to start, make sure the index of the first element is 0
this._virtualStart = 0;
} else if (this._physicalSize > 0) {
// Before running _scrollHandler, update _virtualStart to workaround an iron-list issue.
// See https://github.com/vaadin/web-components/issues/1691
const reusables = this._getReusables(true);
this._virtualStart += reusables.indexes.length;
}

if (this.reorderElements) {
this.__scrollReorderDebouncer = Debouncer.debounce(
this.__scrollReorderDebouncer,
Expand Down
91 changes: 91 additions & 0 deletions packages/component-base/test/virtualizer-workarounds.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import { expect } from '@esm-bundle/chai';
import { fixtureSync, nextFrame } from '@vaadin/testing-helpers';
import { Virtualizer } from '@vaadin/component-base/src/virtualizer.js';

customElements.define(
'test-element',
class extends HTMLElement {
constructor() {
super();

const root = this.attachShadow({ mode: 'open' });
root.innerHTML = `
<style>
:host {
display: block;
height: 400px;
transform: translateZ(0);
overflow: auto;
}
#items > ::slotted(*) {
width: 100%;
}
</style>
<div id="items">
<slot></slot>
</div>`;

this.virtualizer = new Virtualizer({
createElements: this.__createElements,
updateElement: this.__updateElement,
elementsContainer: this,
scrollTarget: this,
scrollContainer: this.shadowRoot.querySelector('#items'),
});
}

__createElements(count) {
return [...Array(count)].map(() => document.createElement('div'));
}

__updateElement(el, index) {
el.textContent = `item ${index}`;
}
},
);

describe('virtualizer - workarounds', () => {
let element;

beforeEach(() => {
element = fixtureSync(`<test-element></test-element>`);
});

describe('with items', () => {
beforeEach(() => {
element.virtualizer.size = 100000;
});

it('should have an item at the bottom of the viewport after scrolling up', async () => {
// Scroll to end
element.virtualizer.scrollToIndex(100000);
await nextFrame();

// Scroll upwards in 1000px steps
for (let i = 0; i < 10; i++) {
await nextFrame();
element.scrollTop -= 1000;
}

// There should be an item at the bottom of the viewport
await nextFrame();
const listRect = element.getBoundingClientRect();
const lastVisibleElement = element.getRootNode().elementFromPoint(listRect.left, listRect.bottom - 1);
expect(lastVisibleElement.textContent).to.equal('item 99473');
});

it('should have 0 for the first visible index when scrolled to start', async () => {
// Scroll to start, taking a couple of steps on the way
const scrollPositions = [115000, 3500, 0];
for (let i = 0; i < scrollPositions.length; i++) {
element.scrollTop = scrollPositions[i];
await nextFrame();
}

// The index of the first visible item should be 0
expect(element.virtualizer.firstVisibleIndex).to.equal(0);
});
});
});

0 comments on commit 90de528

Please sign in to comment.