UNPKG

@syncfusion/ej2-spreadsheet

Version:

Feature-rich JavaScript Spreadsheet (Excel) control with built-in support for selection, editing, formatting, importing and exporting to Excel

88 lines (72 loc) 6.83 kB
# VirtualScroll Module data flow ## What It Does The VirtualScroll module enables large-sheet virtualization by mapping pixel scroll positions to logical row/column ranges, creating virtual track elements, and translating rendered content to simulate a full sheet while only rendering visible rows/columns. Two-layer architecture: **VirtualScroll (UI)** manages virtual DOM containers, translate offsets, and incremental refreshes; **Workbook/Render (Core)** provides size metrics and performs targeted re-rendering for requested ranges. ## Entry Points **VirtualScroll (UI Layer)** - `createVirtualElement(args: { top, left })` - creates `.e-virtualable` wrappers and virtual track elements, computes initial virtual sizes. - `initScroll()` / `setScrollCount(count, layout)` - initialize per-sheet virtual counts. - `onVerticalScroll(args: IScrollArgs)` / `onHorizontalScroll(args: IScrollArgs)` - respond to offset changes, update `viewport` indexes and request partial/full refreshes. - `updateScrollCount(idx, layout, threshold?)` - grow internal row/col counts when content extends. - `updateRowColCount(args)` - adjust virtual track sizes when rows/cols are inserted/deleted. - `updateVTrackHeight(args)` / `updateVTrackWidth(args)` - incrementally adjust virtual track sizes and translate offsets when an individual row/col size changes. - `translate(args)` - apply CSS transforms to `.e-virtualable`, rowHeader and colHeader to maintain visual alignment. - `updateColumnWidth(args)` - recompute content/column header widths and update scroll-track sizing. - `updateTranslate(args)` - adjust translateX/translateY on hide/show or render operations. - `addEventListener()` / `removeEventListener()` / `destroy()` - wire lifecycle events and cleanup. **Workbook / Render (Core Layer)** - `getRowsHeight(sheet, start, end, includeHidden?)` / `getColumnsWidth(sheet, start, end, includeHidden?)` - compute cumulative pixel sizes used for virtual track calculations. - `getRangeIndexes` / `getCellIndexes` / `getRangeAddress` - address helpers for refresh requests. - `skipHiddenIdx()` / `isHiddenCol()` - account for hidden rows/columns when mapping indexes. - `renderModule.refreshUI()` / `renderModule.refreshSheet()` - core re-render entry points for partial/full refreshes triggered by virtual scroll. - `sheetModule.getScrollSize()` - used to include scrollbar size in track calculations when not finite. - Notifications/events used: `beforeContentLoaded`, `beforeVirtualContentLoaded`, `virtualContentLoaded`, `updateTableWidth`, `onVerticalScroll`, `onHorizontalScroll`, `updateRowColCount`, `rowHeightChanged`, `colWidthChanged`, `updateTranslate`, `sheetCreated`, `sheetsDestroyed`, `deInitProperties`, `spreadsheetDestroyed`. ## Core Logic Flow ``` Initial load → beforeContentLoaded → createVirtualElement({top,left}) ↓ Compute virtual track sizes using `getRowsHeight`/`getColumnsWidth`, build `.e-virtualable` containers ↓ User scrolls → Scroll module computes pixel offsets → notifies `onVerticalScroll` / `onHorizontalScroll` ↓ VirtualScroll maps `cur.idx/size` → update viewport indexes and diffs → decide partial vs full refresh ↓ Call `renderModule.refreshUI` for RowPart/ColumnPart or full `refreshSheet`; call `translate()` to move rendered fragment ↓ On row/col size changes or hide/show → update virtual track via `updateVTrackHeight`/`updateVTrackWidth` and `updateTranslate` ↓ On structural changes (insert/delete/sheet changes) → `updateRowColCount` / `setScrollCount` adjust virtual counts and track metrics ``` ## Operations Handled 1. Virtual container creation: move actual `table` inside `.e-virtualable`, add virtual track elements for main, row-header, column-header and scroller. 2. Pixel-to-index mapping: translate scroll pixels into logical viewport indexes using cumulative heights/widths and hidden-index helpers. 3. Threshold-driven refresh: compare index diffs against thresholds and select `RowPart`/`ColumnPart` partial refresh vs full refresh. 4. Translate management: compute `translateX`/`translateY` to position the virtual fragment so visible cells align with scroll position. 5. Dynamic track updates: incrementally resize virtual tracks when rows/columns change size, or when row/col counts expand. 6. Finite vs infinite scroll: support `scrollSettings.isFinite` to cap virtual counts or grow them based on usedRange. 7. Frozen panes: consider `frozenRowCount` / `frozenColCount` and pane top-left offsets when computing start indexes and tracks. 8. Sheet lifecycle: handle sheet-created/destroyed events to keep per-sheet `scroll` metadata in sync. ## VirtualScroll Modes | Mode | Behavior | |------|----------| | Initial Virtualize | Wrap content in `.e-virtualable`, build virtual tracks for initial viewport. | | Incremental Refresh | Small scroll deltas → `RowPart`/`ColumnPart` refresh and adjust translate. | | Full Refresh | Large deltas or structural changes → `refreshSheet` to re-render entire visible fragment. | | Dynamic Growth | Content growth extends virtual counts → `updateScrollCount` increases internal row/col counts. | ## Validation & Safety - **Threshold tuning:** Uses parent `getThreshold('row'|'col')` to decide partial vs full refresh to balance performance and correctness. - **Hidden items:** Employ `skipHiddenIdx` and `hiddenCount` helpers to map logical indexes across hidden rows/columns accurately. - **Finite scrolling:** When `scrollSettings.isFinite` is false, the module grows `rowCount/colCount` to match used ranges; otherwise treats ends as bounds. - **DPR & rounding:** Pixel math uses cumulative helper functions; small 1px tolerances in other modules avoid jitter across devices. - **Frozen panes safety:** Carefully include frozen-row/col offsets in start-index calculations to prevent wrong fragments being removed/inserted. - **Event ordering:** Hooks into `beforeVirtualContentLoaded`/`virtualContentLoaded` to ensure translate and DOM swaps occur in a predictable lifecycle. - **Cleanup:** On `spreadsheetDestroyed` remove virtual elements and restore DOM to a clean state. ## Desired Outputs **User-Facing:** - Smooth, low-memory scrolling for large sheets with no visible repaint glitches. - Correct alignment of headers and main content when scrolling or resizing. - Responsive expansion when sheet used range grows. **System-Level:** - `.e-virtualable` wrappers and `.e-virtualtrack` elements accurately reflect virtualized extents. - `viewport` indexes updated and used to drive minimal re-render requests via `renderModule.refreshUI`. - `translateX`/`translateY` keep rendered fragment visually aligned with scrollbar positions. - Events emitted/handled: `virtualContentLoaded`, `updateTranslate`, `updateRowColCount`, and related scroll notifications.