Método mais eficiente para detectar / monitorar mudanças no DOM?

Eu preciso de um mecanismo eficiente para detectar alterações no DOM. De preferência, entre navegadores, mas se houver algum meio eficiente que não seja cross browser, posso implementá-los com um método cross-browser fail-safe.

Em particular, preciso detectar alterações que afetariam o texto em uma página, portanto, quaisquer elementos novos, removidos ou modificados ou alterações no texto interno (innerHTML) seriam necessários.

Eu não tenho controle sobre as alterações que estão sendo feitas (elas podem ser devido a inclusões de javascript de terceiros, etc), portanto, não pode ser abordado deste ângulo – eu preciso “monitorar” as alterações de alguma forma.

Atualmente eu implementei um método “quick’n’dirty” que verifica body.innerHTML.length em intervalos. Obviamente, isso não detectará alterações que resultem na mesma duração de retorno, mas neste caso é “bom o suficiente” – as chances de isso acontecer são extremamente pequenas e, neste projeto, a falha em detectar uma alteração não resultará em dados perdidos.

O problema com body.innerHTML.length é que é caro. Pode demorar entre 1 e 5 milissegundos em um navegador rápido , e isso pode atrapalhar bastante as coisas – também estou lidando com um grande número de iframes e tudo isso se sum. Eu tenho certeza que o custo de fazer isso é porque o texto innerHTML não é armazenado estaticamente pelos navegadores, e precisa ser calculado a partir do DOM toda vez que for lido.

Os tipos de respostas que estou procurando são desde o “preciso” (por exemplo, evento) até o “bom o suficiente” – talvez algo como “quick’n’dirty” como o método innerHTML.length, mas que é executado mais rapidamente.

EDIT: Gostaria também de salientar que, embora seria “bom” para detectar o elemento preciso que foi modificado, não é uma necessidade absoluta – apenas o fato de que tenha havido qualquer mudança seria bom o suficiente. Espero que isso amplie as respostas das pessoas. Eu vou investigar Eventos de Mutação, mas eu ainda preciso de um substituto para o suporte ao IE, então qualquer idéia maluca, criativa, fora do quadrado seria muito bem vinda.

    http://www.quirksmode.org/js/events/DOMtree.html

    O jQuery agora suporta uma maneira de append events a elementos existentes e futuros correspondentes a um seletor: http://docs.jquery.com/Events/live#typefn

    Outro achado interessante – http://james.padolsey.com/javascript/monitoring-dom-properties/

    Para atualizar isso, o padrão DOM4 elimina os Eventos de Mutação e os substitui por Observadores de Mutação: https://developer.mozilla.org/pt-BR/docs/Web/API/MutationObserver

    Eventos de mutação são a recomendação W3 do que você está procurando.

    Não tenho certeza se eles são suportados por toda parte .. (IE provavelmente não irá suportá-los ..)

    Você pode tentar usar os events DOMNodeInserted e DOMNodeRemoved. De acordo com o Quirksmode, eles funcionam na maioria dos navegadores, com a notável exceção do IE …

    http://www.quirksmode.org/dom/events/index.html

    Eu escrevi recentemente um plugin que faz exatamente isso – jquery.initialize

    Você o usa da mesma maneira que .each function

     $(".some-element").initialize( function(){ $(this).css("color", "blue"); }); 

    A diferença de .each é – leva o seu seletor, neste caso .some-element e espera por novos elementos com este seletor no futuro, se tal elemento for adicionado, ele será inicializado também.

    Em nosso caso, inicialize a function apenas altere a cor do elemento para azul. Então, se vamos adicionar novo elemento (não importa se com ajax ou mesmo F12 inspector ou qualquer coisa) como:

     $("
    ").addClass('some-element').appendTo("body"); //new element will have blue color!

    O plug-in será iniciado instantaneamente. O plugin também garante que um elemento seja inicializado apenas uma vez. Então, se você adicionar element, then .deatch() do body e depois adicioná-lo novamente, ele não será inicializado novamente.

     $("
    ").addClass('some-element').appendTo("body").detach() .appendTo(".some-container"); //initialized only once

    O plug-in é baseado no MutationObserver – ele funcionará no IE9 e 10 com dependencies, conforme detalhado na página do readme .

    O jQuery Mutate faz isso também, por padrão suporta como height, width, scrollHeight etc … mas também pode ser estendido com um pouco de código extra para adicionar novos events como ver se o texto mudou, etc …

    http://www.jqui.net/jquery-projects/jquery-mutate-official/

    Espero que ajude