2013-02-08 2 views
0

Мне нужно получить позицию курсора в div contentDditable. Я получаю полезную функцию от Get a range's start and end offset's relative to its parent container и https://stackoverflow.com/a/4770562/2008261.Как получить позицию курсора в contentEditable, содержащей HTML?

Но эти функции НЕ помогают, потому что мне нужна фактическая позиция в HTML, вот что мне нужно.

, если у меня есть:

<div id="diva" contenteditable="true">Insert <b>text here</b></div> 

и я поставил курсор перед словом «текст» он возвращает 7, как это имеет дело с текстом. Но мне нужно, чтобы он возвращался 10, как будто он имеет дело с внутренним HTML-массивом div contentEditabe.

Эти функции я уже говорил ранее:

function getCaretCharacterOffsetWithin(element) { 
var caretOffset = 0; 
if (typeof window.getSelection != "undefined") { 
    var range = window.getSelection().getRangeAt(0); 
    var preCaretRange = range.cloneRange(); 
    preCaretRange.selectNodeContents(element); 
    preCaretRange.setEnd(range.endContainer, range.endOffset); 
    caretOffset = preCaretRange.toString().length; 
} else if (typeof document.selection != "undefined" && document.selection.type != "Control") { 
    var textRange = document.selection.createRange(); 
    var preCaretTextRange = document.body.createTextRange(); 
    preCaretTextRange.moveToElementText(element); 
    preCaretTextRange.setEndPoint("EndToEnd", textRange); 
    caretOffset = preCaretTextRange.text.length; 
} 
return caretOffset; 
} 

И:

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; 
} 
+1

Вы пытались использовать кросс-браузерную библиотеку, например [rangy] (https://code.google.com/p/rangy/)? –

+0

@ VladMagdalin, rangy является удивительным. У меня было больше, чем мне нужно –

ответ

0

Достигнув решать это раньше (я создал слово веб на основе процессора): единственным жизнеспособным решением является подойти к дереву DOM и подсчитать длину innerHTML и outerHTML, а затем использовать смещение в пределах диапазона, если оно есть.

Я также очень обескураживаю использование contentEditable реализаций, вы потратите гораздо больше времени, пытаясь исправить то, что с ними не так, и попытаться переопределить их поведение, чем вы будете кодировать нужные вам функции.

Моя реализация была функцией, которая приняла смещение диапазона и подошла, пока она не попала в указанный родитель. Некоторые вещи, о которых следует помнить, предыдущие братья и сестры легко добавить, но обертывание родителей сложно с атрибутами и т. Д. Для учета длины.

Мой расчет был взять на себя всю длину узла "<div id="" class="" foo="bar">sometext</div>", вычесть длину innerHTML, вычесть длину tagname и subtract 3, чтобы получить длину <div id="" class="" foo="bar">

но если вы не контролировала создание что HTML, ваш счет все еще может быть неправильным, поскольку в зависимости от браузера несколько пробелов в строке возвращаются как 1 символ или несколько символов при тестировании длины.

+0

, если я не использую реализаторы contentEditable, что я буду использовать вместо этого. Я не могу реализовать textarea для выполнения моих потребностей. Я согласен с вами в том, что у него много проблем и очень запутанно, поскольку я кодирую очень много кодов, но каково другое решение для него? –

+0

Почему вы не можете реализовать текстовое поле? Скрытая текстовая область - гораздо более полезный трюк, чем iframes или редактирование контента. – runspired

+0

Фактически я использую оба из них, текстовое поле и contentEditable. ContentEditable - это то, с чем пользователь взаимодействует, и текстовая область скрыта. Когда пользователь что-то пишет или создает что-то в contentEditable, он отражается в скрытой текстовой области. Таким образом, в textarea хранятся html-разметки, тогда код jQuery создает мост между ними. Но я не могу использовать текстовую область, потому что она не поддерживает отображение текста в формате HTML. Я думаю, ваш текстовый процессор реализует ту же концепцию. Не так ли? –

Смежные вопросы