@syncfusion/ej2-spreadsheet
Version:
Feature-rich JavaScript Spreadsheet (Excel) control with built-in support for selection, editing, formatting, importing and exporting to Excel
106 lines (88 loc) • 7.88 kB
Markdown
# Context Menu Module data flow
## What It Does
The Context Menu module provides the right-click menu for the Spreadsheet UI. It builds a contextual menu based on click target (cells, headers, sheet tabs, select-all), localizes items, validates actions (protection/readonly), dispatches commands via notifications, and exposes APIs to extend/modify menu items at runtime.
Primary implementation file: `src/spreadsheet/integrations/context-menu.ts`.
## Entry Points (UI)
**Class:** `ContextMenu`
- Created during module init; initializes a `ContextMenuComponent` instance attached to a generated `<ul>` with id `${parent.element.id}_contextmenu` and CSS `e-spreadsheet-contextmenu`.
- Listens to parent notifications/events: `addContextMenuItems`, `removeContextMenuItems`, `enableContextMenuItems`.
- Key handlers:
- `initContextMenu()` — construct DOM host and configure component callbacks (`select`, `beforeOpen`, `beforeClose`, `beforeItemRender`).
- `beforeOpenHandler(args)` — determine target area (`Content`, `ColumnHeader`, `RowHeader`, `Footer`, `SelectAll`), compute items via `getDataSource()`, and abort if menu should not open.
- `selectHandler(args)` — handle item selection by mapping item ids to notifications or internal actions (cut/copy/paste, insert/delete/move sheet, sort/filter, comments/notes, hyperlinks, protect, etc.).
- `beforeCloseHandler(args)` — fires `contextMenuBeforeClose` and handles ESC key focus.
- `addItemsHandler(args)`, `removeItemsHandler(args)`, `enableItemsHandler(args)` — runtime mutation APIs for the context menu.
- `destroy()` — detach handlers and destroy the component.
## ASCII Core Logic Flow
User right-click → browser event → `beforeOpenHandler()`
↓
Identify target area via DOM/notifications (`getRowIdxFromClientY`, `getColIdxFromClientX`) → `getDataSource(target)`
↓
Build localized `MenuItemModel[]` (clipboard, filter/sort, insert/delete, comments/notes, hyperlinks, sheet actions) → `contextMenuInstance.items = items` → open menu
↓
User selects item → `selectHandler()` validates (readonly/protection/etc.) → send workbook notifications (e.g. `cut`, `copy`, `paste`, `insertModel`, `removeSheetTab`, `hideSheet`, `updateSortCollection`)
↓
Target operation performed by other subsystems → potential `focus()`/UI updates and undo/redo handled by respective handlers
## Operations (functions & responsibilities)
- `initContextMenu()`
- Create `<ul>` host with id `${parent.element.id}_contextmenu` and append to `parent.element`.
- Instantiate `ContextMenuComponent` with callbacks.
- Ensure ARIA role `menu` and attach keyboard prevention handler.
- `beforeOpenHandler(args)`
- Determine whether menu can open by checking target element classes and z-index.
- Compute `target` using `getTarget()` (maps DOM element → Content/RowHeader/ColumnHeader/Footer/SelectAll).
- For header/footer targets, call `getRowIdxFromClientY`/`getColIdxFromClientX` notifications to resolve header vs content.
- Call `getDataSource(target, targetEle)` to build item list for the target area.
- Fire `cMenuBeforeOpen` notification and `contextMenuBeforeOpen` event for external customization.
- `getDataSource(target, targetEle)`
- Uses localization `L10n` and helper setters to build contextual items:
- `setClipboardData()` — Cut/Copy/Paste/PasteSpecial
- `setFilterItems()` / `setSortItems()` — filter and sort submenus
- `setCommentsMenu()` / `setNotesMenu()` — comment/note items based on cell state
- `setHyperLink()` — hyperlink options based on cell content
- `setInsertDeleteItems()` / `setHideShowItems()` — for headers, respecting `allowInsert`/`allowDelete` and hidden counts
- `setProtectSheetItems()` — footer sheet protect/unprotect
- `selectHandler(args)`
- Maps menu item id prefix `${parent.element.id}_cmenu` to concrete actions; performs validation (read-only cells via `isReadOnlyCells`, selection mode, protection) and sends notifications:
- Clipboard: `cut`, `copy`, `paste` (with type flags)
- Sheet actions: `insertModel`, `removeSheetTab`, `hideSheet`, `duplicateSheet`, `moveSheet`
- Sort/Filter: `updateSortCollection`, `getFilteredColumn`, etc.
- Notes/Comments: custom notifications for comment/note flows
- Hyperlinks: `insertHyperlink` / `editHyperlink` / `removeHyperlink` (via notification paths present in code)
- Some selections call library helpers (e.g., `duplicateSheet`, `moveSheet`) and call `focus(this.parent.element)` where appropriate.
- Runtime mutation API
- `addItemsHandler`, `removeItemsHandler`, `enableItemsHandler` are thin wrappers around `ContextMenuComponent` methods to allow dynamic extension by other modules.
- `destroy()`
- Removes event listeners, destroys `contextMenuInstance`, detaches the host `<ul>`, and clears references.
## Validation & Safety
- Readonly/protection checks: `selectHandler` inspects rows/columns and calls `isReadOnlyCells`; if action is not allowed it cancels and triggers `readonlyAlert` notify.
- Selection mode: respects `selectionSettings.mode === 'None'` to disable filter/insert options when appropriate.
- Hidden rows/cols: `beforeOpenHandler` and `setHideShowItems` use `hiddenCount()` to avoid invalid hide/unhide operations.
- UI gating: `beforeOpenHandler` cancels opening for targets outside supported areas.
- Keyboard accessibility: `beforeCloseHandler` handles `Esc` to refocus and `preventKeyNavigation` blocks arrow keys when keyboard navigation is disabled.
- Lifecycle: `destroy()` ensures event handlers and DOM nodes are cleaned up to avoid leaks.
## Desired Outputs
User-facing
- Contextual right-click menu tailored to the clicked area (Content, RowHeader, ColumnHeader, Footer, SelectAll).
- Localized labels and icons; nested menus for filter/sort and paste special.
- Dynamic enable/disable and insertion/removal of menu items by other modules.
- Correct focus behavior and keyboard handling (ESC to close and refocus).
System-level
- Events & Notifications (used by this module):
- Incoming: `addContextMenuItems`, `removeContextMenuItems`, `enableContextMenuItems` (for runtime mutation)
- Outgoing / used notifications in `selectHandler`: `cut`, `copy`, `paste`, `insertModel`, `removeSheetTab`, `hideSheet`, `updateSortCollection`, `getFilteredColumn`, `renameSheetTab`, `getRowIdxFromClientY`, `getColIdxFromClientX`, `readonlyAlert`, and others mapped to specific menu actions.
- Hooks for customization: `cMenuBeforeOpen` notification and `contextMenuBeforeOpen`, `contextMenuBeforeClose`, `contextMenuItemSelect` events.
- DOM and CSS hooks:
- Host element: `<ul id="${parent.element.id}_contextmenu">` with role `menu`.
- Component CSS class: `e-spreadsheet-contextmenu`.
- Item id prefix: `${parent.element.id}_cmenu`.
- Integration contracts:
- Consumer modules can add/remove/enable items via `addContextMenuItems`, `removeContextMenuItems`, `enableContextMenuItems` notifications.
- Actions are performed by notifying existing workbook services; this module does not perform heavy state changes itself (it delegates).
- Undo/Redo: operations triggered by menu items should integrate into the workbook action pipeline since underlying notifications (e.g., `insertModel`, `paste`) include `isAction`/undo hooks.
## Implementation Notes (short)
- Prefer building `MenuItemModel[]` via helper setters (`setClipboardData`, `setFilterItems`, `setSortItems`, etc.) to keep `beforeOpenHandler()` concise.
- Localize all visible labels using the `L10n` service.
- Keep validation checks (read-only, allowInsert/allowDelete, hiddenCount) in `selectHandler` and `beforeOpenHandler` to prevent invalid commands.
- Ensure `destroy()` cleans up `EventHandler` keyup listener and detaches the host `<ul>` to avoid leaks.
---