如何获得包含图像的内容可编辑div的插入符位置 [英] how to get the caret position of a contenteditable div which contains images
问题描述
我有这个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屋!