Dom Mutation Events Replacement

DOM mutation events replacement

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:

  • http://www.w3.org/2008/webapps/wiki/MutationReplacement
  • http://www.quirksmode.org/dom/events/ > W3C events
  • http://robertnyman.com/javascript/javascript-getters-setters.html

Are DOM Mutation Observers slower than DOM Mutation Events?

DOM Mutation Observers, are not intended to be faster than DOM Mutation Events. Rather they are intended to be more efficient and safer.

The basic gist of the difference is that DOM Mutation Events fire whenever there is a change. So this code for example would create a callback loop, that will ultimately crash the browser.

document.addEventListener('DOMNodeInserted', function() {
var newEl = document.createElement('div');
document.body.appendChild(newEl);
});

The fact that they are called in this fashion and so often also has a significant effect on the browser, as it forces an interrupt between the browsers recalculate style, reflow and repaint cycle or worse forces the browser to recalculate styles, reflow and repaint on every callback. The problem is further exasperated by the fact that other code maybe executing that makes further changes to the DOM, which will continue to be interrupted by your callback.

What's more is that because events propagate in the same way as normal DOM Events, you're going to start hearing changes on elements that you might not care about or didn't account for in your code. So the whole mechanism of DOM Mutation Events can become troublesome to manage fairly quickly.

DOM Mutation Observers counteract these problems by, as the name suggests observing changes to the DOM and providing you with a report of all the changes that took place from from the start of the change. This is a much better situation to be in as it allows the browsers to notify you at a time that makes sense, for example when the document is idle and all other JavaScript that could make further changes has finished executing, or before the browser restarts the recalc / repaint cycle, so it can apply any changes you make, without having to repeat the cycle shortly after.

It also makes it easier for you to manage, because you can scan through all the changed elements to find what you're looking for, instead of writing lots of case handling code for stuff you don't care about, as was the situation with Mutation Events. And more importantly its only going to call it once, so you don't need to worry that any further changes are going to effect the elements i.e. they are no longer in changing state, they have changed.

So in answer to your question, DOM Mutation Observers are slower because they waited for jQuery to finish its manipulation of the DOM before it notified you of what jQuery changed. Which for the reason explained above and your example, proves it is safer more efficient solution ( you no longer cause an error), and you didn't really care that jQuery added something to the DOM because it would have removed it shortly after. With Observers you would have received a report detailing the jQuery element being added and removed.

This is still a bit troublesome however because you have to figure out what actually happened by matching up elements with all the changes that took place. The reality is that as far as you're concerned nothing happened ( the same element was added and removed ) so nothing has actually changed in the structure of the DOM. To help with this there is a little library called MutationSummary:

http://code.google.com/p/mutation-summary/

That calculates the net effect of the changes and only calls your callback passing in those changes. So in your case your callback would not have been called at all, because the net effect of the change was zero.

E.g. for the following you will only get one change. The body style was changed to left: 1000px. Even though I changed it in 1000 increments. The net effect of the change is only the difference between its initial value and its final one.

function moveBody() {
for (var i = 0; i < 1000; i++) document.body.style.left = i + 'px';
}
moveBody();

How to detect element being added/removed from dom element?

Use Mutation Observers as suggested by @Qantas in his answer


Following methods are deprecated

You can use DOMNodeInserted and DOMNodeRemoved

$("#parent").on('DOMNodeInserted', function(e) {
console.log(e.target, ' was inserted');
});

$("#parent").on('DOMNodeRemoved', function(e) {
console.log(e.target, ' was removed');
});

MDN Docs

Detecting DOM change events

I think what you're looking for is DOMSubtreeModified

Edit: upon further inspection this and other MutationEvents have been deprecated by the W3C but there doesn't appear to be a replacement until DOM Level 4

See: "Why is the DOMSubtreeModified event deprecated in DOM level 3?"

Long story short, DOMSubtreeModified will still work and there is no reasonable alternative implemented across stable browsers.

Firing event on DOM attribute change

Note: As of 2012, Mutation Events have been removed from the standard and are now deprecated. See other answers or documentation for how to use their replacement, MutationObserver.

You are referring to DOM Mutation Events. There is poor (but improving) browser support for these events. Mutation Events plugin for jQuery might get you some of the way.

What's the state of cross-browser support for DOM Mutation Observers?

This feature (DOM mutation) is working from Chrome 18.
You can see more details here: http://updates.html5rocks.com/2012/02/Detect-DOM-changes-with-Mutation-Observers

In case you wish to check 'any' HTML5 feature and the browsers that support it: http://caniuse.com/ is the place.
Other great source is: http://html5please.com/

Firefox : DOM Mutation Events for disconnected nodes?

  1. The DOMNodeRemoved event is fired when an a node (element, text node, comment, ..) is removed from the document/element to which the event is bound.

    document.addEventListener('DOMNodeRemoved', function(event) {
    console.log('Removed node: ' + event.target.nodeName);
    });
  2. Benchmarking two possibilities:

    • A plain loop:

      function isDisconnected(node) {
      var rootElement = document.documentElement;
      while (node) {
      if (node === rootElement)
      return false;
      node = node.parentNode;
      }
      return true;
      }
    • document.contains( node ):

      function isDisconnected(node) {
      return !document.contains(node);
      }


    Result: http://jsperf.com/dom-contains-vs-parentnode

    The document.contains() method significantly (47x) faster than the loop method (whether the nodes are disconnected or not, the document.contains method always outperforms the loop).

  3. The Magic iframe feature does not work in Firefox, as tested using this fiddle: http://jsfiddle.net/GRFsd/

    For those who don't know about this feature: In Chrome, an iframe can be moved from one document to the other, without unloading the frame. This is called the magic iframe feature.

The provided jsfiddle moves an iframe whose src attribute is set to "data:text/html,<script>alert(/Test/);<\/script>". When this URL is loaded, an alert shows up. Two alerts showing up means that the Magic iframe feature is not supported. One alert showing up means that the feature is supported. Zero alerts showing up means that your JavaScript is disabled, or that your browser doesn't support data-URIs.

Why is the DOMSubtreeModified event deprecated in DOM level 3?

If you scroll down a bit, you see:

Warning! The MutationEvent interface was introduced in DOM Level 2
Events, but has not yet been completely and interoperably implemented
across user agents. In addition, there have been critiques that the
interface, as designed, introduces a performance and implementation
challenge. A new specification is under development with the aim of
addressing the use cases that mutation events solves, but in more
performant manner. Thus, this specification describes mutation events
for reference and completeness of legacy behavior, but deprecates the
use of both the MutationEvent interface and the MutationNameEvent
interface.

The replacement API is mutation observers, which are fully specified in the DOM Living Standard that supercedes all of the DOM level X silliness.



Related Topics



Leave a reply



Submit