Javascript 更改内容后恢复光标位置可编辑

Javascript 更改内容后恢复光标位置可编辑,javascript,jquery,html,contenteditable,Javascript,Jquery,Html,Contenteditable,有这样的html: <div contenteditable="true" class="value research-form thumbnail"> Some text here </div> 这里有一些文字 div的内容应该动态地突出显示一些单词,而用户类型,例如: <div contenteditable="true" class="value research-form thumbnail"> Some text here <sp

有这样的html:

<div contenteditable="true" class="value research-form thumbnail">
 Some text here
 </div>

这里有一些文字
div的内容应该动态地突出显示一些单词,而用户类型,例如:

 <div contenteditable="true" class="value research-form thumbnail">
 Some text here <span style="background-color: yellow">highlight</div> it
 </div>
 <script>
    $(document).ready(function () {
        var input = $('#textarea').on('input', function (event) {
            var newText = input.text().replace('highlight', '<span style="background-color: yellow">highlight</div>');
            input.html($.parseHTML(newText));
        });
    });
</script>

这里的一些文字突出显示了它
$(文档).ready(函数(){
变量输入=$('#textarea')。在('input',函数(事件)上{
var newText=input.text().replace('highlight','highlight');
html($.parseHTML(newText));
});
});
但有一个问题:当我刷新div中的文本时,光标在input中文本的开头移动

更改contenteditable值后,是否有方法恢复光标位置?或者有其他方法可以达到同样的效果?

我找到了解决办法

以下是完整的代码:

<div class="container" style="margin-top: 10px">

    <div class="thumbnail value" contenteditable="true">

    </div>

</div>

<script>
    $(document).ready(function () {
        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;
        }

        function setCaretPosition(element, offset) {
            var range = document.createRange();
            var sel = window.getSelection();

            //select appropriate node
            var currentNode = null;
            var previousNode = null;

            for (var i = 0; i < element.childNodes.length; i++) {
                //save previous node
                previousNode = currentNode;

                //get current node
                currentNode = element.childNodes[i];
                //if we get span or something else then we should get child node
               while(currentNode.childNodes.length > 0){
                  currentNode = currentNode.childNodes[0];
               }

                //calc offset in current node
                if (previousNode != null) {
                    offset -= previousNode.length;
                }
                //check whether current node has enough length
                if (offset <= currentNode.length) {
                    break;
                }
            }
            //move caret to specified offset
            if (currentNode != null) {
                range.setStart(currentNode, offset);
                range.collapse(true);
                sel.removeAllRanges();
                sel.addRange(range);
            }
        }

        function onInput(event) {
            var position = getCaretCharacterOffsetWithin(input.get(0));
            var text = input.text();
            text = text.replace(new RegExp('\\btest\\b', 'ig'), '<span style="background-color: yellow">test</span>');
            input.html($.parseHTML(text));
            setCaretPosition(input.get(0), position);
        }

        var input = $('.value').on('input',onInput);

        //content should be updated manually to prevent aditional spaces
        input.html('simple input test example');
        //trigger event
        onInput();
    });
</script>

$(文档).ready(函数(){
函数getCaretCharacterOffsetWithin(元素){
var caretofset=0;
var doc=element.ownerDocument | | element.document;
var win=doc.defaultView | | doc.parentWindow;
var-sel;
if(typeof win.getSelection!=“未定义”){
sel=win.getSelection();
如果(选择范围计数>0){
var range=win.getSelection().getRangeAt(0);
var precretange=range.cloneRange();
预重排列。选择节点内容(元素);
precretange.setEnd(range.endContainer,range.endOffset);
CareTofset=precretange.toString().length;
}
}如果((选择=文件选择)&&sel.type!=“控制”){
var textRange=sel.createRange();
var precarteTextRange=doc.body.createTextRange();
PrecretTextRange.moveToElementText(元素);
setEndPoint(“EndToEnd”,textRange);
CareTofset=PrecretTextRange.text.length;
}
返回caretofset;
}
函数setCaretPosition(元素,偏移){
var range=document.createRange();
var sel=window.getSelection();
//选择合适的节点
var currentNode=null;
var-previousNode=null;
对于(var i=0;i0){
currentNode=currentNode.childNodes[0];
}
//计算当前节点中的偏移量
if(previousNode!=null){
偏移量-=上一个节点的长度;
}
//检查当前节点是否有足够的长度

if(offset)尝试保存光标位置(请参见),然后在input.html(…)之后将其设置回(请参见)。我认为这里还有其他问题:在您的示例中是“突出显示”每次编辑文本时,word都将被包装在一个新的跨距中。在添加新跨距之前,您可能应该用占位符替换包装的word,然后再替换占位符。如果您有一个满足您期望的解决方案,您应该将其添加为答案并选择它。回到2016年。我为divs找到了一个很好的解决方案。并将其发布到此处回答这个问题:在您的特殊情况下,这是一个很好的解决方案:如果您在ContentDibales中禁用新行。否则,获取光标偏移量的脚本将忽略新行实体,如
,并将光标位置设置在错误的位置(在
元素之前)。当输入字符
时,还有一个ces。它会把整个内容弄乱。您可能应该先用
逃离第一个。此任务的代码太多了:(