I want to execute a function when some div or input are added to the html. Is this possible?
For example, a text input is added, then the function should be called.
I want to execute a function when some div or input are added to the html. Is this possible?
For example, a text input is added, then the function should be called.
No there is no cross-browser way for that. The DOM Level-2 has Mutation event types, but you can't use it in production because of the lack of support in IE.
Someone else is changing the document? Because if you have full control over the changes you just need to create a domChanged
simple callback and call it everywhere you modify things.
For a full domChange an interval would be an over-kill. Imagine that you need to store the current state of the whole document, and examine every element's every property to be the same.
Maybe if you're only interested in elements and their order (as you mentioned in your question), a getElementsByTagName("*")
can work. This will fire automatically if you add an element, remove an element, replace elements or change the structure of the document.
UPDATE
You can try to emulate mutation event with onpropertychange
in IE (and fall back to the brute-force approach if non of them is available).
I wrote a proof of concept:
//
// ON DOCUMENT CHANGE
// Makes it possible to execute code when the DOM changes.
//
// Licensed under the terms of the MIT license.
// (c) 2010 Balázs Galambosi
//
(function( window ) {
var last = +new Date();
var delay = 100; // default delay
// Manage event queue
var stack = [];
function callback() {
var now = +new Date();
if ( now - last > delay ) {
for ( var i = 0; i < stack.length; i++ ) {
stack[i]();
}
last = now;
}
}
// Public interface
var onDomChange = function( fn, newdelay ) {
if ( newdelay )
delay = newdelay;
stack.push( fn );
};
// Naive approach for compatibility
function naive() {
var last = document.getElementsByTagName('*');
var lastlen = last.length;
var timer = setTimeout( function check() {
// get current state of the document
var current = document.getElementsByTagName('*');
var len = current.length;
// if the length is different
// it's fairly obvious
if ( len != lastlen ) {
// just make sure the loop finishes early
last = [];
}
// go check every element in order
for ( var i = 0; i < len; i++ ) {
if ( current[i] !== last[i] ) {
callback();
last = current;
lastlen = len;
break;
}
}
// over, and over, and over again
setTimeout( check, delay );
}, delay );
}
//
// Check for mutation events support
//
var support = {};
var el = document.documentElement;
var remain = 3;
// callback for the tests
function decide() {
if ( support.DOMNodeInserted ) {
window.addEventListener( "DOMContentLoaded", function() {
if ( support.DOMSubtreeModified ) { // for FF 3+, Chrome
el.addEventListener( 'DOMSubtreeModified', callback, false );
} else { // for FF 2, Safari, Opera 9.6+
el.addEventListener( 'DOMNodeInserted', callback, false );
el.addEventListener( 'DOMNodeRemoved', callback, false );
}
}, false );
} else if ( document.onpropertychange ) { // for IE 5.5+
document.onpropertychange = callback;
} else { // fallback
naive();
}
}
// checks a particular event
function test( event ) {
el.addEventListener( event, function fn() {
support[event] = true;
el.removeEventListener( event, fn, false );
if( --remain === 0 ) decide();
}, false);
}
// attach test events
if ( window.addEventListener ) {
test( 'DOMSubtreeModified');
test( 'DOMNodeInserted' );
test( 'DOMNodeRemoved' );
} else {
decide();
}
// do the dummy test
var dummy = document.createElement("div");
el.appendChild( dummy );
el.removeChild( dummy );
// expose
window.onDomChange = onDomChange;
})( window );
Usage
onDomChange(function(){
alert("The Times They Are a-Changin'");
});
Works on: IE 5.5+, FF 2+, Chrome, Safari 3+, Opera 9.6+