Home > Software engineering >  ChildNodes seemingly not existing in DOM while using MutationObserver
ChildNodes seemingly not existing in DOM while using MutationObserver

Time:03-17

I am trying to use MutationObserver to observe changes in the DOM but it seems like I can't access the "grand"-children nodes. I have configured the observer with subtree and childList values. As I understand, it is not possible to get the entire DOM-tree of added childLists or changes with the MutationObserver, all it does is observe the changes. Instead you are supposed to use getElementById.

I've tried using getElementById to find the relevant "parent"-node in the DOM after the change is observed, and then crawl all the childNodes. Although I still get no hits on the childNodes.

I assume the "parent"-node is inserted onto the DOM first, and the childNodes are then inserted on to the "parent"-node after the fact, though these events are not triggered in the observer for some reason.

I suspect I might need to update the target of the MutationObserver as I observe the changes, and then continuously use getElementById and crawl these nodes.

Any idea on why these childNodes are not observable, and/or how to approach the solution to this?

Best regards.

Code to MutationObserver

function createObserver() {
    const documentBody = document.body;

    // callback function to execute when mutations are observed
    const observer = new MutationObserver(mutationRecords => {
        let addedNodes = []

        for (const mut of mutationRecords) {

            let arr = Array.prototype.slice.call(mut.addedNodes)
            arr = arr.filter(node => popupTagNames.includes(node.tagName)); // Keep only selected tags

            if (arr.length == 0) return; // don't keep empty

            addedNodes = addedNodes.concat(arr)

            let el = document.getElementById(addedNodes[0].id);

            // Crawler
            inspectNode(el)
        }


    })

    const config = { attributes: true, childList: true, subtree: true, characterData: true }
    observer.observe(documentBody, config)
}

CodePudding user response:

Let's investigate by logging the added nodes that belong to #qc-cmp2-container element:

new MutationObserver(mutations => {
  const parent = document.getElementById('qc-cmp2-container');
  if (parent) console.log(...mutations.flatMap(m =>
    [...m.addedNodes].filter(n => parent.contains(n)).map(n => n.cloneNode(true))));
}).observe(document, {subtree: true, childList: true});

We'll see several separate calls:

  1. The main #qc-cmp2-container and its empty child
  2. An inner div with a lot of child elements and text
  3. Two additional inner elements are added

The most resource-effective solution is to wait for the parent using the super fast getElementById check and then switch to observing the parent:

function waitForId(id, callback) {
  let el = document.getElementById(id);
  if (el) {
    callback(el);
  } else {
    new MutationObserver((mutations, observer) => {
      el = document.getElementById(id);
      if (el) {
        observer.disconnect();
        callback(el);
      }
    }).observe(document, { subtree: true, childList: true });
  }
}

waitForId('qc-cmp2-container', parent => {
  new MutationObserver((mutations, observer) => {
    // do something
  }).observe(parent, { subtree: true, childList: true });
});
  • Related