Mutation Observer is undefined

knightsbore picture knightsbore · Dec 4, 2013 · Viewed 11.6k times · Source

I am attempting to fix and issue with my code. I was originally using DOMNodeRemoved and DOMNodeInserted for keeping an eye on an element within a page I am working on. They worked well but did not function in IE. So I started trying to work with a MutationObserver.

Here is my Code it's called on onPageInit(the callback writes to the console but I disabled it since IE no longer supports console):

var callback = function(allmutations){
    allmutations.map( function(mr){
        var mt = 'Mutation type: ' + mr.type;  // log the type of mutation
        mt += 'Mutation target: ' + mr.target; // log the node affected.
        //console.log( mt );
    })
}
mo = new MutationObserver(callback),
options = {
    // required, and observes additions or deletion of child nodes.
    'childList': true, 
    // observes the addition or deletion of "grandchild" nodes.
    'subtree': true
}
alert('its alive');
mo.observe(document.body, options);

It works fine in chrome, however for some reason falls flat in IE. I get a message box during load of the page that says :

An unexpected error occurred in a script running on this page.
onPageInit(pageInit)
scriptname

JS_EXCEPTION
TypeError 'MutationObserver' is undefined

Am I doing something wrong? Additional info: Page is a netsuite page, running jQuery 1.7.2 (if it matters)

Answer

naugtur picture naugtur · Feb 6, 2014

If you need to detect DOM insertions in IE10+ (and other browsers that don't yet support MutationObserver) You can use a trick based on listening to animationstart event for CSS animations that animate a property that doesn't affect the way your nodes look.

The technique was discovered by Daniel Buchner, you can see it described it this post by David Walsh

The code required to make it work would be something like this:

@keyframes animationName{ 
    from { outline: 1px solid transparent } 
    to { outline: 0px solid transparent } 
}
* { 
    animation-duration: 0.001s; 
    animation-name: animationName;
}

and

document.addEventListener('animationstart', insertionHandler, false);

The setup required for this trick to work cross-browser is quite complicated with all the prefixes and event listener names. The handler will be called for every new node and the choice of the property to animate is hard.

That's why I wrapped it in a library to make it easy to use: https://github.com/naugtur/insertionQuery

Here's a brief usage example:

insertionQ('selector').every(function(element){
    //callback on every new element
});