获得包括标签在内的可信赖div中的插入位置

时间:2013-05-24 13:54:14

标签: javascript html contenteditable getcaretpos

我有一个contenteditable div,其中我有多个标签(br,b,u,i)和文本,我需要获得相对于div的插入位置,包括所有标签。

例如:

<div id="h" contenteditable="true">abc<b>def<br>ghi</b>jkl</div>

如果光标在g和h之间,我需要插入位置为14。 问题是找到的使用treeWalker的方法在这种情况下不起作用。 找不到粗体标签......可能是因为它没有关闭。 我也尝试了几种方法,但仍然没有运气。

我需要它才能在Firefox中运行。 谢谢。

2 个答案:

答案 0 :(得分:19)

你试过这个吗? Get a range's start and end offset's relative to its parent container

直接链接到jsfiddle: https://jsfiddle.net/TjXEG/1/

功能代码:

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 showCaretPos() {
    var el = document.getElementById("test");
    var caretPosEl = document.getElementById("caretPos");
    caretPosEl.innerHTML = "Caret position: " + getCaretCharacterOffsetWithin(el);
}

document.body.onkeyup = showCaretPos;
document.body.onmouseup = showCaretPos;

答案 1 :(得分:3)

只需这样做,因此有一些工作解决方案(可能需要进行一些测试)

基本理念是:

  1. 使用此方法获取textContent位置:Get caret (cursor) position in contentEditable area containing HTML content

  2. 将元素的innerHTML迭代到textContent位置

  3. 如果遇到html标记或实体,请遍历它直到普通char,然后继续

  4. 示例代码:

    function getHTMLCaretPosition(element) {
    var textPosition = getCaretPosition(element),
        htmlContent = element.innerHTML,
        textIndex = 0,
        htmlIndex = 0,
        insideHtml = false,
        htmlBeginChars = ['&', '<'],
        htmlEndChars = [';', '>'];
    
    
    if (textPosition == 0) {
      return 0;
    }
    
    while(textIndex < textPosition) {
    
      htmlIndex++;
    
      // check if next character is html and if it is, iterate with htmlIndex to the next non-html character
      while(htmlBeginChars.indexOf(htmlContent.charAt(htmlIndex)) > -1) {
        // console.log('encountered HTML');
        // now iterate to the ending char
        insideHtml = true;
    
        while(insideHtml) {
          if (htmlEndChars.indexOf(htmlContent.charAt(htmlIndex)) > -1) {
            if (htmlContent.charAt(htmlIndex) == ';') {
              htmlIndex--; // entity is char itself
            }
            // console.log('encountered end of HTML');
            insideHtml = false;
          }
          htmlIndex++;
        }
      }
      textIndex++;
    }
    
    //console.log(htmlIndex);
    //console.log(textPosition);
    // in htmlIndex is caret position inside html
    return htmlIndex;
    }
    
相关问题