not ejemplo javascript dom

not - getelementbyid javascript ejemplo



¿Cómo puedo determinar si un elemento DOM creado dinámicamente se ha agregado al DOM? (11)

Según las especificaciones , solo los elementos BODY y FRAMESET proporcionan un evento "onload" para adjuntar, pero me gustaría saber cuándo se ha agregado un elemento DOM creado dinámicamente al DOM en JavaScript.

La heurística super ingenua que estoy usando actualmente, que funciona, es la siguiente:

  • Atraviese la propiedad parentNode del elemento hasta que encuentre el ancestro final (es decir, parentNode.parentNode.parentNode.etc hasta que parentNode sea nulo)

  • Si el ancestro final tiene una propiedad corporal definida y no nula

    • asumir que el elemento en cuestión es parte de la dom
  • más

    • repita estos pasos nuevamente en 100 milisegundos

Lo que busco es la confirmación de que lo que estoy haciendo es suficiente (una vez más, está funcionando tanto en IE7 como en FF3) o una solución mejor que, por alguna razón, no he tenido en cuenta; quizás otras propiedades que debería verificar, etc.

EDITAR: Quiero una forma de hacer esto, no vivo en un navegador, desafortunadamente; Dicho esto, se agradece la información específica del navegador, pero tenga en cuenta qué navegador sabe que funciona. ¡Gracias!


¿No puedes hacer un document.getElementById(''newElementId''); y ver si eso vuelve verdadero. Si no es así, como dices, espera 100ms e intenta de nuevo?


ACTUALIZACIÓN: Para cualquier persona interesada en esto, aquí está la implementación que finalmente utilicé:

