javascript 在 contenteditable div 中获取插入符号索引,包括标签
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16736680/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Get caret index in contenteditable div including tags
提问by helldrain
I have a contentEditable
divin which I have multiple tags (br
, b
, u
, i
) and text.
我有一个contentEditable
div,其中有多个标签(br
、b
、u
、i
)和文本。
I need to get the caret index position relative to the div, including all the tags.
我需要获取相对于 div 的插入符号索引位置,包括所有标签。
For example:
例如:
<div id="h" contenteditable="true">abc<b>def<br>ghi</b>jkl</div>
If the cursor is between g
and h
, I need the caret index position to be 14
.
The problem is that the found methods that use a treeWalker
do not work in this case.
The bold tag is not found... probably because it isn't closed.
Also I have tried several methods but still no luck.
如果光标在g
和之间h
,我需要插入符号索引位置为14
。问题是找到的使用 a 的方法treeWalker
在这种情况下不起作用。未找到粗体标记...可能是因为它没有关闭。我也尝试了几种方法,但仍然没有运气。
I need it to work in Firefox. Thank you.
我需要它在Firefox 中工作。谢谢你。
回答by Eric McCormick
Have you tried this? Get a range's start and end offset's relative to its parent container
你试过这个吗? 获取范围相对于其父容器的开始和结束偏移量
Direct link to the jsfiddle: https://jsfiddle.net/TjXEG/1/
jsfiddle 的直接链接:https://jsfiddle.net/TjXEG/1/
Function code:
功能代码:
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;
回答by YangombiUmpakati
just had to do this so there is some working solution (some testing may be required)
只是必须这样做,所以有一些可行的解决方案(可能需要进行一些测试)
basic idea is to:
基本思想是:
get textContent position using this method: Get caret (cursor) position in contentEditable area containing HTML content
iterate through innerHTML of an element to the textContent position
if html tag or entity is encountered, iterate through it until normal char, then continue
使用此方法获取 textContent 位置:在包含 HTML 内容的 contentEditable 区域中获取插入符号(光标)位置
遍历元素的 innerHTML 到 textContent 位置
如果遇到 html 标签或实体,遍历它直到正常字符,然后继续
sample code here:
示例代码在这里:
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;
}