Saving and Restoring caret position for contentEditable div

后端 未结 3 1144
耶瑟儿~
耶瑟儿~ 2020-11-29 08:49

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

3条回答
  •  心在旅途
    2020-11-29 09:16

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

    Idea is very simple .

    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

    Two edge case:

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

    2. 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){
        const NODE_TYPE = NodeFilter.SHOW_TEXT;
        var treeWalker = document.createTreeWalker(root, NODE_TYPE, function next(elem) {
            if(index > elem.textContent.length){
                index -= elem.textContent.length;
                return NodeFilter.FILTER_REJECT
            }
            return NodeFilter.FILTER_ACCEPT;
        });
        var c = treeWalker.nextNode();
        return {
            node: c? c: root,
            position: index
        };
    }
    
    
      
    

    Edit the CSS Snippet

        p { color: red }
    

提交回复
热议问题