2009-08-17 20 views
7

如果我在HTML文檔中有兩個節點,那麼如何判斷使用DOM方法的Javascript文檔中,哪一個以HTML文檔順序排在第一位?確定來自節點的文檔順序

例如,

function funstuff(a, b) { 
    //a and b can be any node in the DOM (text, element, etc) 
    if(b comes before a in document order) { 
     var t = b; b = a; a = t; 
    } 
    // process the nodes between a and b. I can handle this part 
    // when I know that a comes before b. 
} 

回答

5

Resig to the rescue

// Compare Position - MIT Licensed, John Resig 
function comparePosition(a, b){ 
    return a.compareDocumentPosition ? 
    a.compareDocumentPosition(b) : 
    a.contains ? 
     (a != b && a.contains(b) && 16) + 
     (a != b && b.contains(a) && 8) + 
     (a.sourceIndex >= 0 && b.sourceIndex >= 0 ? 
      (a.sourceIndex < b.sourceIndex && 4) + 
      (a.sourceIndex > b.sourceIndex && 2) : 
      1) + 
     0 : 
     0; 
} 
+0

應該指出,Resig的方法只能在元素節點上工作,而不能在文本節點上工作。 – Michael 2009-09-16 19:33:29

+0

是的。文本節點沒有.sourceIndex,並且沒有.contains()。 – Michael 2009-09-17 18:35:54

+0

&&在所有這些情況下都不會做任何事情,因爲RHS總是如此。 – gsnedders 2011-04-12 11:43:41

1

相當困難,我個人itterate高達每個樹,直到我發現一個共同的ansester,然後檢查該父節點(或者如果該低實際節點)是一第一開始則firstChild並通過兄弟姐妹的工作,是這樣的:

function OrderCheck(node1, node2){ 

    var ar1 = [null, node1]; 
    var ar2 = [null, node2]; 

    for(var i = 1; ar1[i] != null; i++) 
     ar1[i+1]=ar1[i].parentNode; 
    for(var i = 1; ar2[i] != null; i++) 
     ar2[i+1]=ar2[i].parentNode; 
    ar1.reverse(); ar2.reverse(); // easier to work with. 
    i = 0; 
    while(ar1[i] === ar2[i]){ 
     if(ar1[i] === null) 
     return 0; 
     else 
     i++ 
    } 

    if(ar1[i] === null) 
     return 2; 
    if(ar2[i] === null) 
     return 1; 

    if(i != 0){ 
     var n = ar1[i-1].firstChild; 
     do{ 
     if(n === ar1[i]) 
      return 1; 
     if(n === ar2[i]) 
      return 2; 
     }while(n = n.nextSibling); 
    } 
     return -1;// Shouldn't happen. 
    } 

    var order = OrderCheck(document.body, document.body.previousSibling); 
    if(order == 1){ 
     // element 1 first 
    }else if(order == 2){ 
     // element 2 first 
    }else{ 
     // there was an error. 
    } 

我只是在嘗試解決兩個可能的問題,編輯該代碼,我沒有測試這種新的編輯但是,如果東西壞了,我得再次嘗試。 (再次修改以修復「不會運行」的風格錯誤)。

+0

尼斯的答案,但我認爲,如果一個節點失敗是另一個的祖先。你需要測試'i'超出任何一個數組的長度。 – Alohci 2009-08-17 23:52:21

+0

這是一個非常有趣的想法,比我想象的更有效率。如果沒有定義a.compareDocumentPosition(這是一個DOM 3方法),我將把它作爲回退來包含它。 謝謝! – Michael 2009-08-18 17:44:51

4

可以使用DOM功能compareDocumentPosition這將返回基於兩個節點關係不同的數字:

DOCUMENT_POSITION_DISCONNECTED = 0x01; 
DOCUMENT_POSITION_PRECEDING = 0x02; 
DOCUMENT_POSITION_FOLLOWING = 0x04; 
DOCUMENT_POSITION_CONTAINS = 0x08; 
DOCUMENT_POSITION_CONTAINED_BY = 0x10; 

潛在結果可能是這些代碼作爲一個以上的總和答案是一個掩碼,但我無法想象這兩種情況同時成立的情況。還要注意的是,「斷開連接」的結果將返回例如與已創建的節點,但不會添加到文檔樹又

+0

請注意* compareDocumentPosition *不受任何版本的Internet Explorer支持,直到幷包括IE 8。 – NickFitz 2009-08-18 09:32:13

+0

我認爲完整的解決方案將回退到scragar的代碼(如果未定義的話)。謝謝你的提示。 – Michael 2009-08-18 17:45:58

相關問題