【问题标题】:Get caret index in contenteditable div including tags在 contenteditable div 中获取插入符号索引,包括标签
【发布时间】:2013-05-20 03:44:36
【问题描述】:

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

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

例如:

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

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

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

【问题讨论】:

  • 为什么需要这个号码?这本质上是没有意义的,因为有很多方法可以用不同的 HTML 来表示同一个 DOM,这会影响数字(例如,使用 &lt;br /&gt; 而不是 &lt;br&gt;)。我假设你想要这个,这样你就可以获得相对于你从服务器发送到浏览器的 HTML 字符串的偏移量。
  • 是的...这正是我需要这个号码的原因。我尝试了几种方法,但仍然没有成功。
  • 无法通过 DOM 取回原始 HTML 字符串,因此您需要通过 Ajax 重新请求页面,解析 HTML 并将其与当前 DOM 匹配。这将是相当棘手的。

标签: javascript html contenteditable getcaretpos


【解决方案1】:

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

基本思路是:

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

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

【讨论】:

  • 你是我的英雄。这很好用,让我省了几个小时的眼泪。
  • getCaretPosition(element) 引用了什么函数?您似乎没有包含它的定义。
  • @CFitz 阅读答案的第一点,该函数有链接
  • 如何获取选中的文本?
  • 它有效!拯救生命@YangombiUmpakati 谢谢人
【解决方案2】:

你试过吗? 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;

【讨论】:

  • 感谢您的回答。问题是在确定插入符号位置时没有考虑
  • @helldrain 我想知道您是否设法找到包含标签的解决方案。
  • 有没有包含标签长度的函数。 ?
猜你喜欢
  • 2013-06-05
  • 2012-10-15
  • 1970-01-01
  • 2011-10-05
  • 2013-04-12
  • 1970-01-01
  • 2020-10-29
相关资源
最近更新 更多