保存和恢复插入符位置CONTENTEDITABLE DIV保存和恢复插入符位置CONTENTEDIT

2019-05-12 02:45发布

我有一个contentEditable DIV的innerHTML这些都可以通过AJAX同时编辑进行更新。 问题是,当你改变div的内容将光标移到到div结束(或因失去专注于浏览器)。 什么是一个很好的跨浏览器的解决方案来存储改变之前插入位置innerHTML ,然后将其还原?

Answer 1:

回至2016年:)
之后我遇到了这个解决方案,它不适合我,因为我的DOM各打字后完全取代。 我做更多的研究,并配有简单的解决方案,通过对我的工作完美人物的位置保存光标。

想法很简单。

  1. 找到charachters的符前面的长度和保存。
  2. 改变DOM。
  3. 使用TreeWalker只是走在text nodescontext node ,直到我们得到正确的计数字符text node和里面的位置

两个边缘情况:

  1. 完全移除的内容,所以没有text node
    所以 :将光标移动到开始上下文节点

  2. 有较少的内容,则index指出的:
    所以 :将光标移动到最后一个节点结束

 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> 



Answer 2:

我知道这是一个古老的线程,但我想我会提供一个可选的非库解决方案

http://jsfiddle.net/6jbwet9q/9/

在测试的铬,FF和IE10 +允许您更改,删除和恢复HTML,同时保留插入位置/选择。

HTML

<div id=bE contenteditable=true></div>

JS

function saveRangePosition()
  {
  var range=window.getSelection().getRangeAt(0);
  var sC=range.startContainer,eC=range.endContainer;

  A=[];while(sC!==bE){A.push(getNodeIndex(sC));sC=sC.parentNode}
  B=[];while(eC!==bE){B.push(getNodeIndex(eC));eC=eC.parentNode}

  return {"sC":A,"sO":range.startOffset,"eC":B,"eO":range.endOffset};
  }

function restoreRangePosition(rp)
  {
  bE.focus();
  var sel=window.getSelection(),range=sel.getRangeAt(0);
  var x,C,sC=bE,eC=bE;

  C=rp.sC;x=C.length;while(x--)sC=sC.childNodes[C[x]];
  C=rp.eC;x=C.length;while(x--)eC=eC.childNodes[C[x]];

  range.setStart(sC,rp.sO);
  range.setEnd(eC,rp.eO);
  sel.removeAllRanges();
  sel.addRange(range)
  }

function getNodeIndex(n){var i=0;while(n=n.previousSibling)i++;return i}


Answer 3:

更新:我已经移植四肢修长的代码到一个独立的要点是:

https://gist.github.com/timdown/244ae2ea7302e26ba932a43cb0ca3908

原来的答案

你可以使用四肢修长 ,我的跨浏览器的范围和选择库。 它有一个选择保存和恢复模块那似乎非常适合您的需求。

这种方法并不复杂:它插入在每个选定范围的开始和结束标记元素,并使用这些标记元素稍后再恢复的范围界线,其未瘦长的没有太多的代码实现(你甚至可以适应瘦长自己代码 )。 瘦长的主要优点是为IE <= 8的支持。



文章来源: Saving and Restoring caret position for contentEditable div