in packages/attribute-slicer/src/lib/VirtualList.ts [64:120]
private renderChunkDebounced: (
element: BaseSelection,
idx: number,
) => void = lodashDebounce(
(element: BaseSelection, idx: number) => this.renderChunk(element, idx),
50,
);
private generatorFn?: (idx: number) => HTMLElement;
private afterRender?: () => unknown;
constructor(config: IConfiguration) {
const width: string = (config && `${config.w}px`) || "100%";
const height: string = (config && `${config.h}px`) || "100%";
this.itemHeight = config.itemHeight;
this.listContainer = create("div").classed("list-display", true);
this.scroller = VirtualList.createScroller(0);
this.container = VirtualList.createContainer(width, height);
this.container.append(() => this.listContainer.node());
this.container.append(() => this.scroller.node());
this.generatorFn = config.generatorFn;
this.afterRender = config.afterRender;
// As soon as scrolling has stopped, this interval asynchronouslyremoves all
// the nodes that are not used anymore
const cleanNodes = () => {
if (!this.destroyed) {
if (Date.now() - this.lastScrolled > 100) {
const badNodes = this.container.selectAll("[data-rm]");
if (badNodes.size()) {
badNodes.remove();
}
}
this.cleanTimeout = setTimeout(cleanNodes, 300);
}
};
this.cleanTimeout = setTimeout(cleanNodes, 300);
this.container.on("scroll.virtual-list", () => {
const scrollPos: number = d3Selection.event.target[this.scrollProp]; // Triggers reflow
if (
!this.lastRepaintPos ||
Math.abs(scrollPos - this.lastRepaintPos) > this.maxBuffer
) {
const first: number =
Math.floor(scrollPos / this.itemHeight) - this.screenItemsLen;
this.renderChunk(this.listContainer, first < 0 ? 0 : first);
this.lastRepaintPos = scrollPos;
}
this.lastScrolled = Date.now();
if (d3Selection.event.preventDefault) {
d3Selection.event.preventDefault();
}
});
}