如何获得包含图像的内容可编辑div的插入符位置 [英] how to get the caret position of a contenteditable div which contains images

查看:78
本文介绍了如何获得包含图像的内容可编辑div的插入符位置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个contentedittable div

I have this contentedittable div

<div contenteditable="true" id="text">minubyv<img src="images/smiley/Emoji Smiley-01.png" class="emojiText" />iubyvt</div>

以下是代码输出的图像描述

Here is an image description of the code output

所以我想获取div的插入符位置,并假设光标位于最后一个字符之后。这是我获取插入符位置的代码

so I want to get the caret position of the div and lets assume that the cursor is after the last character. And this is my code for getting the caret position

function getCaretPosition(editableDiv) {
  var caretPos = 0,
    sel, range;
  if (window.getSelection) {
    sel = window.getSelection();
    if (sel.rangeCount) {
      range = sel.getRangeAt(0);
      if (range.commonAncestorContainer.parentNode == editableDiv) {
        caretPos = range.endOffset;
      }
    }
  } else if (document.selection && document.selection.createRange) {
    range = document.selection.createRange();
    if (range.parentElement() == editableDiv) {
      var tempEl = document.createElement("span");
      editableDiv.insertBefore(tempEl, editableDiv.firstChild);
      var tempRange = range.duplicate();
      tempRange.moveToElementText(tempEl);
      tempRange.setEndPoint("EndToEnd", range);
      caretPos = tempRange.text.length;
    }
  }
  return caretPos;
}

var update = function() {
  console.log(getCaretPosition(this));
};
$('#text').on("mousedown mouseup keydown keyup", update);

但是问题在于它返回 6 而不是 14 。图像后,插入符号位置返回到 0 。请在这种情况下,有一种方法可以使插入符号的位置变为 14

But the problem is that it returns 6 instead of 14. The caret position goes back to 0 after the image. Please is there a way I can get the caret position to be 14 in this case.

编辑

我还要从插入符位置插入一些元素。因此,这是我的功能

I want to also insert some element starting from the caret position. so this is my function to do that

selectStart = 0;
var update = function() {
  selectStart = getCaretPosition(this);
};
function insertEmoji(svg){
    input = $('div#text').html();
    beforeCursor = input.substring(0, selectStart);
    afterCursor = input.substring(selectStart, input.length);
    emoji = '<img src="images/smiley/'+svg+'.png" class="emojiText" />';
    $('div#text').html(beforeCursor+emoji+afterCursor);
}


推荐答案

请参见Tim Down的答案 end-offsets-relative-to-its-parent-container>获取相对于其父容器的范围的开始和结束偏移量。

See Tim Down's answer on Get a range's start and end offset's relative to its parent container.

尝试使用他必须使用以下嵌套元素获取选择索引的函数:

Try to use the function he has to get the selection index with nested elements like this:

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

var update = function() {
  console.log(getCaretCharacterOffsetWithin(this));
};
$('#text').on("mousedown mouseup keydown keyup", update);

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div contenteditable="true" id="text">minubyv<img src="https://themeforest.net/images/smileys/happy.png" class="emojiText" />iubyvt</div>

我根据Tim Down编写了自己的函数,该函数的运行就像您想要的一样。我更改了 treeWalker 来过滤 NodeFilter.ELEMENT_NODE 插入的 NodeFilter.SHOW_TEXT ,现在< img /> 元素也将在循环中处理。我首先存储 range.startOffset ,然后递归遍历所有选择树节点。如果找到 img 节点,则该位置仅增加1;否则,该位置仅增加1。如果当前节点元素与我们的 range.startContainer 不同,则它将添加该节点的长度。位置由另一个变量 lastNodeLength 更改,该变量在每个循环中添加到 charCount 中。最后,当存在循环且我们具有正确的最终值时,它将 lastNodeLength 中剩余的内容添加到 charCount 中插入符号的位置,包括图像元素。

I wrote my own function, based on Tim Down's, that works like you want it. I changed the treeWalker to filter NodeFilter.ELEMENT_NODE insted of NodeFilter.SHOW_TEXT, and now <img/> elements also get processed inside our loop. I start by storing the range.startOffset and then recurse through all the selection tree nodes. If it finds an img node, then it adds just 1 to the position; if the current node element is different than our range.startContainer, then it adds that node's length. The position is altered by a different variable lastNodeLength that is adds to the charCount at each loop. Finally, it adds whatever is left in the lastNodeLength to the charCount when it exists the loop and we have the correct final caret position, including image elements.

最终工作代码 (最后,它返回14,完全符合您的期望)

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

    var charCount = 0, lastNodeLength = 0;

    if (range.startContainer.nodeType == 3) {
        charCount += range.startOffset;
    }

    while (treeWalker.nextNode()) {
        charCount += lastNodeLength;
        lastNodeLength = 0;
        
        if(range.startContainer != treeWalker.currentNode) {
            if(treeWalker.currentNode instanceof Text) {
                lastNodeLength += treeWalker.currentNode.length;
            } else if(treeWalker.currentNode instanceof HTMLBRElement ||
                      treeWalker.currentNode instanceof HTMLImageElement /* ||
                      treeWalker.currentNode instanceof HTMLDivElement*/)
            {
                lastNodeLength++;
            }
        }
    }
    
    return charCount + lastNodeLength;
}

var update = function() {
    var el = document.getElementById("text");
    var range = window.getSelection().getRangeAt(0);
    console.log("Caret pos: " + getCharacterOffsetWithin_final(range, el))
};
$('#text').on("mouseup keyup", update);

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div contenteditable="true" id="text">minubyv<img contenteditable="true" src="https://themeforest.net/images/smileys/happy.png" class="emojiText" />iubyvt</div>

这篇关于如何获得包含图像的内容可编辑div的插入符位置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