In my opinion, the DOM Level 3 events DOMNodeInserted
help (which fires only for nodes) and DOMSubtreeModified
help (which fires for virtually any modification, like attribute changes) are your best shot to accomplish that task.
Of course, the big downside of those events is, that the Internet Explorers of this world don't support them
(...well, IE9 does).
The other reasonable solution for this problem, is to hook into any method Which can modify the DOM. But then we have to ask, what is our scope here?
Is it just enough to deal with DOM modification methods from a specific library like jQuery? What if for some reason another library is modifying the DOM or even a native method ?
If it's just for jQuery, we don't need .sub()
at all. We could write hooks in the form of:
HTML
<div id="test">Test DIV</div>
JS
(function(_append, _appendTo, _after, _insertAfter, _before, _insertBefore) {
$.fn.append = function() {
this.trigger({
type: 'DOMChanged',
newnode: arguments[0]
});
return _append.apply(this, arguments);
};
$.fn.appendTo = function() {
this.trigger({
type: 'DOMChanged',
newnode: this
});
return _appendTo.apply(this, arguments);
};
$.fn.after = function() {
this.trigger({
type: 'DOMChanged',
newnode: arguments[0]
});
return _after.apply(this, arguments);
};
// and so forth
}($.fn.append, $.fn.appendTo, $.fn.after, $.fn.insertAfter, $.fn.before, $.fn.insertBefore));
$('#test').bind('DOMChanged', function(e) {
console.log('New node: ', e.newnode);
});
$('#test').after('<span>new span</span>');
$('#test').append('<p>new paragraph</p>');
$('<div>new div</div>').appendTo($('#test'));
A live example of the above code can be found here: http://www.jsfiddle.net/RRfTZ/1/
This of course requires a complete list of DOMmanip methods. I'm not sure if you can overwrite native methods like .appendChild()
with this approach. .appendChild
is located in Element.prototype.appendChild
for instance, might be worth a try.
update
I tested overwriting Element.prototype.appendChild
etc. in Chrome, Safari and Firefox (official latest release). Works in Chrome and Safari but not in Firefox!
There might be other ways to tackle the requirement. But I can't think of a single approach which is really satisfying, like counting / watching all descendents of a node (which would need an interval
or timeouts
, eeek).
Conclusion
A mixture of DOM Level 3 events where supported and hooked DOMmanip methods is probably the best you can do here.