2012-02-17 23 views
5

szukam rozwiązania przekroju przeglądarki (Chrome, FF, Opera> 10, IE> = 8) na następujący problem:Sprawdź, czy określony element ma wewnątrz wybór

Jest jakiś kod html:

<div> 
    <div id="one"> 
     <p id="red">red</p> 
     <p id="green">green</p> 
    </div> 
    <div id="two"> 
     <p id="blue">blue</p> 
     <p id="black">black</p> 
    </div> 
</div> 

i użytkownik wybiera tekstem myszy od "een" (w węźle #green) do "blu" (w węźle #blue). Jak mogę sprawdzić, czy #blue znajduje się wewnątrz selekcji (nie ma znaczenia, czy jest zaznaczone w całości czy częściowo), a #red i #black nie są zaznaczone. Proste API będzie wyglądać następująco:

Selection.isElementSelected(document.getElementById('black')); 

Próbowałem użyć DOMSelection i waha ale problemem jest to, że muszę sprawdzić elementy w zagnieżdżonej struktury. W Chrome mogę używać Range.intersectsNode(), ale jest to jedyna przeglądarka obsługująca tę metodę.

Wszelkie sugestie?

Odpowiedz

3

Po niektórych badań Zrobiłem rozwiązanie oparte na następujących materiałów: https://developer.mozilla.org/en/DOM/range

http://msdn.microsoft.com/en-us/library/ms535872(v=vs.85).aspx

http://www.quirksmode.org/dom/range_intro.html

W przypadku IE8 całego węzła musi być wybrany, ale to jest do zaakceptowania dla mnie.

Oto jest jakiś plac zabaw na jsfiddle: http://jsfiddle.net/58Uvd/ A oto kod:

(function() { 

    function UserRange (win) { 
     this.win = win || window; 
     this.doc = this.win.document; 

     this.userRange = this.createUserRange(); 
    } 

    var NonIEPrototype = { 

     constructor: UserRange, 

     createUserRange: function() { 
      var selection = this.win.getSelection(); 
      return selection.rangeCount 
       ? selection.getRangeAt(0) 
       : this.doc.createRange(); 
     }, 

     overlapsNode: function (node) { 
      return this.intersectsNode(node); 
     }, 


     intersectsNode: function (node) { 
      // this method is implemented in Firefox with Gecko before 1.9 
      // and other non-IE browsers 
      if (this.userRange.intersectsNode) { 
       return this.userRange.intersectsNode(node); 
      } 

      return this.intersectsRange(this.createRangeWithNode(node)); 
     }, 

     createRangeWithNode: function (node) { 
      var rangeWithNode = node.ownerDocument.createRange(); 
      try { 
       rangeWithNode.selectNode(node); 
      } 
      catch (ex) { 
       rangeWithNode.selectNodeContents(node); 
      } 
      return rangeWithNode; 
     }, 

     intersectsRange: function (range) { 
      return this.userRange.compareBoundaryPoints(Range.END_TO_START, range) === -1 && 
       this.userRange.compareBoundaryPoints(Range.START_TO_END, range) === 1; 
     } 
    }; 

    var IEPrototype = { 

     constructor: UserRange, 

     createUserRange: function() { 
      return this.doc.selection.createRange(); 
     }, 

     overlapsNode: function (node) { 
      var rangeWithNode = this.createRangeWithNode(node); 
      return this.containsRange(rangeWithNode); 
     }, 

     createRangeWithNode: function (node) { 
      var range = node.ownerDocument.selection.createRange(); 
      range.moveToElementText(node); 
      return range; 
     }, 

     containsRange: function (range) { 
      return this.userRange.inRange(range); 
     } 
    }; 

    UserRange.prototype = window.getSelection ? NonIEPrototype : IEPrototype; 
    window.UserRange = UserRange; 

}()); 

i użytkowania:

var userRange = new UserRange(); 
userRange.overlapsNode(document.getElementById('node-to-check')); 
+0

Może to pomaga na doskonały wynik w IE <9: containsRange: function (range) { return this.userRange.inRange (range) || range.inRange (this.userRange) || this.userRange.compareEndPoints ("EndToStart", zakres)> -1 && this.userRange.compareEndPoints ("StartToEnd", zakres) <1; } –

Powiązane problemy