Skip to content

Commit a6a26d0

Browse files
committed
web: pass saved widths to makeResizableHeaders to skip the measuring reflow
makeResizableHeaders now takes an optional widths array; when given (e.g. widths saved from the previous render) it applies them directly instead of resetting to auto layout and reading offsetWidth, avoiding a forced reflow on every timing table re-render. Signed-off-by: Matt Liberty <mliberty@precisioninno.com>
1 parent 92f8388 commit a6a26d0

2 files changed

Lines changed: 20 additions & 24 deletions

File tree

src/web/src/timing-widget.js

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -367,14 +367,9 @@ export class TimingWidget {
367367

368368
this._pathTable.appendChild(tbody);
369369

370-
// Install resize grips, then restore previous widths if available.
371-
makeResizableHeaders(this._pathTable);
372-
if (savedWidths.length > 0 && savedWidths[0]) {
373-
const newHeaders = this._pathTable.querySelectorAll('thead th');
374-
newHeaders.forEach((th, i) => {
375-
if (i < savedWidths.length) th.style.width = savedWidths[i];
376-
});
377-
}
370+
// Install resize grips, reusing any previously saved widths to
371+
// avoid a measuring reflow.
372+
makeResizableHeaders(this._pathTable, savedWidths);
378373
}
379374

380375
_selectDetailRow(idx) {
@@ -449,14 +444,10 @@ export class TimingWidget {
449444
});
450445
this._detailTable.appendChild(tbody);
451446

452-
// Install resize grips, then restore previous widths if available.
453-
makeResizableHeaders(this._detailTable);
454-
if (savedWidths.length > 0 && savedWidths[0]) {
455-
const newHeaders = this._detailTable.querySelectorAll('thead th');
456-
newHeaders.forEach((th, i) => {
457-
if (i < savedWidths.length) th.style.width = savedWidths[i];
458-
});
459-
} else {
447+
// Install resize grips, reusing any previously saved widths to
448+
// avoid a measuring reflow.
449+
makeResizableHeaders(this._detailTable, savedWidths);
450+
if (!savedWidths[0]) {
460451
// Pin column: set initial width to 30 characters
461452
const pinTh = this._detailTable.querySelector('thead th');
462453
if (pinTh) {

src/web/src/ui-utils.js

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,20 @@ export function isStaticMode(app) {
1010
}
1111

1212
// Make table column headers resizable by dragging.
13-
export function makeResizableHeaders(table) {
14-
// Reset to auto layout so browser computes natural column widths
15-
table.style.tableLayout = 'auto';
13+
// widths is an optional array of CSS width strings (e.g. saved from a
14+
// previous render); when given, it is applied directly instead of
15+
// measuring natural widths, avoiding a forced reflow.
16+
export function makeResizableHeaders(table, widths) {
1617
const headers = table.querySelectorAll('thead th');
17-
headers.forEach((th) => th.style.width = '');
18-
// Force reflow to get natural widths
19-
const widths = Array.from(headers, (th) => th.offsetWidth);
20-
// Now lock in widths and switch to fixed layout
21-
headers.forEach((th, i) => th.style.width = widths[i] + 'px');
18+
if (!widths || !widths[0]) {
19+
// Reset to auto layout so browser computes natural column widths;
20+
// reading offsetWidth forces a reflow.
21+
table.style.tableLayout = 'auto';
22+
headers.forEach((th) => th.style.width = '');
23+
widths = Array.from(headers, (th) => th.offsetWidth + 'px');
24+
}
25+
// Lock in widths and switch to fixed layout
26+
headers.forEach((th, i) => th.style.width = widths[i] || '');
2227
table.style.tableLayout = 'fixed';
2328

2429
headers.forEach((th, idx) => {

0 commit comments

Comments
 (0)