2010-04-12 12 views
12

Me gustaría poder identificar si un nodo DOM dado se ha anexado/insertado en otro nodo aún, o si es recién salido de document.createElement() o similar y no se ha colocado en ninguna parte.Javascript: cómo saber si un objeto nodo se ha insertado en un documento/otro elemento aún

En la mayoría de los navegadores, solo se comprueba que parentNode funcione.

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

Sin embargo, en Internet Explorer parece que los nuevos elementos, incluso justo después de que hayan sido creados con document.createElement() ya tienen un objeto parentNode (de tipo DispHTMLDocument ??).

¿Alguna otra buena navegación cruzada y manera confiable?

Editar: parece que Internet Explorer está creando implícitamente una DocumentFragment (con nodeType de 11) y el establecimiento de que a medida que la propiedad parentNode del nodo.

+0

He editado la pregunta un poco porque no estaba bien expresada. Perdón por nickf que me dio una gran respuesta pero ¡exagerado por lo que realmente quería! – thomasrutter

Respuesta

5

he encontrado una respuesta a mi propia pregunta. ¡Lo siento! Parece que estoy haciendo eso mucho últimamente.

fragmentos de documentos tienen un nodeType de 11 años, y nunca se insertan en el documento, para que pueda comprobar de esta manera:

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

Sólo es necesario un fragmento del documento cuando se va a insertar más de un nodo de pares . Sin embargo, IE crea implícitamente uno para todos los nodos recién creados. De todos modos, verificando el nodeType para 11 funciona.

+0

Eso podría no funcionar si el nodo de interés está anidado. Se definirá la propiedad parentNode y el nodeType de parentNode puede ser distinto de 11 (Node Element o 1 por ejemplo). La solución de Nick parece ser una forma de sureshot de saber si un nodo está conectado. – Anurag

+0

Pero eso es lo que quiero. Si está "anidado" como dices, considero que se ha insertado en un elemento. Quiero detectar nodos que flotan libremente, y mi definición de eso fue "sin padre". Ahora, debido al comportamiento de IE, tuve que expandir esa definición a "sin padre, o un DocumentFragment como padre". – thomasrutter

6

Creo que incluso sin las debilidades de IE, la comprobación de la presencia de parentNode podría no ser suficiente. Por ejemplo:

var d = document.createElement('div'); 
var s = document.createElement('span'); 
d.appendChild(s); 
if (s.parentNode) { 
    // this will run though it's not in the document 
} 

Si hay algo en el documento y, a continuación, finalmente, uno de sus antepasados ​​será el propio documento. Trate de hacer esto y ver cómo va:

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

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

Si sólo desea comprobar hasta una cierta profundidad - es decir, usted sabe que sus elementos recién creados no van a ser anidado más allá Fragmento de IE, intente esto:

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

Gracias nickf; en mi caso, sin embargo, solo estoy preocupado por el padre inmediato; no me importa si su abuelo, o un antepasado, no es parte del elemento del documento, solo si ese elemento dado ha sido 'anexado' o 'insertado' en cualquier lugar todavía. En otras palabras, en el primer ejemplo de código no me preocupa que d no se inserte en algún lugar, ya que s * es *. – thomasrutter

+0

@thomasrutter en ese caso, podría cortocircuitar el ciclo después de dos saltos. El parentNode del DocumentFragment que crea IE debería ser nulo. – nickf

+0

La suya es la respuesta más concisa a "cómo saber si un nodo se ha insertado en el documento". Solo soy un fracaso para expresar lo que realmente quería. – thomasrutter

2

DOM nivel 3 introdujo el método compareDocumentPosition para un Node que proporciona información posicional sobre cómo dos nodos están relacionados entre sí. Uno de los valores devueltos es DOCUMENT_POSITION_DISCONNECTED, lo que significa que los nodos no están conectados entre sí. Podría utilizar este hecho para comprobar si un nodo no está contenido dentro de otro nodo mediante:

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 escrito una aplicación multi-navegador (creo, no se menciona es decir, no) de una función contains que se pueden encontrar al http://code.google.com/p/doctype-mirror/wiki/ArticleNodeContains.Usted podría utilizar eso para comprobar si un determinado nodo es un descendiente del documento

.contains(document, someNode) 
0

En la versión de IE fueron que las pruebas de este:


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

tal vez con versiones antiguas de IE debería probar:


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

en su lugar.

Aunque en nueves obtendrá >> nula < < con ambos enfoques siempre que el elemento contenedor superior creada todavía no se analiza que a su vez se traduce en >> falsa < < exactamente como lo quería.

Cuestiones relacionadas