2014-07-19 9 views
7

रीसेट किए बिना किसी कंटेंटएडेबल डिव में टेक्स्ट को संशोधित करें, मैं /any thing in here/ के <b>/any thing in here/</b> के साथ किसी भी उदाहरण को प्रतिस्थापित करने की कोशिश कर रहा हूं, क्योंकि सामग्री को संतोषजनक div में किया जाता है।कैरेट (कर्सर) स्थिति

मेरा वर्तमान कार्यान्वयन कार्य करता है, लेकिन प्रत्येक कीप्रेस पर कैरेट को कार्यान्वयन योग्य बनाने के लिए div की शुरुआत में स्थानांतरित किया जाता है। Div की सामग्री को प्रतिस्थापित करते समय कैरेट स्थिति रखने का कोई तरीका है?

$('.writer').on('keyup', function(e) { 
    $(this).html($(this).html().replace(/\/(.*)\//g, '<b>\/$1\/<\/b>')); 
}); 
+0

वहाँ एक कारण है कि आप के साथ 'एक' textarea' या कुछ इसी तरह के बजाय contenteditable' एक 'div' उपयोग करने के लिए है? – royhowie

+0

@ लक्सेलिन: मैं div के भीतर एचटीएमएल प्रस्तुत करना चाहता हूं, और जहां तक ​​मुझे पता है, HTML को टेक्स्टरेरा के अंदर प्रस्तुत नहीं किया जा सकता है। – slyv

+0

भले ही आप टेक्स्टरेरा का उपयोग करना चाहते थे, मुझे यकीन है कि देखभाल अभी भी घूमती रहेगी। –

उत्तर

4

कोशिश यह demo

$('#writer').on('keyup', function(e) { 
     var range = window.getSelection().getRangeAt(0); 
     var end_node = range.endContainer; 
     var end = range.endOffset; 
     if(end_node != this){ 
      var text_nodes = get_text_nodes_in(this); 
      for (var i = 0; i < text_nodes.length; ++i) { 
       if(text_nodes[i] == end_node){ 
        break; 
       } 
       end += text_nodes[i].length; 
      } 
     } 
     var html = $(this).html(); 
     if(/\&nbsp;$/.test(html) && $(this).text().length == end){ 
      end = end - 1; 
      set_range(end,end,this); 
      return; 
     } 
     var filter = html.replace(/(<b>)?\/([^<\/]*)(<\/b>)?/g, '\/$2'); 
     console.log(filter); 
     filter = filter.replace(/(<b>)?([^<\/]*)\/(<\/b>)?/g, '$2\/'); 
     console.log(filter); 
     filter = filter.replace(/(<b>)?\/([^<\/]*)\/(<\/b>)?/g, '<b>\/$2\/<\/b>'); 
     console.log(filter); 
     if(!/\&nbsp;$/.test($(this).html())){ 
      filter += '&nbsp;'; 
     } 
     $(this).html(filter); 
     set_range(end,end,this); 

    }); 

    $('#writer').on('mouseup', function(e) { 
     if(!/\&nbsp;$/.test($(this).html())){ 
      return; 
     } 
     var range = window.getSelection().getRangeAt(0); 
     var end = range.endOffset; 
     var end_node = range.endContainer; 
     if(end_node != this){ 
      var text_nodes = get_text_nodes_in(this); 
      for (var i = 0; i < text_nodes.length; ++i) { 
       if(text_nodes[i] == end_node){ 
        break; 
       } 
       end += text_nodes[i].length; 
      } 
     } 
     if($(this).text().length == end){ 
      end = end - 1; 
      set_range(end,end,this); 
     } 
    }); 

    function get_text_nodes_in(node) { 
     var text_nodes = []; 
     if (node.nodeType === 3) { 
      text_nodes.push(node); 
     } else { 
      var children = node.childNodes; 
      for (var i = 0, len = children.length; i < len; ++i) { 
       var text_node 
       text_nodes.push.apply(text_nodes, get_text_nodes_in(children[i])); 
      } 
     } 
     return text_nodes; 
    } 

    function set_range(start, end, element) { 
     var range = document.createRange(); 
     range.selectNodeContents(element); 
     var text_nodes = get_text_nodes_in(element); 
     var foundStart = false; 
     var char_count = 0, end_char_count; 

     for (var i = 0, text_node; text_node = text_nodes[i++];) { 
      end_char_count = char_count + text_node.length; 
      if (!foundStart && start >= char_count && (start < end_char_count || (start === end_char_count && i < text_nodes.length))) { 
       range.setStart(text_node, start - char_count); 
       foundStart = true; 
      } 
      if (foundStart && end <= end_char_count) { 
       range.setEnd(text_node, end - char_count); 
       break; 
      } 
      char_count = end_char_count; 
     } 

     var selection = window.getSelection(); 
     selection.removeAllRanges(); 
     selection.addRange(range); 
    } 
संबंधित मुद्दे