Domnodeinserted Equivalent in Ie

DOMNodeInserted equivalent in IE?

No, there isn't. The nearest is the propertychange event, which fires in response to a change in an attribute or CSS property of an element. It fires in response to changing the innerHTML property of an element directly but not when the contents of the elements are altered by some other means (e.g. by using DOM methods such as appendChild() or by altering the innerHTML of a child element).

UPDATE 6 February 2014

As pointed out in the comments, there is a workaround. It's based on an elaborate hack and I'd recommend using mutation observers instead wherever possible. See @naugtur's answer for details. @naugtur's answer has been deleted but the solution can be found at https://github.com/naugtur/insertionQuery

Alternative to DOMNodeInserted

If you are creating a web app that targets recent mobile phones and newer versions of browsers (Firefox 5+, Chrome 4+, Safari 4+, iOS Safari 3+, Android 2.1+), you can use the following code to create an awesome event for the insertion of dom nodes, and it even runs on the nodes initially part of the page's static mark-up!

Here's the link to the full post with and example: http://www.backalleycoder.com/2012/04/25/i-want-a-damnodeinserted/

Note on Mutation Observers: while the newer Mutation Observers features in recent browsers are great for monitoring simple insertions and changes to the DOM, do understand that this method can be used to do far more as it allows you to monitor for any CSS rule match you can thing of. This is super powerful for many use-cases, so I wrapped this up in a library here: https://github.com/csuwildcat/SelectorListener

You'll need to add the appropriate prefixes to the CSS and animationstart event name if you want to target various browsers. You can read more about that in the post linked to above.

The basic node insertion case

CSS:

@keyframes nodeInserted {  
from {
outline-color: #fff;
}
to {
outline-color: #000;
}
}

div.some-control {
animation-duration: 0.01s;
animation-name: nodeInserted;
}

JavaScript:

document.addEventListener('animationstart', function(event){
if (event.animationName == 'nodeInserted'){
// Do something here
}
}, true);

Listening for more complex selector matches:

This enables things that are almost impossible to do with Mutation Observers

CSS:

@keyframes adjacentFocusSequence {  
from {
outline-color: #fff;
}
to {
outline-color: #000;
}
}

.one + .two + .three:focus {
animation-duration: 0.01s;
animation-name: adjacentFocusSequence;
}

JavaScript:

document.addEventListener('animationstart', function(event){
if (event.animationName == 'adjacentFocusSequence'){
// Do something here when '.one + .two + .three' are
// adjacent siblings AND node '.three' is focused
}
}, true);

What Event should I register on DOM Update with Internet Explorer

I've figured it out after reading some of the source of head.js. This calls for a bit of creative javascript magic.

The events we're interested in are onreadystatechange, and onload. You can attach a custom function to these to trigger update notifications when they insert into the page.

I've abstracted this into a function, where, if you pass it an element and a callback statement, it'll dump the element at the end of the page body and run the callback.

function loadElement(e, callback) {
if ( typeof(callback) === 'function' ) {
e.onreadystatechange = e.onload = function() {
var state = e.readyState;

if ( !callback.done && (!state || /loaded|complete/.test(state)) ) {
callback.done = true;
callback();
}
}
}
document.body.appendChild(e);
}

Though I've posted this answer to my problem, I'm interested in alternative approaches to this :).

How to call a function in every element in the DOM even if they are dynamically created

You were close. Try:

$(document).on("load", ".red", function(){ this.css({backgroundColor: "pink"}) });

Oops, that doesn't work. This does http://jsfiddle.net/4Bv9r/

$('body').on('DOMNodeInserted', ".red", function(){ $(this).css({backgroundColor: "pink"}) });

Preferred way of modifying elements that have yet to be created (besides events)

In my opinion, the DOM Level 3 events DOMNodeInsertedhelp (which fires only for nodes) and DOMSubtreeModifiedhelp (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.

DOMNodeInserted/Removed event polyfills (or similar events)

I ended up writing a reasonably compliant polyfill for MutationObserver using interval checks of a cloned childList (similar to what @plalx mentioned in his comments) instead of falling back on the MutationEvents. MutationEvents will be more performant for most scenarios as any poll vs interrupt implementations but compatibility sucks

Simple auto scrolling example using my shim



Related Topics



Leave a reply



Submit