dom-observer

An abstraction for Mutation Observer with some extra features

Usage no npm install needed!

<script type="module">
  import domObserver from 'https://cdn.skypack.dev/dom-observer';
</script>

README

dom-observer

Build TestCoverage SemVer License

Tests

An abstraction for Mutation Observer with some extra features in ~1kb gzipped.

Useful to observe an DOM element for changes without taking too much hit on performance, the Mutation Observer technique is used by many libraries and frameworks.

This lib intention is to provide quick and simple access to the Mutation Observer features by abstracting the API into a simple function call and adding some handy methods.

Getting Started

As usual most package managers are supported.

NPM

npm install dom-observer

Bower

bower install dom-observer

Direct Download

  1. Download ZIP
  2. Unzip
  3. Grab the JS in the dist folder.
  4. Profit!

CDN

RawGit

Basic Usage

It's really simple if you know how Mutation Observers work.

This lib is designed to ease your life when dealing with MOs.

Take a look at this:

// My function that handle mutations
function handleMutations(mutations) {
  mutations.forEach(mutation, () => {
    console.log('YO', mutation);
  });
}

// Import the module, a global var is exposed too if you're not into modules
import observe from 'dom-observer';
const myTarget = document.body;
const myObserver = observe(myTarget, handleMutations);

That would be the same as doing the following using just the MutationObserver:

// My function that handle mutations
function handleMutations(mutations) {
  mutations.forEach(mutation, () => {
    console.log('YO', mutation);
  });
}

const myTarget = document.body;
const myObserver = new MutationObserver(handleMutations);
myObserver.observe(myTarget, {
  attributes: true,
  childList: true,
  characterData: true
});

Notice that with the lib we default to all 3 properties (attributes, childList and characterData) true when you pass no object.

Of course you can specify to just observe attributes by setting it explicitly to true, then the lib will respect that.

In fact, the observe function second argument is MutationObserverInit object. Meaning it will respect options like subtree or attributeFilter too. Please check the MO docs if you're lost.

As you would expect the callback, in this case the handleMutations function, receives as first argument an array of MutationRecord so you can handle the DOM mutations as you please.

Passing options

You can pass any option already specified in the MutationObserverInit object and two other special properties that you can use:

onlyFirstChange

It tells the observer to only send the first change to the callback and then unregister the observer.

Example:

// Importing ES module
import observe from 'dom-observer';

// Getting my target
const target = document.body;

// Registering the handler
const mutationHandler = (mutations) => mutations.forEach(mutation, () => console.log(mutation));

// Making my observer getting only the first mutation/change
const myObserver = observe(target, mutationHandler, { onlyFirstChange: true });

// Will trigger mutation = first mutation will be reported to the handler
document.body.appendChild(document.createElement('div'));

// Trigger a second mutation, will not be reported because the myObserver already unregistered
document.body.appendChild(document.createElement('div'));

onlyLastChange

Sometimes more than one mutation is filed in a render cycle, so you can get just the last one by setting this property.

Example:

// Importing ES module
import observe from 'dom-observer';

// Getting my target
const target = document.body;

// Registering the handler
const mutationHandler = (mutations) => mutations.forEach(mutation, () => console.log(mutation));

// Making my observer getting only the first mutation/change
const myObserver = observe(target, mutationHandler, { onlyLastChange: true });

// If the browser batches the mutations this mutation will not be reported
document.body.appendChild(document.createElement('div'));

// This mutation will be reported
document.body.appendChild(document.createElement('div'));

Adding targets to the observer

It's not recommended but you can add a new target to an existent observer with addTarget.

The lib allows you to add a new target while maintaining the config from the constructor.

myObserver.addTarget(document.querySelector('#myElement'));

Adding a new target with new config

If you want to add an entirely new target with config you can do it too with andObserve.

myObserver.andObserve(document.querySelector('#myElement'), {
  attributes: true
});

Chaning the function that handles mutations on the fly

You can change the callback you set on the observe function later on with changeCallback.

function myNewFunc(mutations) {
  console.log('I\'m handling the changes now!');
}
myObserver.changeCallback(myNewFunc);

Taking records

This mirrors the behaviors of the original Mutation Observer takeRecords() method. It works as you expect.

myObserver.takeRecords(); // Will return the records cached

Wipe

This new handy function wiped the records cache and returns a chainable instance of dom-observer.

myObserver.wipe(); // Cache is now clean and returns myObserver

Chaining

The lib was designed to make it easy to chain functionality.

const myObserver = observe(myTarget, handleMutations)
  .addTarget(document.querySelector('#otherElement'))
  .andObserve(document.querySelector('#yetAnotherElement'), {
    childList: true
  });

Docs

Online Docs

While developing the npm run docs script updates the local docs in the docs folder.

License

MIT License