2011-12-10 16 views
12

के iframe में वर्तमान कैरट स्थिति से ऑफसेट करने के लिए मैं कैसे contentEditable के साथ एक iframe में एक अस्थायी div तत्व की स्थिति चाहते हैं, मामले में उपयोगकर्ता के लिए एक निश्चित कुंजी संयोजन (स्वत: पूर्ण उद्देश्यों के लिए) में प्रवेश करती है ।पिक्सेल contenteditable

मैं कैरट स्थिति प्राप्त करने के लिए कैसे पता: document.getElementById('elm1_ifr').contentWindow.getSelection().anchorOffset

मैं इस का उपयोग div की left संपत्ति की गणना कर सकते हैं, लेकिन मैं यह पता लगाने की top पाने के लिए नहीं कर पा रहे।

एक और संभावना के बारे में मैं उपयोग कर रहा था सोचा: document.getElementById('elm1_ifr').contentWindow.getSelection().anchorNode.parentNode

और jQuery का उपयोग कर पाने के लिए ऑफसेट, लेकिन अगर यह है कि माता-पिता के लिए एक लंबे पाठ लाइन है, मैं सिर्फ पहली पंक्ति के शीर्ष स्थिति को निकालने के लिए सक्षम हो जाएगा ।

क्या कोई इस से मेरी सहायता कर सकता है?

उत्तर

12

ऐसा करने का एकमात्र विश्वसनीय तरीका कैरेट पर एक अस्थायी तत्व डालना है (यह सुनिश्चित करना कि यह शून्य चौड़ाई है), इसकी स्थिति प्राप्त करें और इसे फिर से हटा दें। आपको नोड डालने से पहले डीओएम जैसा था यह सुनिश्चित करने के लिए आपको पाठ नोड के दो सिरों को भी गोंद करना चाहिए (यदि यह एक टेक्स्ट नोड था जिसमें देखभाल शामिल था)। नोट, हालांकि, ऐसा करने (या संपादन योग्य सामग्री पर कोई अन्य मैनुअल डीओएम हेरफेर) ब्राउज़र के आंतरिक पूर्ववत ढेर को तोड़ देता है।

इसका कारण यह है कि the spec for the getBoundingClientRect() method of Range की सावधानीपूर्वक पढ़ने से पता चलता है कि getBoundingClientRect() एक संक्षिप्त रेंज के लिए एक रेक्ट वापस करने के लिए बाध्य नहीं है। संकल्पनात्मक रूप से, दस्तावेज़ में हर स्थिति में एक अच्छी तरह परिभाषित बाध्य आयताकार नहीं है। हालांकि, देखभाल पर स्क्रीन पर भौतिक स्थान होता है, जो मेरी राय में चयन API द्वारा प्रदान किया जाना चाहिए, लेकिन वर्तमान में ब्राउज़र में यह उपलब्ध कराने के लिए कुछ भी नहीं है।

+2

आप, 0 से वर्तमान कैरट स्थान पर होने के लिए सीमा सेट नहीं हो सका तो getBoundingClientRect() का उपयोग '' बाईं + चौड़ाई और शीर्ष + ऊंचाई ऑफसेट पाने के लिए है, तो कैरट बहाल यह पिछले है करने के लिए सेटिंग? – Mottie

+3

पुराना धागा हां, लेकिन एक तत्व डालने वाले नाइट के लायक ['execCommand (' insertHTML ') का उपयोग करके] और इसे हटाने से पूर्ववत/फिर से स्टैक को गड़बड़ कर दिया जाता है। इससे कोई फर्क नहीं पड़ता कि पूर्ववत/फिर से महत्वहीन है। – techfoobar

+0

@techfoobar: अच्छा बिंदु, धन्यवाद। मैंने जवाब में एक नोट जोड़ा। –

7

मैं आज इस समस्या में आया था। कुछ परीक्षण के बाद, मुझे यह काम मिल गया, बिना थैरी तत्व का उपयोग किए।

आईई में, ऑफसेट लेफ्ट और ऑफ़सेट के साथ इसे काम करना आसान है टेक्स्ट टेक्स्ट ऑब्जेक्ट की संपत्ति। हालांकि वेबकिट के लिए कुछ प्रयास की जरूरत है।

यहां एक परीक्षण है, आप परिणाम देख सकते हैं। http://jsfiddle.net/gliheng/vbucs/12/

var getCaretPixelPos = function ($node, offsetx, offsety){ 
    offsetx = offsetx || 0; 
    offsety = offsety || 0; 

    var nodeLeft = 0, 
     nodeTop = 0; 
    if ($node){ 
     nodeLeft = $node.offsetLeft; 
     nodeTop = $node.offsetTop; 
    } 

    var pos = {left: 0, top: 0}; 

    if (document.selection){ 
     var range = document.selection.createRange(); 
     pos.left = range.offsetLeft + offsetx - nodeLeft + 'px'; 
     pos.top = range.offsetTop + offsety - nodeTop + 'px'; 
    }else if (window.getSelection){ 
     var sel = window.getSelection(); 
     var range = sel.getRangeAt(0).cloneRange(); 
     try{ 
      range.setStart(range.startContainer, range.startOffset-1); 
     }catch(e){} 
     var rect = range.getBoundingClientRect(); 
     if (range.endOffset == 0 || range.toString() === ''){ 
      // first char of line 
      if (range.startContainer == $node){ 
       // empty div 
       if (range.endOffset == 0){ 
        pos.top = '0px'; 
        pos.left = '0px'; 
       }else{ 
        // firefox need this 
        var range2 = range.cloneRange(); 
        range2.setStart(range2.startContainer, 0); 
        var rect2 = range2.getBoundingClientRect(); 
        pos.left = rect2.left + offsetx - nodeLeft + 'px'; 
        pos.top = rect2.top + rect2.height + offsety - nodeTop + 'px'; 
       } 
      }else{ 
       pos.top = range.startContainer.offsetTop+'px'; 
       pos.left = range.startContainer.offsetLeft+'px'; 
      } 
     }else{ 
      pos.left = rect.left + rect.width + offsetx - nodeLeft + 'px'; 
      pos.top = rect.top + offsety - nodeTop + 'px'; 
     } 
    } 
    return pos; 
}; 
+0

अच्छा जवाब दोस्त! –

+0

इस समस्या के साथ, जैसा कि मैंने अपने उत्तर में बताया है, यह है कि 'range.getBoundingClientRect()' फ़ायरफ़ॉक्स और अन्य ब्राउज़रों में कभी-कभी एक रेक्ट को एक संक्षिप्त श्रृंखला के लिए सभी शून्यों को वापस कर देता है। एक उदाहरण के लिए http://jsfiddle.net/CK3e8/ देखें। –

+0

यह सच है, समय। मैंने चयन को एक चरित्र को वापस ले जाने की कोशिश की, और वहां से कैरेट की स्थिति का काम किया। – osamu

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