Чтобы получить и установить позицию каретки в контентном элементе, я пробовал код из этого ответа, но начальная и конечная позиции сбрасываются при переходе в различные текстовые узлы.
<div contenteditable>012345<br><br><br>9012345</div>
Итак, я изменил код из этого ответа (by @TimDown), но он все еще не совсем считает, что строка ломается правильно... В эта демонстрация, когда я нажимаю после 4
и три раза нажимаю стрелку вправо, я увижу отчет начала/конца как 5
, 6
, затем 8
. Или, используйте мышь, чтобы выбрать из 4
в первой строке и продолжить выбор вправо (см. Gif)
Вот код (demo, хотя он похож на него, jQuery не используется)
function getCaret(el) {
let start, end;
const range = document.getSelection().getRangeAt(0),
preSelectionRange = range.cloneRange(),
postSelectionRange = range.cloneRange();
preSelectionRange.selectNodeContents(el);
preSelectionRange.setEnd(range.startContainer, range.startOffset);
postSelectionRange.selectNodeContents(el);
postSelectionRange.setEnd(range.endContainer, range.endOffset);
start = preSelectionRange.toString().length;
end = start + range.toString().length;
// count <br> and adjust start & end
if (start > 0) {
var node,
i = el.children.length;
while (i--) {
node = el.children[i];
if (node.nodeType === 1 && node.nodeName === 'BR') {
start += preSelectionRange.intersectsNode(el.children[i]) ? 1 : 0;
end += postSelectionRange.intersectsNode(el.children[i]) ? 1 : 0;
}
}
}
return {start, end};
}
Функциональная модификация setCaret
работает корректно (в этом базовом контентном примере).
function setCaret(el, start, end) {
var node, i, nextCharIndex, sel,
charIndex = 0,
nodeStack = [el],
foundStart = false,
stop = false,
range = document.createRange();
range.setStart(el, 0);
range.collapse(true);
while (!stop && (node = nodeStack.pop())) {
// BR aren't counted, so we need to increase the index when one
// is encountered
if (node.nodeType === 1 && node.nodeName === 'BR') {
charIndex++;
} else if (node.nodeType === 3) {
nextCharIndex = charIndex + node.length;
if (!foundStart && start >= charIndex && start <= nextCharIndex) {
range.setStart(node, start - charIndex);
foundStart = true;
}
if (foundStart && end >= charIndex && end <= nextCharIndex) {
range.setEnd(node, end - charIndex);
stop = true;
}
charIndex = nextCharIndex;
} else {
i = node.childNodes.length;
while (i--) {
nodeStack.push(node.childNodes[i]);
}
}
}
sel = document.getSelection();
sel.removeAllRanges();
sel.addRange(range);
}
Я мог бы использовать некоторые советы/помощь по следующим вопросам:
- Как правильно подсчитать
<br>
s? -
Как вы считаете
<br>
в начале (в этом примере HTML)?<div contenteditable><br>12345<br><br><br>9012345</div>
-
Включить
<br>
, завернутый в<div>
(в этом примере HTML) - я в конце концов доберусь до этого, но я не хотел продолжать этот путь и выяснить, есть ли более простой метод.<div contenteditable><div><br></div>12345<div><br></div><div><br></div><div><br></div>9012345</div>
-
Я попытался заменить указанный выше код
rangy
, но он, похоже, не имеет встроенного метода для получения или установки диапазона.