2011-09-16 13 views
10

मेरे पास एक संतोषजनक div है जिसमें विशिष्ट wysiwyg संपादक html (बोल्ड, एंकर, सूचियां) शामिल हैं।संवेदी डीआईवी - मैं कैसे निर्धारित कर सकता हूं कि कर्सर सामग्री के प्रारंभ या समाप्ति पर है

मुझे यह निर्धारित करने की आवश्यकता है कि वर्तमान कर्सर, शुरुआत में और div के अंत में, केडडाउन पर है या नहीं। इसका कारण कर्सर की स्थिति के आधार पर है, और कुंजी दबाया गया है, मैं इस div को पिछले div के साथ बैकस्पेस पर विलय करना चाहता हूं, या एंटर पर एक नया निम्न div बना सकता हूं।

मैं श्रेणियों के साथ घूम रहा हूं, लेकिन जब आप तत्व के अंदर एचटीएमएल के साथ काम कर रहे हैं, तो चीजें बहुत जटिल हो जाती हैं।

मुझे उम्मीद है कि मुझे कुछ सरल समाधान दिखाना चाहिए।

क्या यह निर्धारित करने का एक अपेक्षाकृत सरल तरीका है - मैं रंगी जैसी लाइब्रेरी का उपयोग करने के लिए खुला हूं।

धन्यवाद!

संपादित करें:

$('.mycontenteditable').bind('keydown', handle_keydown) 

handle_keydown = function(e) { 

    range = window.getSelection().getRangeAt(0) 
    start_range = document.createRange() 
    start_range.selectNodeContents(this.firstChild) 
    start_range.collapse(true) // collapse to start 
    is_start = start_range.compareBoundaryPoints(Range.START_TO_START,range) 
    end_range = document.createRange() 
    end_range.selectNodeContents(this.lastChild) 
    end_range.collapse(false) 
    is_end = end_range.compareBoundaryPoints(Range.END_TO_END,range) 
} 

मैं कुछ इस तरह के साथ किसी भी अजीब समस्या आती है करने के लिए जा रहा हूँ: मैं इन पंक्तियों के साथ कुछ सोच रहा हूँ?

उत्तर

13

इस तरह मैंने इसे हल करने का अंत किया। मेरे प्रस्तावित समाधान ने कभी-कभी काम किया लेकिन कई किनारे के मामलों के लिए रास्ता तय किया गया, इसलिए मैंने कर्सर से पहले या उसके बाद कितना टेक्स्ट था, और यदि वह 0 अक्षर था, तो मैं शुरुआत या अंत में था:

handle_keydown = function(e) { 
    // Get the current cusor position 
    range = window.getSelection().getRangeAt(0) 
    // Create a new range to deal with text before the cursor 
    pre_range = document.createRange(); 
    // Have this range select the entire contents of the editable div 
    pre_range.selectNodeContents(this); 
    // Set the end point of this range to the start point of the cursor 
    pre_range.setEnd(range.startContainer, range.startOffset); 
    // Fetch the contents of this range (text before the cursor) 
    this_text = pre_range.cloneContents(); 
    // If the text's length is 0, we're at the start of the div. 
    at_start = this_text.textContent.length === 0; 
    // Rinse and repeat for text after the cursor to determine if we're at the end. 
    post_range = document.createRange(); 
    post_range.selectNodeContents(this); 
    post_range.setStart(range.endContainer, range.endOffset); 
    next_text = post_range.cloneContents(); 
    at_end = next_text.textContent.length === 0; 
} 

अभी भी पूरी तरह से सुनिश्चित नहीं है कि कोई अन्य किनारे के मामले हैं, क्योंकि मुझे पूरी तरह से यह सुनिश्चित नहीं है कि यूनिट का परीक्षण कैसे किया जाए, क्योंकि इसे माउस परस्पर क्रिया की आवश्यकता होती है - शायद कहीं से निपटने के लिए एक लाइब्रेरी है।

+0

यह बहुत मजबूत होना चाहिए आईई <9, जो सीमा या चुनाव वस्तुओं का समर्थन नहीं करता के लिए छोड़कर। –

+1

ध्यान दें कि यह समाधान न्यूलाइन के लिए खाता नहीं है। यदि कर्सर और अंत के बीच एकमात्र पाठ न्यूलाइन की एक श्रृंखला है, तो यह गलत तरीके से कहता है कि कर्सर div के अंत में है। खाली लाइनों को हमेशा '
'के साथ दर्शाया जाता है, लेकिन आप' post_range 'में केवल
' की तलाश नहीं कर सकते हैं।क्लोन सामग्री() ', क्योंकि वर्तमान लाइन अंतिम पंक्ति है, क्योंकि इसमें वर्तमान पंक्ति '
' शामिल है। इसके अलावा, क्रोम 'क्लोन सामग्री()' में '


'है, यदि आप अंतिम पंक्ति पर हैं और यदि आप दूसरी-से-आखिरी पंक्ति पर हैं और अंतिम खाली है। तो, अकेले रेंज इस समस्या को हल नहीं कर सकते हैं। –

15

अनावश्यक क्लोनिंग से बचने के लिए cloneContents() की बजाय ऑब्जेक्ट्स ऑब्जेक्ट्स को छोड़कर मैं आपके लिए एक समान दृष्टिकोण का उपयोग करूंगा। इसके अलावा, आईई < 9 (जो श्रेणियों का समर्थन नहीं करता है) में, आप textTextRange की संपत्ति के साथ एक समान दृष्टिकोण का उपयोग कर सकते हैं।

ध्यान दें कि सामग्री में अग्रणी और/या पिछली लाइन ब्रेक होने पर इसमें समस्याएं होंगी क्योंकि toString() एक श्रेणी की विधि textContent नोड की संपत्ति की तरह काम करती है और केवल टेक्स्ट नोड्स पर विचार करती है, इसलिए खाते में नहीं लेना <br> या ब्लॉक तत्वों द्वारा निहित लाइन ब्रेक। इसके अलावा सीएसएस को ध्यान में नहीं रखा जाता है: उदाहरण के लिए, display: none के माध्यम से छुपाए गए तत्वों के अंदर पाठ शामिल है।

यहाँ एक उदाहरण है:

लाइव डेमो: http://jsfiddle.net/YA3Pu/1/

कोड:

function getSelectionTextInfo(el) { 
    var atStart = false, atEnd = false; 
    var selRange, testRange; 
    if (window.getSelection) { 
     var sel = window.getSelection(); 
     if (sel.rangeCount) { 
      selRange = sel.getRangeAt(0); 
      testRange = selRange.cloneRange(); 

      testRange.selectNodeContents(el); 
      testRange.setEnd(selRange.startContainer, selRange.startOffset); 
      atStart = (testRange.toString() == ""); 

      testRange.selectNodeContents(el); 
      testRange.setStart(selRange.endContainer, selRange.endOffset); 
      atEnd = (testRange.toString() == ""); 
     } 
    } else if (document.selection && document.selection.type != "Control") { 
     selRange = document.selection.createRange(); 
     testRange = selRange.duplicate(); 

     testRange.moveToElementText(el); 
     testRange.setEndPoint("EndToStart", selRange); 
     atStart = (testRange.text == ""); 

     testRange.moveToElementText(el); 
     testRange.setEndPoint("StartToEnd", selRange); 
     atEnd = (testRange.text == ""); 
    } 

    return { atStart: atStart, atEnd: atEnd }; 
}