2011-11-30 40 views
6

DOM4 compareDocumentPositiontrình duyệt chéo so sánh vị trí tài liệu

Tôi muốn triển khai compareDocumentPosition. Resig đã thực hiện great start at doing just this. Tôi đã lấy code của mình và neatened nó lên

function compareDocumentPosition(other) { 
    var ret = 0; 
    if (this.contains) { 
     if (this !== other && this.contains(other)) { 
      ret += 16; 
     } 
     if (this !== other && other.contains(this)) { 
      ret += 8; 
     } 
     if (this.sourceIndex >= 0 && other.sourceIndex >= 0) { 
      if (this.sourceIndex < other.sourceIndex) { 
       ret += 4; 
      } 
      if (this.sourceIndex > other.sourceIndex) { 
       ret += 2; 
      } 
     } else { 
      ret += 1; 
     } 
    } 
    return ret; 
} 

này làm việc cho Element nhưng không cho Text hoặc DocumentFragment. Điều này là do IE8 không cung cấp cho .sourceIndex trên các nút đó. (Nó không cung cấp cho .contains một trong hai nhưng tôi đã cố định vấn đề đó đã được)

Làm thế nào để có hiệu quả viết +=4+=2 chút tương ứng với DOCUMENT_POSITION_FOLLOWINGDOCUMENT_POSITION_PRECEDING.

Đối với thêm tài liệu tham khảo hai được xác định bằng cây đặt hàng mà DOM4 định nghĩa như

Một đối tượng A được trước một đối tượng B nếu A và B trong cùng một cây và A đứng trước B để cây .

Một đối tượng A theo một đối tượng B nếu A và B nằm trong cùng một cây và A đến sau B theo thứ tự cây.

Thứ tự cây được đặt hàng trước, trải qua chiều sâu đầu tiên.

Hầu hết các trình duyệt hiện đại đều thực hiện điều này (bao gồm IE9). Vì vậy, bạn chỉ cần một cái gì đó mà làm việc trong IE8 (Tôi không quan tâm về IE6/7, nhưng nếu nó hoạt động tuyệt vời!)

Trả lời

10
function recursivelyWalk(nodes, cb) { 
    for (var i = 0, len = nodes.length; i < len; i++) { 
     var node = nodes[i]; 
     var ret = cb(node); 
     if (ret) { 
      return ret; 
     } 
     if (node.childNodes && node.childNodes.length) { 
      var ret = recursivelyWalk(node.childNodes, cb); 
      if (ret) { 
       return ret; 
      } 
     } 
    } 
} 

function testNodeForComparePosition(node, other) { 
    if (node === other) { 
     return true; 
    } 
} 

function compareDocumentPosition(other) { 
    function identifyWhichIsFirst(node) { 
     if (node === other) { 
      return "other"; 
     } else if (node === reference) { 
      return "reference"; 
     } 
    } 

    var reference = this, 
     referenceTop = this, 
     otherTop = other; 

    if (this === other) { 
     return 0; 
    } 
    while (referenceTop.parentNode) { 
     referenceTop = referenceTop.parentNode; 
    } 
    while (otherTop.parentNode) { 
     otherTop = otherTop.parentNode; 
    } 

    if (referenceTop !== otherTop) { 
     return Node.DOCUMENT_POSITION_DISCONNECTED; 
    } 

    var children = reference.childNodes; 
    var ret = recursivelyWalk(
     children, 
     testNodeForComparePosition.bind(null, other) 
    ); 
    if (ret) { 
     return Node.DOCUMENT_POSITION_CONTAINED_BY + 
      Node.DOCUMENT_POSITION_FOLLOWING; 
    } 

    var children = other.childNodes; 
    var ret = recursivelyWalk(
     children, 
     testNodeForComparePosition.bind(null, reference) 
    ); 
    if (ret) { 
     return Node.DOCUMENT_POSITION_CONTAINS + 
      Node.DOCUMENT_POSITION_PRECEDING; 
    } 

    var ret = recursivelyWalk(
     [referenceTop], 
     identifyWhichIsFirst 
    ); 
    if (ret === "other") { 
     return Node.DOCUMENT_POSITION_PRECEDING; 
    } else { 
     return Node.DOCUMENT_POSITION_FOLLOWING; 
    } 
} 

