2014-10-01 5 views
13

वहाँ एचटीएमएल इस तरह है:कर्सर की स्थिति बहाल contenteditable बदलने के बाद

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

और div की सामग्री dynamicly कुछ शब्दों को हाइलाइट करना चाहिए उपयोगकर्ता प्रकार जैसे की तरह कुछ बनाने, जबकि:

<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 कर्सर में टेक्स्ट रीफ्रेश करता हूं।

क्या सामग्रीबद्ध मूल्य बदलने के बाद कर्सर की स्थिति को पुनर्स्थापित करने के कोई तरीके हैं? या शायद एक ही प्रभाव पाने का दूसरा तरीका है?

+1

कर्सर स्थिति सहेजने का प्रयास करें (देखें http://stackoverflow.com/questions/4767848/get-caret-cursor-position-in-contenteditable-area-containing- एचटीएमएल-सामग्री) और उसके बाद इसे वापस सेट करें (input.html (...) के बाद http://stackoverflow.com/questions/1181700/set-cursor-position-on-contentitable-div देखें)। मुझे लगता है कि आपको यहां अन्य समस्या भी है: आपके उदाहरण में "हाइलाइट" शब्द प्रत्येक बार पाठ को संपादित करते समय एक नए अवधि में लपेटा जाएगा। आपको नए स्पैन जोड़ने से पहले प्लेसहोल्डर्स के साथ लिपटे शब्दों को प्रतिस्थापित करना चाहिए, फिर प्लेसहोल्डर्स को वापस लेना चाहिए। – Qwerty

+0

यदि आपके पास कोई समाधान है जो आपकी अपेक्षाओं को पूरा करता है तो आपको इसे एक उत्तर के रूप में जोड़ना चाहिए और इसे चुनना चाहिए। http://stackoverflow.com/help/self-answer –

+0

@ जेसनस्पर्सके ने – Tdm

उत्तर

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

यह आपके विशेष मामले में एक अच्छा समाधान है: यदि आप अपनी संतुष्टताओं में नई लाइनें अक्षम करते हैं। अन्यथा, कर्सर ऑफसेट प्राप्त करने वाली स्क्रिप्ट
जैसी नई लाइन इकाइयों को नजरअंदाज करती है और कर्सर की स्थिति गलत जगह पर सेट करती है (
तत्वों से पहले)। –

संबंधित मुद्दे