2012-03-19 10 views
7

Me gusta ejecutar scripts personalizados en páginas que no son de mi propiedad o control. Muchas veces estas páginas tienen contenido creado dinámicamente al cual me gustaría aplicarle una función.Controlador para nodos DOM creados dinámicamente a medida que se insertan

¿Esto es posible? Si es así, ¿cómo puedo hacer esto? Idealmente, estoy buscando algo en vivo en el método live de jQuery, excepto que en lugar de vincular un evento como click sería más como un evento que ocurre cuando el elemento se carga en el DOM. load evento funcionaría para algunos elementos pero no creo para nada ...

Para esta pregunta, suponga que no puede ver o cambiar el código que está insertando los nodos DOM. Me gustaría una técnica que podría usar en un UserScript o bookmarklet que podría usarse en múltiples sitios no relacionados.

Editar: Estoy buscando algo para usar en mi invertir colores bookmarklet: JavaScript: Invert color on all elements of a page

+0

¿Qué tipo de función está buscando para aplicar? Puede escuchar el evento 'DOMNodeInsertedIntoDocument', pero es probable que esto se aplique a muchos nodos insertados que no le interesarán. – nrabinowitz

+0

Estoy interesado en cada nodo en realidad. Estoy cambiando los colores de todo en la página. – Muhd

Respuesta

6

Suponiendo que se está ejecutando un navegador como Firefox o Chrome, se puede detectar el evento DOMNodeInserted:

$(document).on('DOMNodeInserted', function(e) { 
    $(e.target).css({ color : '#c00' }); 
}); 

$('body').append('<div>test</div>');​ 

violín: http://jsfiddle.net/VeF6g/ (probablemente falla en IE)

+1

Me gustaría señalar por el bien de los lectores aleatorios: no use los eventos de mutación si puede evitarlo. Detalles: http://lists.w3.org/Archives/Public/public-webapps/2011JulSep/0779.html – Nickolay

+1

@Nickolay - gracias por la referencia. Sé que es una mala idea en general usar estos, pero parece razonable para el caso de uso del OP (entre otras cosas, la discusión es sobre un script de usuario, por lo que será el único afectado por lentitud o fallas). – nrabinowitz

1

Esto es bastante difícil de lograr, porque no hay ningún caso viable para reaccionar a DOM cambios. Preferiría adherirme a la delegación de eventos en su lugar.

Pero hay algunos eventos que pueden serle útiles o interesantes. En Mozilla Developer Network's list of DOM events se puede ver por ejemplo .:

  • DOMNodeInserted,
  • DOMNodeInsertedIntoDocument,
  • DOMNodeRemoved,
  • DOMElementNameChanged,

Todos ellos, sin embargo están marcados como borradores del W3C.

+0

¿Qué navegadores han implementado? Idealmente, me gustaría algo que funcione en Chrome. – Muhd

+0

El marcador 'borrador' es un descuido de una parte de los editores de MDC. Esos eventos también estuvieron en los Eventos DOML2, que es "recomendación". El hecho es que la mayoría de estos eventos funcionan en todo menos en IE; pero debe evitar usarlos, si puede, ya que tienen desventajas importantes (detalles: http://lists.w3.org/Archives/Public/public-webapps/2011JulSep/0779.html) – Nickolay

1

Una forma genérica de detectar la inserción de nodos es utilizar el evento de mutación DOMNodeInserted.

Estoy interesado en cada nodo en realidad. Estoy cambiando los colores de todo en la página.

Para este propósito, una mejor solución es inyectar una hoja de estilos dinámica, suficiente con la bandera !important. Si solo desea cambiar los colores, le recomiendo la extensión Stylish (Stylish for Chrome) en lugar de GreaseMonkey.

+0

¡Correcto, pero el '! una bandera importante destruiría muchas páginas. Estoy buscando crear una secuencia de comandos inteligente que funcione en muchas páginas diferentes y se vea bien. – Muhd

+0

@Muhd Puede elegir selectores inteligentes para seleccionar solo elementos específicos. Elegante soporta la selección de dominio usando RegExes a través del '@ -moz-document regexp()' - Ver también ['@ document'] (https://developer.mozilla.org/en/CSS/@document). –

1

Si no tienen el acceso a una biblioteca como jQuery , aquí es la sintaxis de JavaScript solamente- :

document.addEventListener('DOMNodeInserted', nodeInsert) 

function nodeInsert() { 
    event.srcElement.style.color = '#ffffff' 
} 

Creo que debería funcionar en la mayoría de los navegadores.

3

Aquí hay una buena forma de manejar el evento de inserción de nodos. establece animaciones para el elemento que vas a agregar usando css.

<style type="text/css"> 

/* set up the keyframes; remember to create prefixed keyframes too! */ 

@keyframes nodeInserted { 
from { opacity: 0.99; } 
to { opacity: 1; } 
} 

#parent > button { 
animation-duration: 0.001s; 
animation-name: nodeInserted; 
} 

</style> 

#parent es el id de la div, en el que voy a añadir dinámicamente botón de .

<script type="text/javascript"> 

    var insertListener = function(event){ 
     if (event.animationName == "nodeInserted") { 
      // This is the debug for knowing our listener worked! 
      // event.target is the new node! 
      console.warn("Another node has been inserted! ", event, event.target); 
     } 
    } 

    document.addEventListener("animationstart", insertListener, false); // standard + firefox 
    document.addEventListener("MSAnimationStart", insertListener, false); // IE 
    document.addEventListener("webkitAnimationStart", insertListener, false); // Chrome + Safari 

    setInterval(function(){ 

     var btn = document.createElement("BUTTON"); 

     var t = document.createTextNode("CLICK ME");  // Create a text node 

     btn.appendChild(t);   

     document.getElementById("parent").appendChild(btn); 

    }, 2000); 

</script> 
+0

Implementé este método y programé un cambio de tamaño responsivo de un 'iframe' dentro del método' insertListener'. Lo extraño es que el comportamiento de cambio de tamaño personalizado se produce solo después de desplazarse hacia abajo hasta el 'iframe', no antes. ¿Alguna idea de lo que podría estar pasando aquí? –

Cuestiones relacionadas