Skip to content

Commit 18e53be

Browse files
committed
refactor: improve goToRow with promise-based flow and scroll fallback
Return a Promise from goToRow for async coordination. Use scrollIntoView as fallback after tabulator's scrollToRow to handle edge cases near the bottom of the grid. Check element connectivity in _isVisible and compare against tableholder bounds instead of window.
1 parent 0fd8cb1 commit 18e53be

1 file changed

Lines changed: 64 additions & 45 deletions

File tree

log-viewer/src/tabulator/module/RowNavigation.ts

Lines changed: 64 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -13,70 +13,89 @@ export class RowNavigation extends Module {
1313
this.registerTableFunction('goToRow', this.goToRow.bind(this));
1414
}
1515

16-
goToRow(row: RowComponent, opts: GoToRowOptions = { scrollIfVisible: true, focusRow: true }) {
17-
if (row) {
18-
const { focusRow } = opts;
16+
goToRow(
17+
row: RowComponent,
18+
opts: GoToRowOptions = { scrollIfVisible: true, focusRow: true },
19+
): Promise<void> {
20+
if (!row) {
21+
return Promise.resolve();
22+
}
1923

20-
const table = this.table;
21-
this.tableHolder ??= table.element.querySelector('.tabulator-tableholder') as HTMLElement;
24+
const { focusRow } = opts;
2225

23-
table.blockRedraw();
26+
const table = this.table;
27+
this.tableHolder ??= table.element.querySelector('.tabulator-tableholder') as HTMLElement;
2428

25-
const grp = row.getGroup();
26-
if (grp && !grp.isVisible()) {
27-
grp.show();
28-
}
29+
table.blockRedraw();
2930

30-
const rowsToExpand = [];
31-
//@ts-expect-error This is private to tabulator, but we have no other choice atm.
32-
let parent = row._getSelf().modules.dataTree ? row.getTreeParent() : false;
33-
while (parent) {
34-
if (!parent.isTreeExpanded()) {
35-
rowsToExpand.push(parent);
36-
}
37-
parent = parent.getTreeParent();
31+
const grp = row.getGroup();
32+
if (grp && !grp.isVisible()) {
33+
grp.show();
34+
}
35+
36+
const rowsToExpand = [];
37+
//@ts-expect-error This is private to tabulator, but we have no other choice atm.
38+
let parent = row._getSelf().modules.dataTree ? row.getTreeParent() : false;
39+
while (parent) {
40+
if (!parent.isTreeExpanded()) {
41+
rowsToExpand.push(parent);
3842
}
43+
parent = parent.getTreeParent();
44+
}
3945

40-
rowsToExpand.forEach((row) => {
41-
row.treeExpand();
42-
});
46+
for (const row of rowsToExpand) {
47+
row.treeExpand();
48+
}
4349

44-
table.getSelectedRows().forEach((rowToDeselect) => {
45-
rowToDeselect.deselect();
46-
});
47-
row.select();
48-
table.restoreRedraw();
50+
for (const row of table.getSelectedRows()) {
51+
row.deselect();
52+
}
4953

50-
if (focusRow) {
51-
this.tableHolder.focus();
52-
}
53-
if (row) {
54-
setTimeout(() => this._scrollToRow(row, opts));
55-
}
54+
row.select();
55+
table.restoreRedraw();
56+
57+
if (focusRow) {
58+
this.tableHolder.focus();
5659
}
60+
61+
return new Promise<void>((resolve) => {
62+
setTimeout(() => {
63+
this._scrollToRow(row, opts).then(resolve);
64+
});
65+
});
5766
}
5867

59-
_scrollToRow(row: RowComponent, opts: GoToRowOptions) {
68+
_scrollToRow(row: RowComponent, opts: GoToRowOptions): Promise<void> {
6069
const { scrollIfVisible, focusRow } = opts;
6170

62-
this.table.scrollToRow(row, 'center', scrollIfVisible).then(() => {
63-
setTimeout(() => {
64-
const elem = row.getElement();
71+
return this.table
72+
.scrollToRow(row, 'center', scrollIfVisible)
73+
.catch(() => {})
74+
.then(() => {
75+
return new Promise<void>((resolve) => {
76+
setTimeout(() => {
77+
const elem = row.getElement();
78+
79+
if (scrollIfVisible || !this._isVisible(elem)) {
80+
elem.scrollIntoView({ behavior: 'auto', block: 'center', inline: 'start' });
81+
}
6582

66-
if (scrollIfVisible || !this._isVisible(elem)) {
67-
// NOTE: work around because this.table.scrollToRow does not work correctly when the row is near the very bottom of the grid.
68-
elem.scrollIntoView({ behavior: 'auto', block: 'center', inline: 'start' });
69-
}
83+
if (focusRow) {
84+
elem.focus();
85+
}
7086

71-
if (focusRow) {
72-
elem.focus();
73-
}
87+
resolve();
88+
});
89+
});
7490
});
75-
});
7691
}
7792

7893
_isVisible(el: Element) {
94+
if (!this.tableHolder || !el.isConnected) {
95+
return false;
96+
}
97+
const holderRect = this.tableHolder.getBoundingClientRect();
7998
const rect = el.getBoundingClientRect();
80-
return rect.top >= 0 && rect.bottom <= window.innerHeight;
99+
return rect.top >= holderRect.top && rect.bottom <= holderRect.bottom;
81100
}
82101
}

0 commit comments

Comments
 (0)