Это, конечно, хак, но почему бы не исправить основные методы DOM, используемые для вставки узлов? Есть несколько способов сделать это:
A . Вы знаете, к какому * конкретному элементу будет добавлен:
var c = document.getElementById('#container');
c.__appendChild = c.appendChild;
c.appendChild = function(){
alert('new item added');
c.__appendChild.apply(c, arguments);
}
демонстрация скрипки для A
B . Вы знаете, к какому элементу type будет добавлен:
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
Как прокомментировал Тим Даун , указанное выше решение также не будет работать в IE < 8
, поскольку appendChild
не является Function
и не поддерживает call
или apply
. Я полагаю, вы всегда можете вернуться к неуклюжему, но надежному методу setInterval
, если typeof document.body.appendChild !== 'function'
.