Tôi đã tự viết. Tôi nghĩ rằng việc thực hiện này đã bị lỗi nhưng đó là một lỗi trong một số mã khác của tôi. Có vẻ khá vững chắc.

+5

Oh Raynos, bạn tuyệt vời . Cảm ơn bạn đã trả lời câu hỏi của tôi – Raynos

+0

Bạn có ổn không ....? –

+0

@TimDown Tôi không ngủ đủ. – Raynos

0

Câu trả lời từ Raynos là sự khởi đầu hàng đầu, nhưng không thể chạy ra khỏi hộp. Không thể tìm thấy Node.*.bind không có trong IE8.

Đây là mã sẵn sàng để sử dụng trong trình duyệt Internet Explorer 8:

function recursivelyWalk(nodes, cb) { 
    for (var i = 0, len = nodes.length; i < len; i++) { 
     var node = nodes[i]; 
     var ret = cb(node); 
     if (ret) { 
      return ret; 
     } 
     if (node.childNodes && node.childNodes.length) { 
      var ret = recursivelyWalk(node.childNodes, cb); 
      if (ret) { 
       return ret; 
      } 
     } 
    } 
} 

function testNodeForComparePosition(node, other) { 
    if (node === other) { 
     return true; 
    } 
} 

var DOCUMENT_POSITION_DISCONNECTED = 1; 
var DOCUMENT_POSITION_PRECEDING = 2; 
var DOCUMENT_POSITION_FOLLOWING = 4; 
var DOCUMENT_POSITION_CONTAINS = 8; 
var DOCUMENT_POSITION_CONTAINED_BY = 16; 

function compareDocumentPosition(thisNode, other) { 
    function identifyWhichIsFirst(node) { 
     if (node === other) { 
      return "other"; 
     } else if (node === reference) { 
      return "reference"; 
     } 
    } 

    var reference = thisNode, 
     referenceTop = thisNode, 
     otherTop = other; 

    if (this === other) { 
     return 0; 
    } 
    while (referenceTop.parentNode) { 
     referenceTop = referenceTop.parentNode; 
    } 
    while (otherTop.parentNode) { 
     otherTop = otherTop.parentNode; 
    } 

    if (referenceTop !== otherTop) { 
     return DOCUMENT_POSITION_DISCONNECTED; 
    } 

    var children = reference.childNodes; 
    var ret = recursivelyWalk(
     children, 
     function(p) { 
      (function() { 
       var localOther = other; 
       return testNodeForComparePosition(localOther, p); 
      })(); 
     } 
    ); 
    if (ret) { 
     return DOCUMENT_POSITION_CONTAINED_BY + 
      DOCUMENT_POSITION_FOLLOWING; 
    } 

    var children = other.childNodes; 
    var ret = recursivelyWalk(
     children, 
     function(p) { 
      (function() { 
       var localOther = reference; 
       return testNodeForComparePosition(localOther, p); 
      })(); 
     } 
    ); 
    if (ret) { 
     return DOCUMENT_POSITION_CONTAINS + 
      DOCUMENT_POSITION_PRECEDING; 
    } 

    var ret = recursivelyWalk(
     [referenceTop], 
     identifyWhichIsFirst 
    ); 
    if (ret === "other") { 
     return DOCUMENT_POSITION_PRECEDING; 
    } else { 
     return DOCUMENT_POSITION_FOLLOWING; 
    } 
} 

Bạn gọi nó là như thế này:

compareDocumentPosition(sourceElement, elementToTest) 

(Nó giống như gọi sourceElement.compareDocumentPosition(elementToTest))

Các vấn đề liên quan