在 contenteditable div 中获取插入符号索引,包括标签

IT技术 javascript html contenteditable getcaretpos
2021-02-13 11:08:51

我有一个contentEditable div,其中有多个标签(brbui)和文本。

我需要获取相对于 div 的插入符号索引位置,包括所有标签。

例如:

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

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

我需要它在Firefox 中工作谢谢你。

2个回答

你试过这个吗? 获取范围相对于其父容器的开始和结束偏移量

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;
是否有任何函数也包括标签的长度。?
2021-03-16 11:08:51
谢谢您的回答。问题是在确定插入符号位置时没有考虑 <br> 。
2021-03-20 11:08:51
@helldrain 我想知道您是否设法找到包含标签的解决方案。
2021-04-10 11:08:51

只是必须这样做,所以有一些可行的解决方案(可能需要进行一些测试)

基本思想是:

  1. 使用此方法获取 textContent 位置:在包含 HTML 内容的 contentEditable 区域中获取插入符号(光标)位置

  2. 遍历元素的 innerHTML 到 textContent 位置

  3. 如果遇到 html 标签或实体,遍历它直到正常字符,然后继续

示例代码在这里:

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

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;
}
如何获取选定的文本?
2021-03-15 11:08:51
@CFitz 阅读答案的第一点,该函数有链接
2021-03-18 11:08:51
你是我的英雄。这工作得很好,让我省了几个小时的眼泪。
2021-03-20 11:08:51
什么函数被引用getCaretPosition(element)您似乎没有包含其定义。
2021-04-06 11:08:51
有用!救命@YangombiUmpakati 谢谢男人
2021-04-08 11:08:51