2014-10-01 103 views
13

还有就是HTML这样的:恢复光标位置改变CONTENTEDITABLE后

<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> 

但是有一个问题:当我刷新div中的文本时,光标在输入文本的开始处移动。

改变contenteditable值后,有什么办法恢复光标位置吗?或者,也许还有其他方式来获得相同的效果?

+1

尝试保存光标位置(见http://stackoverflow.com/questions/4767848/get-caret-cursor-position-in-contenteditable-area-containing- html-content),然后在input.html(...)后面设置它(请参阅http://stackoverflow.com/questions/1181700/set-cursor-position-on-contenteditable-div)。 我认为你在这里还有其他问题:在你的例子中,每次编辑文本时,“高亮”单词将被包裹在一个新的跨度中。在添加新跨度之前,可能应该用占位符替换包裹的单词,然后将占位符替换回来。 – Qwerty 2014-10-01 10:52:17

+0

如果您的解决方案符合您的期望,则应将其添加为答案并将其选中。 http://stackoverflow.com/help/self-answer – 2016-01-27 17:10:34

+0

@JasonSperske完成 – Tdm 2016-01-29 12:40:14

回答

8

我找到了解决方案。

下面是一个完整的代码:

<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> 
+0

在您的特例中,这是一个很好的解决方案:如果您在contentedtibales中禁用了新行。否则,获取游标偏移的脚本会忽略新线条实体,如
,并将光标位置设置在错误位置(在
元素之前)。 – 2017-08-02 21:01:49

相关问题