mirror of
https://github.com/vector-im/element-web.git
synced 2024-11-17 05:55:00 +08:00
improve algorithm to reduce selection to text node + charactar offset
this follows the documentation of {focus|anchor}{Offset|Node} better and was causing problems for creating ranges from the document selection when doing ctrl+A in firefox as the anchorNode/Offset was expressed as childNodes from the editor root.
This commit is contained in:
parent
4691108a16
commit
e0668e8517
@ -45,15 +45,47 @@ export function getCaretOffsetAndText(editor, sel) {
|
||||
return {caret: offset, text};
|
||||
}
|
||||
|
||||
function getSelectionOffsetAndText(editor, selectionNode, selectionOffset) {
|
||||
// sometimes selectionNode is an element, and then selectionOffset means
|
||||
// the index of a child element ... - 1 🤷
|
||||
if (selectionNode.nodeType === Node.ELEMENT_NODE && selectionOffset !== 0) {
|
||||
selectionNode = selectionNode.childNodes[selectionOffset - 1];
|
||||
selectionOffset = selectionNode.textContent.length;
|
||||
function tryReduceSelectionToTextNode(selectionNode, selectionOffset) {
|
||||
// if selectionNode is an element, the selected location comes after the selectionOffset-th child node,
|
||||
// which can point past any childNode, in which case, the end of selectionNode is selected.
|
||||
// we try to simplify this to point at a text node with the offset being
|
||||
// a character offset within the text node
|
||||
// Also see https://developer.mozilla.org/en-US/docs/Web/API/Selection
|
||||
while (selectionNode && selectionNode.nodeType === Node.ELEMENT_NODE) {
|
||||
const childNodeCount = selectionNode.childNodes.length;
|
||||
if (childNodeCount) {
|
||||
if (selectionOffset >= childNodeCount) {
|
||||
selectionNode = selectionNode.lastChild;
|
||||
if (selectionNode.nodeType === Node.TEXT_NODE) {
|
||||
selectionOffset = selectionNode.textContent.length;
|
||||
} else {
|
||||
// this will select the last child node in the next iteration
|
||||
selectionOffset = Number.MAX_SAFE_INTEGER;
|
||||
}
|
||||
} else {
|
||||
selectionNode = selectionNode.childNodes[selectionOffset];
|
||||
// this will select the first child node in the next iteration
|
||||
selectionOffset = 0;
|
||||
}
|
||||
} else {
|
||||
// here node won't be a text node,
|
||||
// but characterOffset should be 0,
|
||||
// this happens under some circumstances
|
||||
// when the editor is empty.
|
||||
// In this case characterOffset=0 is the right thing to do
|
||||
break;
|
||||
}
|
||||
}
|
||||
const {text, offsetToNode} = getTextAndOffsetToNode(editor, selectionNode);
|
||||
const offset = getCaret(selectionNode, offsetToNode, selectionOffset);
|
||||
return {
|
||||
node: selectionNode,
|
||||
characterOffset: selectionOffset,
|
||||
};
|
||||
}
|
||||
|
||||
function getSelectionOffsetAndText(editor, selectionNode, selectionOffset) {
|
||||
const {node, characterOffset} = tryReduceSelectionToTextNode(selectionNode, selectionOffset);
|
||||
const {text, offsetToNode} = getTextAndOffsetToNode(editor, node);
|
||||
const offset = getCaret(node, offsetToNode, characterOffset);
|
||||
return {offset, text};
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user