2010-04-12 15 views
12

Mi piacerebbe essere in grado di identificare se un dato nodo DOM è stato aggiunto/inserito in un altro nodo ancora, o se è appena uscito da document.createElement() o simile e non è stato inserito da nessuna parte.Javascript: come stabilire se un oggetto nodo è stato inserito in un documento/in un altro elemento ancora

Nella maggior parte dei browser è sufficiente controllare il genitoreNodo.

if (!node.parentNode) { 
    // this node is not part of a larger document 
} 

Tuttavia, in Internet Explorer sembra che nuovi elementi, anche subito dopo che sono stati creati con document.createElement() hanno già un oggetto parentNode (di tipo DispHTMLDocument ??).

Qualsiasi altro browser cross-friendly e affidabile?

Modifica: sembra che Internet Explorer stia implicitamente creando un DocumentFragment (con nodeType di 11) e impostandolo come proprietà parentNode del nodo.

+0

Ho modificato la domanda un po 'perché non era ben espressa. Mi dispiace per nickf che ha fornito un'ottima risposta ma eccessivo per quello che volevo davvero! – thomasrutter

risposta

5

Ho trovato una risposta alla mia domanda. Scusate! Sembra che lo stia facendo molto ultimamente.

frammenti del documento hanno un nodeType di 11 anni, e non sono mai inserite nel documento, in modo da poter controllare in questo modo:

if (!node.parentNode || node.parentNode.nodeType == 11) { 
    // this node is floating free 
} 

Hai solo bisogno di un frammento di documento quando si inserisce più di un nodo peer . Tuttavia, IE ne crea implicitamente uno per tutti i nodi appena creati. Ad ogni modo controllando il nodeType per 11 lavori.

+0

Potrebbe non funzionare se il nodo di interesse è nidificato. La proprietà parentNode sarà definita e il nodeType di parentNode potrebbe essere diverso da 11 (Nodo elemento o 1 per esempio). La soluzione di Nick sembra essere un modo sureshot per sapere se un nodo è collegato. – Anurag

+0

Ma è quello che voglio. Se è "annidato" come dici tu, lo considero come inserito in un elemento. Voglio rilevare nodi che sono liberi di fluttuare, e la mia definizione era "senza genitore". Ora, a causa del comportamento di IE, ho dovuto estendere tale definizione a "senza genitore o a DocumentFragment come genitore". – thomasrutter

6

Penso che anche senza le debolezze di IE, il controllo della presenza di parentNode potrebbe non essere sufficiente. Ad esempio:

Se qualcosa è presente nel documento, alla fine uno dei suoi antenati sarà il documento stesso. Prova questo fuori e vedere come va:

function inDocument(node) { 
    var curr = node; 
    while (curr != null) { 
     curr = curr.parentNode; 
     if (curr == document) return true; 
    } 
    return false; 
} 

// usage: 
// if (inDocument(myNode)) { .. } 

Se desideri solo controllare per una certa profondità - che è, si sa che gli elementi appena creati non stanno per essere nidificati più in là Frammento di IE, prova questo:

function inDocument(node, depth) { 
    depth = depth || 1000; 
    var curr = node; 
    while ((curr != document) && --depth) { 
     curr = curr.parentNode; 
     if (curr == null) return false; 
    } 
    return true; 
} 

inDocument(myNode, 2); // check only up to two deep. 
inDocument(myNode);  // check up to 1000 deep. 
+0

Grazie nickf - nel mio caso però sono solo preoccupato per il genitore immediato - Non mi importa se il suo nonno, o un antenato, non fa parte dell'elemento del documento, solo se quell'elemento dato è stato "aggiunto" o 'inserito' ovunque ancora. Quindi, in altre parole nel tuo primo esempio di codice, non mi interessa che d non sia inserito da qualche parte, come s * è *. – thomasrutter

+0

@thomasrutter in tal caso, potresti cortocircuitare il loop dopo due hop. Il parentNode di DocumentFragment che IE crea dovrebbe essere, si spera, nullo. – nickf

+0

La tua è la risposta più concisa a "come puoi capire se un nodo è stato inserito nel documento". Sono solo un fallimento nell'esprimere ciò che volevo davvero. – thomasrutter

2

Il livello 3 del DOM ha introdotto il metodo compareDocumentPosition per un Node che fornisce informazioni posizionali su come due nodi sono correlati tra loro. Uno dei valori di ritorno è DOCUMENT_POSITION_DISCONNECTED, il che significa che i nodi non sono collegati tra loro. Potrebbe utilizzare questo fatto per verificare se un nodo non è contenuto all'interno di un altro nodo utilizzando:

Boolean(parent.compareDocumentPosition(descendant) & 16) 

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

Google ha scritto un'implementazione cross-browser (credo, non si parla di IE lì) di una funzione contains che può essere trovato allo http://code.google.com/p/doctype-mirror/wiki/ArticleNodeContains.Si potrebbe utilizzare tale per verificare se un determinato nodo è un discendente del documento

.contains(document, someNode) 
0

In quale versione di IE sono stati voi testando questo:


if (!node.parentNode) { 
    // this node is not part of a larger document 
} 

magari con vecchie versioni di IE si dovrebbe provare:


if (!node.parentElement) { 
    // this node is not part of a larger document 
} 

invece.

Anche se su nove si otterrà nulla >> < < con entrambi gli approcci a condizione che la parte superiore creato elemento contenitore non è ancora analizzato che a sua volta si traduce in >> falsa < < esattamente come si voleva.

Problemi correlati