Получить позицию курсора (курсора) в области contentEditable, содержащей контент HTML - PullRequest
55 голосов
/ 22 января 2011

У меня есть элемент contentEditable (может быть p, div, ...), и я хотел бы получить в нем позицию курсора (курсора).Обычно я могу добиться этого с помощью следующего фрагмента кода:

var position = window.getSelection().getRangeAt(0).startOffset;

Это прекрасно работает, когда элемент содержит только текст.Но когда элемент содержит некоторое форматирование HTML, возвращаемая позиция относительно позиции каретки внутри включенного HTML-элемента.

Предположим, что содержимое элемента contentEditable таково:

AB<b>CD</b>EF

Если каретка находится внутри<b></b>, скажем, между C и D, возвращаемая позиция с приведенным выше кодом равна 1 вместо 3 (считая с начала содержимого элемента contentEditable)

Может кто-нибудь придумать решение для этого?

Ответы [ 3 ]

51 голосов
/ 23 января 2011

UPDATE

Я написал более простую версию, которая также работает в IE <9: </p>

https://stackoverflow.com/a/4812022/96100

Старый ответ

На самом деле это более полезный результат, чем смещение символа в тексте всего документа: свойство startOffset диапазона DOM (которое возвращает window.getSelection().getRangeAt()) является смещением относительно его свойства startContainer (кстати, это не всегда текстовый узел). Однако, если вы действительно хотите смещение символа, вот функция, которая сделает это.

Вот живой пример: http://jsfiddle.net/timdown/2YcaX/

Вот функция:

function getCharacterOffsetWithin(range, node) {
    var treeWalker = document.createTreeWalker(
        node,
        NodeFilter.SHOW_TEXT,
        function(node) {
            var nodeRange = document.createRange();
            nodeRange.selectNode(node);
            return nodeRange.compareBoundaryPoints(Range.END_TO_END, range) < 1 ?
                NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT;
        },
        false
    );

    var charCount = 0;
    while (treeWalker.nextNode()) {
        charCount += treeWalker.currentNode.length;
    }
    if (range.startContainer.nodeType == 3) {
        charCount += range.startOffset;
    }
    return charCount;
}
5 голосов
/ 24 октября 2017

Это очень старый пост, но он все еще один из первых результатов поиска в Google, так что, возможно, все еще полезен. Это работает для меня, чтобы получить правильную позицию, учитывая html-теги и переводы строк (проверено на Firefox):

function getCaretPosition (node) {
    var range = window.getSelection().getRangeAt(0),
        preCaretRange = range.cloneRange(),
        caretPosition,
        tmp = document.createElement("div");

    preCaretRange.selectNodeContents(node);
    preCaretRange.setEnd(range.endContainer, range.endOffset);
    tmp.appendChild(preCaretRange.cloneContents());
    caretPosition = tmp.innerHTML.length;
    return caretPosition;
}

Он использует функциональность cloneContents для получения фактического html и добавляет фрагмент документа во временный div для получения длины html.

1 голос
/ 17 июня 2014

Если вы хотите вставить элемент, вы можете попробовать сделать что-то вроде этого:

// Get range
var range = document.caretRangeFromPoint(event.clientX, event.clientY);
if (range)
  range.insertNode(elementWhichYouWantToAddToContentEditable);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...