2014-10-01 13 views
13

Có html như thế này:Khôi phục vị trí con trỏ sau khi thay đổi contenteditable

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

Và nội dung của div nên dynamicly làm nổi bật một số từ trong khi sử dụng các loại ví dụ như làm một cái gì đó như:

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

Nhưng có một vấn đề: khi tôi làm mới văn bản trong di chuyển con trỏ div ở đầu văn bản trong đầu vào.

Có cách nào để khôi phục vị trí con trỏ sau khi thay đổi giá trị có thể chỉnh sửa được không? Hoặc có thể có cách khác để có được hiệu ứng tương tự?

+1

Cố gắng tiết kiệm vị trí con trỏ (xem http://stackoverflow.com/questions/4767848/get-caret-cursor-position-in-contenteditable-area-containing- html-content) và sau đó thiết lập lại (xem http://stackoverflow.com/questions/1181700/set-cursor-position-on-contenteditable-div) sau input.html (...). Tôi nghĩ rằng bạn cũng có vấn đề khác ở đây: trong ví dụ của bạn "nổi bật" từ sẽ được gói trong một khoảng mới mỗi khi bạn chỉnh sửa văn bản. Bạn có thể nên thay thế các từ được bao bọc bằng các phần giữ chỗ trước khi thêm các nhịp mới, sau đó thay thế các phần giữ chỗ trở lại. – Qwerty

+0

Nếu bạn có một giải pháp đáp ứng kỳ vọng của bạn, bạn nên thêm nó như là một câu trả lời và chọn nó. http://stackoverflow.com/help/self-answer –

+0

@JasonSperske thực hiện – Tdm

Trả lời

8

Tôi đã tìm thấy giải pháp.

Đây là một mã hoàn chỉnh:

<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

Đây là một giải pháp tốt trong trường hợp đặc biệt của bạn: nếu bạn vô hiệu hóa các dòng mới trong contentedtibales của bạn. Nếu không, tập lệnh nhận bù trừ con trỏ sẽ bỏ qua các đối tượng dòng mới như
và đặt vị trí con trỏ ở vị trí không chính xác (trước các phần tử
). –

Các vấn đề liên quan