2009-08-17 14 views
7

Se si dispone di due nodi in un documento HTML, come si può sapere quale viene prima nell'ordine di documento HTML in Javascript utilizzando i metodi DOM?Determinazione dell'ordine documento dai nodi

Per esempio,

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. 
} 

risposta

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

Si noti che il metodo Resig funzionerà solo sui nodi degli elementi, non sui nodi di testo. – Michael

+0

Sì. I nodi di testo non hanno .sourceIndex e non hanno .contains(). – Michael

+0

&& non fa nulla in tutti questi casi, perché l'RHS è sempre vero. – gsnedders

1

Piuttosto difficile, io personalmente sarebbe itterate up ogni albero finché non ho trovato un ansester comune, allora verificare quale nodo padre (o il nodo reale, se così in basso) viene prima di partire con firstChild e di lavoro attraverso i fratelli, qualcosa di simile:

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. 
    } 

mi basta modificare questo codice, nel tentativo di risolvere due possibili problemi, non ho ancora testato questa nuova modifica però, quindi se qualcosa si rompe dovrò riprovare . (Modificato di nuovo per correggere un errore di stile "non funziona nemmeno").

+0

bella risposta, ma penso che questo non riesce se un nodo è l'antenato dell'altro. È necessario testare per 'i' andare oltre la lunghezza di uno degli array. – Alohci

+0

È un'idea molto interessante, molto più efficiente di quella a cui avevo pensato. Lo includerò come ripiego se a.compareDocumentPosition non è definito (è un metodo DOM 3). Grazie! – Michael

4

È possibile utilizzare la funzione DOM compareDocumentPosition che restituirà numeri diversi in base alle relazioni dei due nodi:

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

Potenzialmente il risultato potrebbe essere la somma di più di uno di questi codici come la risposta è una maschera di bit, ma non riesco a immaginare una situazione in cui due di queste condizioni sarebbero vere allo stesso tempo. Si noti inoltre che il risultato "disconnesso" sarebbe tornato per esempio con i nodi che sono state create, ma non aggiunto alla struttura del documento ancora

+0

Si noti che * compareDocumentPosition * non è supportato da alcuna versione di Internet Explorer, fino a IE incluso. – NickFitz

+0

Penso che la soluzione completa sarà quella di ricorrere al codice scragar se non è definito. Grazie per il consiglio. – Michael

Problemi correlati