保存和恢复contentEditable div的插入位置 [英] Saving and Restoring caret position for contentEditable div

查看:109
本文介绍了保存和恢复contentEditable div的插入位置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 contentEditable div, innerHTML 可以在编辑时通过AJAX更新。问题是,当你更改div的内容时,它会将光标移动到div的末尾(或根据浏览器失去焦点)。在更改 innerHTML 然后恢复之前,什么是存储插入位置的良好跨浏览器解决方案?

I have a contentEditable div, the innerHTML of which can be updated through AJAX while editing. The problem is that when you change the contents of the div it moves the cursor to the end of the div (or loses focus depending on the browser). What is a good cross-browser solution to store caret position before changing innerHTML and then to restore it?

推荐答案

回到2016年:)

我遇到这个解决方案之后,它并不适合我,因为我的DOM在每次打字后都完全取代了。我做了更多的工作,并提供简单的解决方案,保存光标的角色位置,对我来说完美

back to 2016 :)
After I came across this solution, and it did not suit me, because my DOM replaced completely after each typing . I do more reasech and come with simple solution that save the cursor by character's position that work perfect for me.

想法非常简单。


  1. 找到插入符号之前的字符长度并保存。

  2. 更改DOM。

  3. 使用 TreeWalker 文本节点 上下文节点并计算字符,直到我们得到正确的文本节点和里面的位置

  1. find the length of charachters before caret and save it .
  2. change the DOM.
  3. using TreeWalker to walk just on text nodes of context node and counting characters until we got the right text node and the position inside it

两个边缘情况:


  1. 内容已完全删除,因此没有文本节点

    所以:将光标移动到上下文节点

  1. content removed completely so there is no text node:
    so: move cursor to start of context node

内容较少,然后索引指向:

so :将光标移动到最后一个节点的末尾

there is less content then the index pointed on :
so: move cursor to the end of the last node

function saveCaretPosition(context){
    var selection = window.getSelection();
    var range = selection.getRangeAt(0);
    range.setStart(  context, 0 );
    var len = range.toString().length;

    return function restore(){
        var pos = getTextNodeAtPosition(context, len);
        selection.removeAllRanges();
        var range = new Range();
        range.setStart(pos.node ,pos.position);
        selection.addRange(range);

    }
}

function getTextNodeAtPosition(root, index){
    var lastNode = null;

    var treeWalker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT,function next(elem) {
        if(index >= elem.textContent.length){
            index -= elem.textContent.length;
            lastNode = elem;
            return NodeFilter.FILTER_REJECT
        }
        return NodeFilter.FILTER_ACCEPT;
    });
    var c = treeWalker.nextNode();
    return {
        node: c? c: root,
        position: c? index:  0
    };
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.5.1/prism.min.js"></script>
<link href="https://rawgit.com/PrismJS/prism/gh-pages/themes/prism.css" rel="stylesheet"/>
<style>
  *{
    outline:none
    }
</style>  
<h3>Edit the CSS Snippet </H3>
<pre>
    <code class="language-css" contenteditable=true >p { color: red }</code>
</pre>

<script >
  var code = document.getElementsByTagName('code')[0];
  
  code.addEventListener('input',function () {
        var restore = saveCaretPosition(this);
        Prism.highlightElement(this);
        restore();
    })
</script>

这篇关于保存和恢复contentEditable div的插入位置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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