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
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 .
TreeWalker to walk just on text nodes of context node and counting characters until we got the right text node and the position inside itTwo edge case:
content removed completely so there is no text node:
so: move cursor to start of context node
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 }