function isInDOMTree(node) { // If the farthest-back ancestor of our node has a "body" // property (that node would be the document itself), // we assume it is in the page''s DOM tree. return !!(findUltimateAncestor(node).body); } function findUltimateAncestor(node) { // Walk up the DOM tree until we are at the top (parentNode // will return null at that point). // NOTE: this will return the same node that was passed in // if it has no ancestors. var ancestor = node; while(ancestor.parentNode) { ancestor = ancestor.parentNode; } return ancestor; }

La razón por la que quería esto es proporcionar una forma de sintetizar el evento de onload para los elementos DOM. Aquí está esa función (aunque estoy usando algo ligeramente diferente porque lo estoy usando junto con MochiKit ):

function executeOnLoad(node, func) { // This function will check, every tenth of a second, to see if // our element is a part of the DOM tree - as soon as we know // that it is, we execute the provided function. if(isInDOMTree(node)) { func(); } else { setTimeout(function() { executeOnLoad(node, func); }, 100); } }

Por ejemplo, esta configuración se puede usar de la siguiente manera:

var mySpan = document.createElement("span"); mySpan.innerHTML = "Hello world!"; executeOnLoad(mySpan, function(node) { alert(''Added to DOM tree. '' + node.innerHTML); }); // now, at some point later in code, this // node would be appended to the document document.body.appendChild(mySpan); // sometime after this is executed, but no more than 100 ms after, // the anonymous function I passed to executeOnLoad() would execute

Espero que sea útil para alguien.

NOTA: la razón por la que terminé con esta solución en lugar de la respuesta de Darryl fue porque la técnica getElementById solo funciona si estás dentro del mismo documento; Tengo algunos iframes en una página y las páginas se comunican entre sí de formas complejas: cuando probé esto, el problema era que no podía encontrar el elemento porque era parte de un documento diferente al código en el que se estaba ejecutando. .


Aquí hay otra solución al problema extraído del código jQuery. La siguiente función se puede usar para verificar si un nodo está conectado al DOM o si está "desconectado".

function isDisconnected( node ) { return !node || !node.parentNode || node.parentNode.nodeType === 11; }

Un nodeType === 11 define un DOCUMENT_FRAGMENT_NODE, que es un nodo no conectado al objeto del documento.

Para obtener más información, consulte el siguiente artículo de John Resig: http://ejohn.org/blog/dom-documentfragments/


Desea el evento DOMNodeInserted (o DOMNodeInsertedIntoDocument ).

Editar: Es completamente posible que estos eventos no sean compatibles con IE, pero no puedo probar eso ahora.



En un mundo perfecto podrías conectar los eventos de mutación. Tengo dudas de que funcionen de manera confiable incluso en navegadores estándar. Parece que ya ha implementado un evento de mutación, por lo que posiblemente podría agregarlo para usar un evento de mutación nativo en lugar de un conteo de tiempo de espera en los navegadores compatibles.

He visto implementaciones de DOM-change que supervisan los cambios al comparar document.body.innerHTML con la última .innerHTML guardada, .innerHTML , que no es exactamente elegante (pero funciona). Como en última instancia va a verificar si se ha agregado un nodo específico, entonces es mejor que solo revise cada interrupción.

Las mejoras que puedo pensar son usando .offsetParent lugar de .parentNode ya que es probable que .parentNode a algunos padres de su ciclo (ver comentarios). O usando compareDocumentIndex() en todos los IE excepto y probando .sourceIndex para IE (debería ser -1 si el nodo no está en el DOM).

Esto también podría ayudar: X browser compareDocumentIndex implementación de John Resig .


La respuesta más directa es hacer uso del método Node.contains , compatible con Chrome, Firefox (Gecko), Internet Explorer, Opera y Safari. Aquí hay un ejemplo:

var el = document.createElement("div"); console.log(document.body.contains(el)); // false document.body.appendChild(el); console.log(document.body.contains(el)); // true document.body.removeChild(el); console.log(document.body.contains(el)); // false

Idealmente, usaríamos document.contains(el) , pero eso no funciona en IE, entonces usamos document.body.contains(el) .

Desafortunadamente, todavía tiene que sondear, pero verificar si un elemento está en el documento es muy simple:

setTimeout(function test() { if (document.body.contains(node)) { func(); } else { setTimeout(test, 50); } }, 50);

Si está de acuerdo con agregar algo de CSS a su página, aquí hay otra técnica inteligente que usa animaciones para detectar inserciones de nodos: http://www.backalleycoder.com/2012/04/25/i-want-a-damnodeinserted/


Ninguno de los eventos DOMNodeInserted o DOMNodeInsertedIntoDocument es compatible con IE. Otra característica que falta en IE [solo] de DOM es la función compararDocumentPosition que está diseñada para hacer lo que sugiere su nombre.

En cuanto a la solución sugerida, creo que no hay una mejor (a menos que haga algunos trucos sucios como sobreescribir implementaciones de miembros DOM nativos)

Además, se corrige el título de la pregunta: el elemento creado dinámicamente forma parte del DOM desde el momento de su creación, se puede adjuntar a un fragmento de documento, oa otro elemento, pero puede que no se anexe a un documento.

También creo que el problema que describiste no es el problema que tienes, este parece ser una de las posibles soluciones a tu problema. ¿Puede probablemente explicar en detalles el caso de uso?


Puede consultar document.getElementsByTagName ("*"). Length o crear una función appendChild personalizada como la siguiente:

var append = function(parent, child, onAppend) { parent.appendChild(child); if (onAppend) onAppend(child); } //inserts a div into body and adds the class "created" upon insertion append(document.body, document.createElement("div"), function(el) { el.className = "created"; });

Actualizar

A pedido, agregando la información de mis comentarios a mi publicación

Hubo un comentario de John Resig en la biblioteca Peppy en Ajaxian hoy que parecía sugerir que su biblioteca Sizzle podría ser capaz de manejar eventos de inserción DOM. Tengo curiosidad por ver si habrá código para manejar IE también

Siguiendo con la idea de sondeo, he leído que algunas propiedades de los elementos no están disponibles hasta que el elemento se haya agregado al documento (por ejemplo, element.scrollTop), tal vez podrías sondear eso en lugar de hacer todo el recorrido DOM.

Una última cosa: en IE, un enfoque que podría valer la pena explorar es jugar con el evento onpropertychange. Considero que al anexarlo al documento está obligado a activar ese evento para al menos una propiedad.


Un MutationObserver es lo que debe usar para detectar cuándo se ha agregado un elemento al DOM. Los servidores de mutación ahora son ampliamente compatibles en todos los navegadores modernos (Chrome 26+, Firefox 14+, IE11, Edge, Opera 15+, etc.).

Aquí hay un ejemplo simple de cómo puedes usar un MutationObserver para escuchar cuando se agrega un elemento al DOM.

Para abreviar, estoy usando la sintaxis de jQuery para construir el nodo e insertarlo en el DOM.

var myElement = $("<div>hello world</div>")[0]; var observer = new MutationObserver(function(mutations) { if (document.contains(myElement)) { console.log("It''s in the DOM!"); observer.disconnect(); } }); observer.observe(document, {attributes: false, childList: true, characterData: false, subtree:true}); $("body").append(myElement); // console.log: It''s in the DOM!

El controlador de eventos del observer se activará siempre que se agregue o elimine cualquier nodo del document . Dentro del manejador, luego realizamos un control de contenido para determinar si myElement está ahora en el document .

No necesita iterar sobre cada registro de mutación almacenado en mutations porque puede realizar el document.contains . myElement verificación directamente sobre myElement .

Para mejorar el rendimiento, reemplace el document con el elemento específico que contendrá myElement en el DOM.


var finalElement=null;

Estoy construyendo objetos dom en un bucle, cuando el ciclo está en el último ciclo y se creó el último objeto lastDomObject :

finalElement=lastDomObject;

dejar el bucle:

while (!finalElement) { } //this is the delay...

La siguiente acción puede usar cualquiera de los objetos dom recién creados. Funcionó en el primer intento.