Подтвердить что ты не робот

Событие DOM Mutation в JQuery или ваниле Javascript

Есть ли какие-либо события мутации DOM в JQuery или в ванильном Javascript, которые используют перекрестный браузер?

Чтобы уточнить, скажем, у меня есть script на моей странице, который вставляет div в тело. У меня нет доступа к script, и я не знаю, когда был добавлен div. Мне было интересно, есть ли событие мутации DOM, для которого я могу добавить слушателя, чтобы знать, когда был вставлен элемент. Я знаю, что могу использовать таймер для периодической проверки вставки, но мне не нравятся накладные расходы, которые это наложило бы.

4b9b3361

Ответ 1

Это, конечно, взлом, но почему бы не исправить базовые методы DOM, используемые для вставки узлов? Есть несколько способов сделать это:

А. Вы знаете, к какому элементу конкретный добавляется:

var c = document.getElementById('#container');
c.__appendChild = c.appendChild;
c.appendChild = function(){
     alert('new item added');
     c.__appendChild.apply(c, arguments); 
}

демонстрацию скрипта для A

В. Вы знаете, что элемент типа будет добавлен к:

HTMLDivElement.prototype.__appendChild = HTMLDivElement.prototype.appendChild;
HTMLDivElement.prototype.appendChild = function(){
    alert('new item added');
    HTMLDivElement.prototype.__appendChild(this,arguments); 
}

скрипт для B

(Обратите внимание, что решение B не поддерживается IE < 8 или любым другим браузером, который не поддерживает прототипы DOM.)

Этот же метод можно так же легко использовать для всех базовых функций мутации DOM, таких как insertBefore, replaceChild или removeChild.

Что общая идея, эти демонстрации могут быть адаптированы практически для любого другого варианта использования - скажем, вы хотите использовать широкую сеть и улавливать все дополнения, независимо от типа И, чтобы убедиться, что он работает все браузеры все, кроме IE < 8? (см. пример C ниже)


UPDATE

C. Рекурсивно пройдите DOM, замените функцию на каждом элементе, чтобы вызвать обратный вызов, а затем примените тот же патч к добавляемым дочерним элементам.

var DOMwatcher = function(root, callback){
  var __appendChild = document.body.appendChild;

  var patch = function(node){
    if(typeof node.appendChild !== 'undefined' && node.nodeName !== '#text'){
      node.appendChild = function(incomingNode){
        callback(node, incomingNode);
        patch(incomingNode);
        walk(incomingNode);
        __appendChild.call(node, incomingNode);
      };
    }
    walk(node);  
  };

  var walk = function(node){
    var i = node.childNodes.length;
    while(i--){
      patch(node.childNodes[i]);
    }
  };

  patch(root);

};

DOMwatcher(document.body, function(targetElement, newElement){ 
   alert('append detected');    
});

$('#container ul li').first().append('<div><p>hi</p></div>');
$('#container ul li div p').append('<a href="#foo">bar</a>');

скрипт для C

ОБНОВЛЕНИЕ 2

Как отметил Tim Down, вышеупомянутое решение также не будет работать в IE < 8, потому что appendChild не является Function и не поддерживает call или apply. Полагаю, вы всегда можете вернуться к неуклюжему, но надежному методу setInterval, если typeof document.body.appendChild !== 'function'.

Ответ 2

Есть несколько устаревших событий DOM-мутации, таких как DOMNodeInserted и DOMNodeInsertedIntoDocument, которые все еще работают для меня в Chrome 14 и IE9.

См. пример в http://jsfiddle.net/Kai/WTJq6/

Посмотрите их на черновик W3C на http://www.w3.org/TR/DOM-Level-3-Events/

Ответ 3

JCADE (JQuery Create and Destroy Events) сделает это. Он использует поведение для IE и событий мутации DOM для других браузеров. Он не использует события синхронизации и не переносит методы JQuery, такие как livequery.

https://github.com/snesin/jcade

    $( document ).create( "a", function( event ) {
      alert( event.target );
    });

Ответ 5

Если вы ищете альтернативу этому методу, http://www.jqui.net/jquery-projects/jquery-mutate-official/, который также позволяет вам добавлять события самостоятельно и поддерживать наблюдать за любыми изменениями, изменением имени класса, изменением высоты, изменением ширины.

Ответ 6

Для этого можно использовать плагин livequery. В версии 1.x таймер использовался для периодической проверки любых изменений. Однако более новая ветка версии 2.x работает без периодического таймаута (непроверенная).