UNPKG

typewriter-editor

Version:

A rich text editor using the Delta format with decorations and rendered with a tiny virtual dom

67 lines (66 loc) 2.76 kB
import { Editor } from '../Editor'; import { getIndexFromNodeAndOffset, getNodesForRange } from './position'; /** * Get the selection range from the current browser selection */ export function getSelection(editor) { const { root } = editor; const current = editor.doc.selection; if (!root.ownerDocument) return null; const selection = root.ownerDocument.getSelection(); const { lines } = editor.typeset; if (selection == null || selection.anchorNode == null || selection.focusNode == null || !root.contains(selection.anchorNode)) { return null; } else { const anchorIndex = getIndexFromNodeAndOffset(editor, selection.anchorNode, selection.anchorOffset, current && current[0]); const isCollapsed = selection.anchorNode === selection.focusNode && selection.anchorOffset === selection.focusOffset; const isFrozen = lines.findByAttributes(editor.doc.getLineAt(anchorIndex)?.attributes, true).frozen; // selection.isCollapsed causes a re-layout on Chrome, manual detection does not. let focusIndex = isCollapsed ? anchorIndex : getIndexFromNodeAndOffset(editor, selection.focusNode, selection.focusOffset, !isFrozen && current ? current[1] : null); return [anchorIndex, focusIndex]; } } /** * Set the current browser selection to the given selection range */ export function setSelection(editor, range) { const { root } = editor; if (!root.ownerDocument) return; const selection = root.ownerDocument.getSelection(); if (!selection) return; const hasFocus = selection.anchorNode && root.contains(selection.anchorNode) && document.activeElement !== document.body; if (range == null) { if (hasFocus) { selection.removeAllRanges(); if (root.classList.contains('focus')) root.classList.remove('focus'); } } else { const [anchorNode, anchorOffset, focusNode, focusOffset] = getNodesForRange(editor, range); const type = range[0] === range[1] ? 'Caret' : 'Range'; if (anchorNode && focusNode) { if (selection.anchorNode !== anchorNode || selection.anchorOffset !== anchorOffset || selection.focusNode !== focusNode || selection.focusOffset !== focusOffset || selection.type !== type) { selection.setBaseAndExtent(anchorNode, anchorOffset, focusNode, focusOffset); } } if (!hasFocus) root.focus(); if (!root.classList.contains('focus')) root.classList.add('focus'); } root.dispatchEvent(new Event('select', { bubbles: true })); }