4

I've found the MutationObserver documentation to be rather confusing. I would like to observe the document body for when DIV elements having the class superelement are added to the DOM.

<div class="superelement" style="display:none;2"></div>

I've managed to glue this snippet together:

const observer = new MutationObserver(onMutation);
observer.observe(document, {
  childList: true,
  subtree: true,
});

function onMutation(mutations) {
  const found = [];
  for (const { addedNodes } of mutations) {
    for (const node of addedNodes) {
      if (!node.tagName) {
        continue; // not an element
      } else {
        if (node.classList.contains('superelement')) {
          console.log(node)
        }
      }
    }
  }
}

Is there no cleaner way to iterate all elements that were added? I can imagine this being rather slow.

Klokie
  • 5
  • 2
Mridang Agarwalla
  • 43,201
  • 71
  • 221
  • 382
  • `const found = mutations.addedNodes.filter(node => node.tagName.toLowerCase() === 'div' && node.classList.contains('superelement'));` will give you all div tags with that classname from the addedNodes in your mutations event – Derek Jul 02 '20 at 04:24
  • Why would this be slower than any other method? Even if you had a DocumentFragment where you could querySelector, it would still basically do the same thing: ask every elements if it matches the selector. Besides, we don't deal with improving working codes just for the sake of making it a bit better. For this, there is [codereview](https://codereview.stackexchange.com/) on the SE network. – Kaiido Jul 02 '20 at 04:26
  • 1
    1) All performance-related concerns should be verified by measuring, there's no need to guess, see [Performance of MutationObserver to detect nodes in entire DOM](https://stackoverflow.com/a/39332340) 2) Your code will miss nested elements, you also need to check the descendants, [example](https://stackoverflow.com/a/38525456). – wOxxOm Jul 02 '20 at 04:47

1 Answers1

1

I had do to some searching before I could find something that wasn't a total mess. You really only need to do two things; it is a lot easier when you have clean code to work with.

With the first the MutationObserver object will pass a MutationRecord object and a MutationObserver object (no third parameters) when the condition (in this case: {childList: true}) is met:

 const observer = new MutationObserver(function(mutation_record,mutation_observer)
 {
  //Match your condition here:
  if (mutation_record[0] && mutation_record[0].addedNodes[0] && mutation_record[0].addedNodes[0] === id_('modal'))
  {
   //Do a jig.
  }
 });

To start the observation simply define the node as the first parameter and an object containing the conditions:

 observer.observe(tag_('body')[0], {childList: true});

Doing some quick research here is an exhuastive example of the second parameter's object:

{
 attributes: false,
 attributeOldValue: false,
 //attributeFilter: array,
 characterDataOldValue: false,
 childList: true,
 characterData: false,
 subtree: false,
}
John
  • 1
  • 13
  • 98
  • 177