DOM mutation events replacement
Asked Answered
G

4

22

Since DOM mutation is marked as deprecated by the w3c (see http://www.w3.org/TR/DOM-Level-3-Events/#events-mutationevents), is there an (fast) alternative way to detect attribute modification in the DOM ?

Glyptodont answered 24/3, 2011 at 9:0 Comment(1)
You can even consider John Resig's NodeList - github.com/jeresig/nodelist However, this is still in development phases, but seems promising candidate as a replacement to the mutation events.Cia
A
7

As far as I know there is no alternative (yet) so you are stuck with DOMAttrModified which is only supported in Firefox and Opera. In IE you have the onpropertychanged event but there is no way to get similar functionality in Chrome/Safari. There are a number of things you could do depending on what you are trying to accomplish and the browsers you are targetting:

  • define getters and setters to the attributes you want to monitor
  • override methods like document.createAttribute, attributes.setNamedItem, ...

I've been working on a cross-browser solution myself but without much success. You should stay away from mutation events all together since they are not cross-browser and very slow. There are good reasons why they are deprecated. If you want to learn more read this:

Athos answered 5/4, 2011 at 15:42 Comment(1)
I think the Mozilla guys finished your work. :)Unders
S
31

The reason that mutation events was deprecated was because of huge performance issues.

The replacement is Mutation Observers, look at http://updates.html5rocks.com/2012/02/Detect-DOM-changes-with-Mutation-Observers and https://developer.mozilla.org/en/DOM/DOM_Mutation_Observers

Information about mutations is delivered to observers as an ordered sequence of MutationRecords, representing an observed sequence of changes that have occurred

Sample usage:

    var observer = new MutationObserver(function(mutationRecords) {
    // Handle mutations
     });

    observer.observe(myNode,
     {  // options:
     subtree: true,  // observe the subtree rooted at myNode
     childList: true,  // include information childNode insertion/removals
     attribute: true  // include information about changes to attributes within the subtree
    });

This is supported in Chrome 18 and Firefox and Webkit nightly builds. Firefox 14 will also be supporting this feature.

Septimal answered 19/6, 2012 at 17:16 Comment(1)
Those semicolons in the 'options' object literal should be commas.Kakemono
U
13

A great replacement for the deprecated DOM* events is animationStart in conjunction with CSS Animations. David Walsh writes about the method.

First, set up the keyframes and apply it to the elements you'd like to listen for (don't forget the vendor prefixes!):

@keyframes nodeInserted {  
  from { clip: rect(1px, auto, auto, auto); }
  to { clip: rect(0px, auto, auto, auto); }  
}

#parentElement > li {
  animation-duration: 0.001s;
  animation-name: nodeInserted;
}

Next, add the listener:

var insertListener = function(event){
  if (event.animationName == "nodeInserted") {
    // This is the debug for knowing our listener worked!
    // event.target is the new node!
    console.warn("Another node has been inserted! ", event, event.target);
  }
}
document.addEventListener("animationstart", insertListener, false); // standard + firefox
document.addEventListener("MSAnimationStart", insertListener, false); // IE
document.addEventListener("webkitAnimationStart", insertListener, false); // Chrome + Safari

Ta-da! Here is David's demo. It works great for me on a Chrome extension that adds Facebook pictures to Google Voice (see content.css and injected.js).

Unders answered 12/12, 2012 at 8:7 Comment(1)
BTW. clip:rect doesn't trigger events in IE10. I got it fixed some time agoOjibwa
M
12

A year later, there are the new and shiny Mutation Observers from DOM Level 4 (follow the links there, they explain a lot!). Where a Mutation Event fired a thousand times, MutationObserver fires only once with all the modifications contained and accessible.

Works for (as of 2017/03):

  • Firefox 14+
  • IE 11
  • Edge
  • Opera 15+
  • Chrome 26+ (18 till 25 prefixed, window.WebKitMutationObserver)
  • Safari 6.0 (prefixed, window.WebKitMutationObserver)
Machuca answered 25/6, 2012 at 23:31 Comment(0)
A
7

As far as I know there is no alternative (yet) so you are stuck with DOMAttrModified which is only supported in Firefox and Opera. In IE you have the onpropertychanged event but there is no way to get similar functionality in Chrome/Safari. There are a number of things you could do depending on what you are trying to accomplish and the browsers you are targetting:

  • define getters and setters to the attributes you want to monitor
  • override methods like document.createAttribute, attributes.setNamedItem, ...

I've been working on a cross-browser solution myself but without much success. You should stay away from mutation events all together since they are not cross-browser and very slow. There are good reasons why they are deprecated. If you want to learn more read this:

Athos answered 5/4, 2011 at 15:42 Comment(1)
I think the Mozilla guys finished your work. :)Unders

© 2022 - 2024 — McMap. All rights reserved.