mirror of
https://github.com/vector-im/element-web.git
synced 2024-11-17 14:05:04 +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};
|
return {caret: offset, text};
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSelectionOffsetAndText(editor, selectionNode, selectionOffset) {
|
function tryReduceSelectionToTextNode(selectionNode, selectionOffset) {
|
||||||
// sometimes selectionNode is an element, and then selectionOffset means
|
// if selectionNode is an element, the selected location comes after the selectionOffset-th child node,
|
||||||
// the index of a child element ... - 1 🤷
|
// which can point past any childNode, in which case, the end of selectionNode is selected.
|
||||||
if (selectionNode.nodeType === Node.ELEMENT_NODE && selectionOffset !== 0) {
|
// we try to simplify this to point at a text node with the offset being
|
||||||
selectionNode = selectionNode.childNodes[selectionOffset - 1];
|
// 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;
|
selectionOffset = selectionNode.textContent.length;
|
||||||
|
} else {
|
||||||
|
// this will select the last child node in the next iteration
|
||||||
|
selectionOffset = Number.MAX_SAFE_INTEGER;
|
||||||
}
|
}
|
||||||
const {text, offsetToNode} = getTextAndOffsetToNode(editor, selectionNode);
|
} else {
|
||||||
const offset = getCaret(selectionNode, offsetToNode, selectionOffset);
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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};
|
return {offset, text};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user