29

HTML5 incluye un concepto de "mutation observers" para supervisar los cambios en el DOM del navegador.¿Se pueden utilizar selectores jQuery con observadores de mutación DOM?

Su devolución de llamada del observador recibirá datos que se parecen mucho a los fragmentos de árbol DOM. No sé si son exactamente esto o cómo funcionan realmente.

Pero cuando escribe código para interactuar con un sitio de terceros sobre el que no tiene control, digamos con un script de Greasemonkey o script de usuario de Google Chrome, debe inspeccionar el árbol de elementos pasados ​​para encontrar qué información es relevante para ti

Esto es mucho más simple con los selectores, al igual que trabajar con cualquier DOM, que caminar el árbol manualmente, especialmente para el código entre navegadores.

¿Hay alguna manera de usar los selectores jQuery con los datos pasados ​​a las devoluciones de llamada del observador de mutación HTML5?

+0

Preguntas relacionadas: [¿Hay un escucha de cambio de jQuery DOM?] (Http://stackoverflow.com/questions/2844565/is-there-a-jquery-dom-change-listener), [Evento de mutación DOM en JQuery o vainilla Javascript] (http://stackoverflow.com/questions/7692730/dom-mutation-event-in-jquery-or-vanilla-javascript) – hippietrail

+0

Ver también: [¿Puedo usar los selectores de Jquery en una cadena HTML que no es adjunto al DOM?] (http://stackoverflow.com/questions/4336674) – hippietrail

+1

Hay un ** complemento ** para eso: https://github.com/kapetan/jquery-observe – vsync

Respuesta

35

Sí, puede usar los selectores jQuery en los datos devueltos a las devoluciones de llamada del observador de la mutación.

See this jsFiddle.

Supongamos que tenemos HTML así:

<span class="myclass"> 
    <span class="myclass2">My <span class="boldly">vastly</span> improved</span> 
    text. 
</span> 


y se establece un observador, así:

var targetNodes   = $(".myclass"); 
var MutationObserver = window.MutationObserver || window.WebKitMutationObserver; 
var myObserver   = new MutationObserver (mutationHandler); 
var obsConfig   = { childList: true, characterData: true, attributes: true, subtree: true }; 

//--- Add a target node to the observer. Can only add one node at a time. 
targetNodes.each (function() { 
    myObserver.observe (this, obsConfig); 
}); 

function mutationHandler (mutationRecords) { 
    console.info ("mutationHandler:"); 

    mutationRecords.forEach (function (mutation) { 
     console.log (mutation.type); 

     if (typeof mutation.removedNodes == "object") { 
      var jq = $(mutation.removedNodes); 
      console.log (jq); 
      console.log (jq.is("span.myclass2")); 
      console.log (jq.find("span")); 
     } 
    }); 
} 

Se habrá dado cuenta de que podamos jQuery en el mutation.removedNodes.


Si a continuación, ejecuta desde la consola $(".myclass").html ("[censored!]"); obtendrá esto desde Chrome y Firefox:

mutationHandler: 
childList 
jQuery(<TextNode textContent="\n ">, span.myclass2, <TextNode textContent="\n text.\n ">) 
true 
jQuery(span.boldly) 

lo que demuestra que se puede utilizar métodos normales de selección de jQuery en los conjuntos de nodos devueltos.

+1

¿Sabe si es oficialmente compatible con jQuery, si funciona en todos los navegadores compatibles con jQuery y cuáles son compatibles con los observadores de mutación? ¿Podría ser que simplemente funciona en estos navegadores? Parece que podría ser el caso, ya que el comportamiento parece ser diferente ... ¡Definitivamente voy a jugar con él de todos modos! (-: – hippietrail

+1

No creo que se trate de soporte "oficial". Cosas como 'removedNodes' y' addedNodes' [listas de devoluciones de nodos] (http://dvcs.w3.org/hg/domcore/raw- file/tip/Overview.html # dom-mutationrecord-addednodes). jQuery funciona en tales listas durante todo el día, siempre lo ha hecho ... El código funciona en Firefox y Chrome, y por especificación W3C. Debería funcionar en cualquier navegador que admite tales eventos. –

+1

PS, vea la respuesta actualizada y el jsFiddle agregado. –

2

Estaba trabajando en un problema muy similar para un script de Stack Exchange en el que estoy trabajando, y necesitaba poder controlar el DOM para ver los cambios. La documentación de jQuery no tenían nada útil, pero yo descubre que el evento DOMNodeInserted funciona en Chrome:

document.addEventListener("DOMNodeInserted", function(event){ 
    var element = event.target; 

    if (element.tagName == 'DIV') { 
     if (element.id == 'seContainerInbox') { 
      //alert($('#seContainerInbox').parent().get(0).tagName); 
      trimStoredItems(); 
      $('#seTabInbox').click(); 
      // var newCount = getNewCount(); 
      // if there are new inbox items, store them for later 
      storeNewInboxItems(); 
      applyNewStyleToItems(); 
     } 
    } 
}); 

no estoy 100% seguro de si esto funciona en Firefox ya que no he llegado tan lejos en el proceso de desarrollo. ¡Espero que esto ayude!

+0

Estoy usando 'WebKitMutationObserver() 'que creo que es nuevo y compatible y lo viejo está obsoleto. No estoy seguro de si 'DOMNodeInserted' es parte de ese" material viejo ". 'WebKitMutationObserver' te pasa un objeto de mutaciones que, aunque supongo que no es DOM, es básicamente un paquete de referencias DOM. Quiero saber si puedo envolverlo o algunas de esas referencias con jQuery ... – hippietrail

+0

No he usado esto por mí mismo, pero por la forma en que lo describes, sospecho que probablemente tendrías que acceder a los elementos RAW DOM en sí mismos para que puedas pasarlos a un objeto jQuery como piezas de dos rompecabezas. Supongo que realmente dependería de los tipos de datos reales. Tal vez mire lo que "typeof" le da para ver si es algo que podría envolverse fácilmente. ¡Espero que esto ayude! – jmort253

+5

'DOMNodeInserted' no es parte de los observadores de mutaciones. ¡Es el viejo, defectuoso, * obsoleto *, sistema de eventos de mutación que los observadores de mutaciones reemplazan! –

7

no tengo ningún fragmentos de código personal para éste, pero tengo tres recursos que pueden ayudar:

Ejemplo de enlace # 3 'jquery-mutación-resumen' biblioteca:

// Use document to listen to all events on the page (you might want to be more specific) 
var $observerSummaryRoot = $(document); 

// Simplest callback, just logging to the console 
function callback(summaries){ 
    console.log(summaries); 
} 

// Connect mutation-summary 
$observerSummaryRoot.mutationSummary("connect", callback, [{ all: true }]); 

// Do something to trigger mutationSummary 
$("<a />", { href: "http://joelpurra.github.com/jquery-mutation-summary"}).text("Go to the jquery-mutation-summary website").appendTo("body"); 

// Disconnect when done listening 
$observerSummaryRoot.mutationSummary("disconnect"); 
+3

Hola Vita, las respuestas de Stack Overflow generalmente incluyen ejemplos de código, no solo un enlace a un tercero. ¿Puedes publicar un ejemplo aquí en Stack Overflow al hacer una [edit] en tu publicación? Si el enlace se rompiera alguna vez, tu respuesta sería inútil. Con un ejemplo, sería útil para otros visitantes futuros, que enfrentan el mismo problema, en los próximos años. ¡Buena suerte! – jmort253

+0

¡Claro! También encontró algunos recursos más que pueden ayudar. –

+0

Hmm Intenté utilizar la versión original que no es jQuery de [Mutation Summary] (https://code.google.com/p/mutation-summary/) pero creo que no funciona bien con páginas no diseñadas con guiones de usuario en mente. Es bueno para ver los cambios en los elementos a los que hace referencia 'id' o' class', pero no tan buenos cuando todos los cambios que te interesan son varios elementos profundos o con 'id's y' className's generados. – hippietrail

2

Sé que esta es una vieja pregunta, pero quizás esto puede ayudar a otros a buscar soluciones alternativas. Hace poco aprendí sobre Mutation Observers y quería experimentar con su uso junto con jQuery. Se me ocurrió dos enfoques posibles y los convertí en complementos. El código está disponible here.

El primer enfoque (jquery.observeWithEvents.js) utiliza la función de jQuery trigger() para activar ya sea un evento insertNode o removeNode que puede ser obligado a través de la función de jQuery on(). El segundo enfoque (jquery.observeWithCallbacks.js) utiliza parámetros de devolución de llamada tradicionales. Por favor, eche un vistazo al archivo README para ejemplos y uso.