Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/js/core/row/Row.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ export default class Row extends CoreFeature{

deinitialize(){
this.initialized = false;
this.heightInitialized = false;
}

deinitializeHeight(){
Expand Down
56 changes: 56 additions & 0 deletions test/e2e/cell-height-recycle.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<!doctype html>
<html>
<head>
<meta charset="UTF-8" />
<title>Tabulator Virtual Cell Height Recycling Test</title>
<link rel="stylesheet" href="../../dist/css/tabulator.min.css" />
<script src="../../dist/js/tabulator.js"></script>
<style>
#test-table {
width: 500px;
}
.tabulator-cell {
white-space: normal !important;
}
</style>
</head>
<body>
<div id="test-table"></div>

<script>
document.addEventListener("DOMContentLoaded", () => {
const metricFields = Array.from(
{ length: 32 },
(_value, index) => `metric_${index + 1}`,
);
const data = Array.from({ length: 500 }, (_, index) => {
const row = {
id: index + 1,
name: `Row ${index + 1}`,
notes: `Notes for row ${index + 1}`,
};

metricFields.forEach((field, metricIndex) => {
row[field] = index * 100 + metricIndex;
});

return row;
});

window.testTable = new Tabulator("#test-table", {
data,
columns: [
{ title: "ID", field: "id", width: 120 },
{ title: "Name", field: "name", width: 200 },
{ title: "Notes", field: "notes", width: 600 },
...metricFields.map((field) => ({ title: field, field, width: 160 })),
],
height: "300px",
rowHeight: 43,
layout: "fitData",
renderHorizontal: "virtual",
});
});
</script>
</body>
</html>
57 changes: 57 additions & 0 deletions test/e2e/scroll-jump.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,63 @@ test.describe("Vertical scroll jumping with variable height rows (#3654)", () =>
});
});

test.describe("Cell heights after virtual row recycling", () => {
test.beforeEach(async ({ page }) => {
await page.goto(`file://${join(__dirname, "cell-height-recycle.html")}`);
await page.waitForSelector(".tabulator-row");
await page.locator(".tabulator-tableholder").hover();
});

test("normalizes cells recreated after an offscreen column refit", async ({
page,
}) => {
await scrollToBottom(page, 900);
await expect(
page
.locator('.tabulator-cell[tabulator-field="id"]')
.filter({ hasText: /^1$/ }),
).toHaveCount(0);

// A column refit makes the horizontal virtual renderer discard cells for
// rows outside its current vertical window.
await page.evaluate(() => window.testTable.getColumn("name").setWidth(1200));

// A direct jump takes the vertical renderer's full-fill path when it
// recreates the discarded cells.
await page.locator(".tabulator-tableholder").evaluate((holder) => {
holder.scrollTop = 0;
holder.dispatchEvent(new Event("scroll"));
});

await expect
.poll(() =>
page
.locator(".tabulator-row")
.first()
.locator(".tabulator-cell")
.first()
.textContent(),
)
.toBe("1");

const geometry = await page.locator(".tabulator-row").first().evaluate((row) => ({
rowHeight: row.getBoundingClientRect().height,
cells: [...row.querySelectorAll(".tabulator-cell")].map((cell) => ({
field: cell.getAttribute("tabulator-field"),
height: cell.getBoundingClientRect().height,
styledHeight: Number.parseFloat((cell as HTMLElement).style.height),
})),
}));

expect(geometry.rowHeight).toBe(43);
expect(geometry.cells.length).toBeGreaterThan(0);
for (const cell of geometry.cells) {
expect(cell.height, cell.field).toBe(geometry.rowHeight);
expect(cell.styledHeight, cell.field).toBe(geometry.rowHeight);
}
});
});

test.describe("Vertical scroll jumping with grouped variable height rows (#3654)", () => {
test.beforeEach(async ({ page }) => {
await page.goto(`file://${join(__dirname, "scroll-jump-group.html")}`);
Expand Down
14 changes: 14 additions & 0 deletions test/unit/core/row/Row.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import Row from "../../../../src/js/core/row/Row.js";

describe("Row", () => {
test("deinitialize invalidates the cached row height", () => {
const row = Object.create(Row.prototype);
row.initialized = true;
row.heightInitialized = true;

row.deinitialize();

expect(row.initialized).toBe(false);
expect(row.heightInitialized).toBe(false);
});
});