2014-10-01 15 views
13

Es wird wie folgt html:Cursorposition wiederherstellen nach contenteditable Ändern

<div contenteditable="true" class="value research-form thumbnail"> 
Some text here 
</div> 

und Inhalt der div markieren sollte dynamicly einige Wörter während Benutzertypen wie machen etwas, zB:

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

Aber es ist ein Problem: Wenn ich Text im Div-Cursor aktualisiere, verschiebt sich der Text am Anfang des Textes.

Gibt es Möglichkeiten, die Cursorposition nach der Änderung des contenteditable Wertes wiederherzustellen? Oder gibt es vielleicht einen anderen Weg, den gleichen Effekt zu erzielen?

+1

Versuchen Cursorposition speichern (siehe http://stackoverflow.com/questions/4767848/get-caret-cursor-position-in-contenteditable-area-containing- html-content) und dann zurück setzen (siehe http://stackoverflow.com/questions/1181700/set-cursor-position-on-contenteditable-div) nach input.html (...). Ich denke, Sie haben hier auch ein anderes Problem: In Ihrem Beispiel wird das Wort "Hervorhebung" jedes Mal, wenn Sie den Text bearbeiten, in einen neuen Bereich eingeschlossen. Vermutlich sollten Sie umbrochene Wörter durch Platzhalter ersetzen, bevor Sie neue Spannen hinzufügen und dann Platzhalter ersetzen. – Qwerty

+0

Wenn Sie eine Lösung haben, die Ihren Erwartungen entspricht, sollten Sie sie als Antwort hinzufügen und auswählen. http://StackOverflow.com/Help/self-answer –

+0

@JasonSperske getan – Tdm

Antwort

8

Ich fand die Lösung. Hier

ist eine komplette Code:

<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

Dies ist eine gute Lösung in Ihrem speziellen Fall: wenn Sie neue Zeilen in Ihren contentedtibales deaktivieren. Andernfalls ignoriert das Skript, das den Cursor-Offset erhält, neue Zeilen-Entities wie
und setzt die Cursor-Position an der falschen Stelle (vor den Elementen
). –

Verwandte Themen