2011-12-10 38 views
12

ile iframe içinde geçerli şapka pozisyonundan ofset almak nasıl kullanıcı (otomatik tamamlama amaçlı) belli bir tuş kombinasyonunu girdiği durumda, contentEditable ile iframe kayan div elemanı konumlandırmak istiyoruz . piksel contentEditable

Ben İnceltme pozisyon almak için biliyorum: document.getElementById('elm1_ifr').contentWindow.getSelection().anchorOffset

Ben div left özelliğini hesaplamak için kullanabilir, ama top nasıl anlamaya görünüyor olamaz.

ben kullanıyordum düşündüm başka olasılık: document.getElementById('elm1_ifr').contentWindow.getSelection().anchorNode.parentNode

Ve ofset almak için jQuery kullanarak, ama bu ebeveyn uzun metin satırı varsa, sadece ilk satırın üst konumda ayıklamak mümkün olacaktır .

Bu konuda bana yardımcı olan var mı?

cevap

12

Bunu yapmanın tek güvenilir yolu, karta (geçici olarak sıfır olduğundan emin olmak) geçici bir eleman eklemek, yerini almak ve tekrar çıkarmaktır. Aynı zamanda, düğümün düğümü yerleştirmeden önce olduğu gibi olduğundan emin olmak için, metin düğümünün iki ucunu (gösterge içeren bir metin düğümüyse) tekrar birbirine yapıştırmalısınız. Bununla birlikte, bunu (veya düzenlenebilir içerik üzerinde başka herhangi bir manuel DOM işlemi) yapmanın tarayıcının dahili geri alma kümesini kırdığını unutmayın. Bunun nedeni, the spec for the getBoundingClientRect() method of Range'un dikkatli okunmasının, getBoundingClientRect()'un daraltılmış bir Aralık için bir Rect döndürmek zorunda olmadığını göstermesidir. Kavramsal olarak, belgedeki her konum iyi tanımlanmış bir sınırlama dikdörtgenine sahip değildir. Ancak, karta, bence seçim API'sı tarafından sağlanmalıdır, ancak fiziksel olarak şu anda ekranda görünmesi gerekir, ancak şu anda bunu sağlamak için tarayıcılarda hiçbir şey yoktur.

+2

sonra, geçerli şapka konumu 0'dan olmak aralığı ayarlamak sol + genişlik ve üst + yükseklik uzaklıklar almak için 'getBoundingClientRect()' kullanılamadı, daha sonra düzeltme işaretini geri ayar? – Mottie

+3

Eski iş parçacığı evet, ancak [execCommand ('insertHTML') '] işlevini kullanarak bir öğenin eklenmesini ve geri almanın geri almayı/geri alma yığınını karıştırdığını nting değerinde. Geri alma/yineleme önemsiz ise önemli değil. – techfoobar

+0

@techfoobar: İyi nokta, teşekkürler. Cevaba bir not ekledim. –

7

Bu soruna bugün geldim. Bazı testlerden sonra, bu çalışmayı geçici eleman kullanmadan aldım.

IE'de, bir TextRange nesnesinin offsetLeft ve offsetTop özelliği ile çalışması kolaydır. Ancak web grubu için biraz çaba gerekiyor.

İşte bir test, sonucunu görebilirsiniz. önceki bulunuyor için 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

Güzel cevap arkadaşın! –

+0

Bunun cevabı, benim cevabımda ima ettiğim gibi, Firefox'taki range.getBoundingClientRect() 'in ve diğer tarayıcıların bazen daraltılmış bir aralık için tüm sıfırları içeren bir Rect döndürmesidir. Bir örnek için http://jsfiddle.net/CK3e8/ adresine bakın. –

+0

Bu doğru, Tim. Seçimi bir karakterin arkasına taşımayı denedim, ve caret pozisyonunu oradan çıkarmaya çalıştım. – osamu