refactor(ScrollAnchor): pixel-accurate anchor and rename module#757
Merged
lcottercertinia merged 4 commits intoMay 9, 2026
Merged
Conversation
Rename MiddleRowFocus → ScrollAnchor (file, class, module name, table option) to better reflect its role. Replace the async re-center (scrollToRow().then + setTimeout(scrollIntoView)) with a synchronous, pixel-accurate restore in renderComplete: capture the anchor row's offsetTop relative to holder.scrollTop, then on restore set scrollTop = rowEl.offsetTop - capturedOffset in the same JS turn so the browser paints the corrected position directly — no visible flash. Use Tabulator's private _virtualRenderFill to pull the anchor row into the vDom window when it has been scrolled out, but skip the refill when the row element is already connected. Fall back to nearest-active-by-timestamp when the original anchor row has been filtered or collapsed away.
- Capture anchor offset via row.offsetTop - holder.scrollTop instead of paired getBoundingClientRect calls to avoid forced layout reads on every render-start. - Skip _virtualRenderFill when the anchor row's element is already connected to the DOM — only refill when the row was scrolled out of the vDom window. - Thread displayRows through _findClosestActive so the recursive binary search reuses one getDisplayRows() call instead of refetching at every tree level. - Extract _isRowActive helper to dedupe the displayRows.indexOf(_getSelf()) pattern across four call sites.
…allback Replaces the timestamp-keyed binary search (`_findClosestActive` / `_findClosestActiveSibling`) used when the captured anchor row is no longer in the post-render display set. The previous logic depended on `originalData.timestamp` from the call-tree row shape, coupling the module to apex-log-parser and making it unusable on other Tabulator tables. The replacement in `_resolveAnchorRow` uses only public Tabulator APIs: - Collapse case: walk up `getTreeParent()` to the nearest displayed ancestor. Matches the previous "anchor lands on the parent" feel for the call-tree views via the same tree relationship. - Filter case: capture the anchor row's index in `getDisplayRows()` pre-render; on restore, use the row at that index in the post-render display set, clamped. Replaces "nearest by timestamp" (only meaningful in time-ordered tables) with "same position in the list" (natural in any sort order). - If neither leg yields a row, return null and the restore is a no-op.
lcottercertinia
previously approved these changes
May 9, 2026
The merge-base changed after approval.
lcottercertinia
approved these changes
May 9, 2026
lcottercertinia
approved these changes
May 9, 2026
lcottercertinia
previously approved these changes
May 9, 2026
The merge-base changed after approval.
lcottercertinia
approved these changes
May 9, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
📝 PR Overview
Improvement on top of #756. Three changes layered:
MiddleRowFocus→ScrollAnchorto reflect the broader role.🛠️ Changes made
Pixel-accurate anchoring
offsetTop - scrollTop) and restorescrollTopsynchronously inrenderCompleteso the row sits at exactly the same pixel — eliminates the post-render flash._virtualRenderFill(same hookscrollToRowuses) before readingoffsetTop.scrollToRow+setTimeout+scrollIntoViewchain with a single synchronousscrollTopwrite.offsetTopinstead of pairedgetBoundingClientRectcalls to avoid forcing extra layout reads on the hot path.Rename
MiddleRowFocus→ScrollAnchor(module name, file, table optionmiddleRowFocus→scrollAnchor, tests, and call sites inAggregatedTable,BottomUpTable,TableShared,TimeOrderTable).Data-agnostic fallback (when the captured anchor row is no longer in the post-render display set)
apex-log-parserLogEventimport and the timestamp-keyed binary search (_findClosestActive/_findClosestActiveSibling, ~100 lines)._resolveAnchorRowwith two legs using only public Tabulator APIs:getTreeParent()to the nearest displayed ancestor. Matches the previous "anchor lands on the parent" feel for the call-tree views.getDisplayRows()pre-render; on restore, use the row at that (clamped) index. Replaces "nearest by timestamp" (only meaningful in time-ordered tables) with "same position in the list" (natural in any sort order).Tests added for offset capture, synchronous pixel-accurate restore, both fallback legs, and the exhausted case.
🧩 Type of change (check all applicable)
📷 Screenshots / gifs / video [optional]
n/a
🔗 Related Issues
related #756
✅ Tests added?
📚 Docs updated?
Anything else we need to know? [optional]
Until #756 lands, the diff against `main` here will include #756's commit too. After #756 merges, the diff will collapse to this PR's three refactor commits.