ignore react comment nodes when locating/setting caret
This commit is contained in:
parent
6be6492cd2
commit
8f0074f824
1 changed files with 46 additions and 21 deletions
|
@ -26,7 +26,10 @@ export function getCaretOffset(editor) {
|
||||||
if (node === editor) {
|
if (node === editor) {
|
||||||
let offset = 0;
|
let offset = 0;
|
||||||
for (let i = 0; i < sel.focusOffset; ++i) {
|
for (let i = 0; i < sel.focusOffset; ++i) {
|
||||||
offset += editor.childNodes[i].textContent.length;
|
const node = editor.childNodes[i];
|
||||||
|
if (isVisibleNode(node)) {
|
||||||
|
offset += node.textContent.length;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return {offset, atNodeEnd: false};
|
return {offset, atNodeEnd: false};
|
||||||
}
|
}
|
||||||
|
@ -36,8 +39,10 @@ export function getCaretOffset(editor) {
|
||||||
// include all preceding siblings of the non-direct editor children
|
// include all preceding siblings of the non-direct editor children
|
||||||
while (node.previousSibling) {
|
while (node.previousSibling) {
|
||||||
node = node.previousSibling;
|
node = node.previousSibling;
|
||||||
|
if (isVisibleNode(node)) {
|
||||||
offset += node.textContent.length;
|
offset += node.textContent.length;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// then move up
|
// then move up
|
||||||
// I guess technically there could be preceding text nodes in the parents here as well,
|
// I guess technically there could be preceding text nodes in the parents here as well,
|
||||||
// but we're assuming there are no mixed text and element nodes
|
// but we're assuming there are no mixed text and element nodes
|
||||||
|
@ -48,8 +53,10 @@ export function getCaretOffset(editor) {
|
||||||
// now include the text length of all preceding direct editor children
|
// now include the text length of all preceding direct editor children
|
||||||
while (node.previousSibling) {
|
while (node.previousSibling) {
|
||||||
node = node.previousSibling;
|
node = node.previousSibling;
|
||||||
|
if (isVisibleNode(node)) {
|
||||||
offset += node.textContent.length;
|
offset += node.textContent.length;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// {
|
// {
|
||||||
// const {focusOffset, focusNode} = sel;
|
// const {focusOffset, focusNode} = sel;
|
||||||
// console.log("selection", {focusOffset, focusNode, position, atNodeEnd});
|
// console.log("selection", {focusOffset, focusNode, position, atNodeEnd});
|
||||||
|
@ -57,22 +64,40 @@ export function getCaretOffset(editor) {
|
||||||
return {offset, atNodeEnd};
|
return {offset, atNodeEnd};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isVisibleNode(node) {
|
||||||
|
return node.nodeType === Node.ELEMENT_NODE || node.nodeType === Node.TEXT_NODE;
|
||||||
|
}
|
||||||
|
|
||||||
|
function untilVisibleNode(node) {
|
||||||
|
// need to ignore comment nodes that react uses
|
||||||
|
while (node && !isVisibleNode(node)) {
|
||||||
|
node = node.nextSibling;
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
export function setCaretPosition(editor, caretPosition) {
|
export function setCaretPosition(editor, caretPosition) {
|
||||||
if (caretPosition) {
|
let node = untilVisibleNode(editor.firstChild);
|
||||||
let focusNode = editor.childNodes[caretPosition.index];
|
if (!node) {
|
||||||
if (!focusNode) {
|
node = editor;
|
||||||
focusNode = editor;
|
|
||||||
} else {
|
} else {
|
||||||
|
let {index} = caretPosition;
|
||||||
|
while (node && index) {
|
||||||
|
node = untilVisibleNode(node.nextSibling);
|
||||||
|
--index;
|
||||||
|
}
|
||||||
|
if (!node) {
|
||||||
|
node = editor;
|
||||||
|
} else if (node.nodeType === Node.ELEMENT_NODE) {
|
||||||
// make sure we have a text node
|
// make sure we have a text node
|
||||||
if (focusNode.nodeType === Node.ELEMENT_NODE) {
|
node = node.childNodes[0];
|
||||||
focusNode = focusNode.childNodes[0];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
console.log("setting caret", caretPosition, node);
|
||||||
const sel = document.getSelection();
|
const sel = document.getSelection();
|
||||||
sel.removeAllRanges();
|
sel.removeAllRanges();
|
||||||
const range = document.createRange();
|
const range = document.createRange();
|
||||||
range.setStart(focusNode, caretPosition.offset);
|
range.setStart(node, caretPosition.offset);
|
||||||
range.collapse(true);
|
range.collapse(true);
|
||||||
sel.addRange(range);
|
sel.addRange(range);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue