Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

How to Track Changes in the DOM Using MutationObserver

DZone's Guide to

How to Track Changes in the DOM Using MutationObserver

Want to learn how to detect and record in changes in the DOM of your site? Read on to learn how to use the MutationObserver API.

· Web Dev Zone
Free Resource

Should you build your own web experimentation solution? Download this whitepaper by Optimizely to find out.

What Is MutationObserver?

MutationObserver is a Web API provided by modern browsers for detecting changes in the DOM. With this API one can listen to newly added or removed nodes, attribute changes, or make changes in the text content of text nodes.

Why would you want to do that?

There are quite a few cases in which the MutationObserver API can really come in handy. For instance, you might be working on a WYSIWYG editor, trying to implement undo/redo functionality. By leveraging the MutationObserver API, you know at any given point what changes have been made, so you can easily undo them. Or, let’s say you want to notify your web app visitor that some change has occurred on the page he’s currently on. Another example: you’re working on a new fancy JavaScript framework that dynamically loads JavaScript modules based on how the DOM changes. These are just a few examples of how the MutationObserver can be of help.

Image title

Alternatives

The MutationObserver, however, has not always been around. So what did developers resort to before the MutationObserver came along? The simplest and most unsophisticated way was by polling. Using the browser setInterval Web API you can set up a task that would periodically check if any changes occurred. Naturally, this method significantly degraded web app/website performance.

In the year 2000, the MutationEvents API was introduced. Albeit useful, mutation events are fired on every single change in the DOM which again causes performance issues. Nowadays, the MutationEvents API has been deprecated, and soon modern browsers will stop supporting it altogether.

A somewhat strange alternative is one that relies on CSS animations. It might sound a bit confusing. Basically, the idea is to create an animation which would be triggered once an element has been added to the DOM. The moment the animation starts, the animationstart event will be fired: if you have attached an event handler to that event, you’d know exactly when the element has been added to the DOM. The animation’s execution time period should be so small that it’s practically invisible to the user. You can check out David Walsh’s blog post for more details on its implementation.

MutationObserver offers a number of advantages over the above-mentioned solutions. In essence, it covers every single change that can possibly occur in the DOM and it’s way more optimized, as it fires the changes in batches. On top of that, MutationObserver is supported by all modern major browsers, along with a couple of polyfills which use MutationEvents under the hood.

How to Use MutationObserver

Implementing MutationObserver into your app is rather easy. You need to create a MutationObserver instance by passing it a function that would be called every time a mutation has occurred. The first argument of the function is a collection of all the mutations which have occurred in a single batch. Each mutation provides information about its type and the changes which have occurred.

var mutationObserver = new MutationObserver(function(mutations) {
    mutations.forEach(function(mutation) {
        console.log(mutation);
    });
});


The created object has three methods:

  • observer – starts listening for changes. Takes two arguments – the DOM node you want to observe and a settings object.
  • disconnect – stops listening for changes.
  • takeRecords – returns the last batch of changes before the callback has been fired.


// Starts listening for changes in the root HTML element of the page.
mutationObserver.observe(document.documentElement, {
    attributes: true,
    characterData: true,
    childList: true,
    subtree: true,
    attributeOldValue: true,
    characterDataOldValue: true
});


// Takes all changes which haven’t been fired so far.
var changes = mutationObserver.takeRecords();

// Stops the MutationObserver from listening for changes.
mutationObserver.disconnect();


MutationObserver occupies a central position in SessionStack. SessionStack doesn’t record an actual video but is rather listening for the changes in the website/web app. Later on, these changes will be recreated in a sandboxed environment which results in the session being replayed just like an ordinary video. The difference is that it’s way lighter than a recorded video, both in terms of CPU and network traffic.

Getting ever more popular, MutationObserver is a really useful tool that can have various use cases. Certainly a great addition to the web developer’s toolbox!

Implementing an Experimentation Solution: Choosing whether to build or buy?

Topics:
javascript ,web dev ,css ,dom

Published at DZone with permission of Antonia Bozhkova, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}