Search code examples
javascriptdommutation-observers

getting the className of added DOM node (mutationObserver)


I'm writing a simple userscript that will auto-hide a Facebook post if it contains a certain list of words. The core functionality works, but my MutationObserver doesn't seem to read the className of mutation.addedNodes properly. I loop through mutation.addedNodes and check if any of those elements have the class userContentWrapper, but the result of that test is always false -- even if the element does have the class.

var startObserver = function() {        
    var observer = new MutationObserver(function(mutations) {        
        mutations.forEach(function(mutation) {            
            var added = mutation.addedNodes;            
            for (var i = 0; i < added.length; i++) {                
                if (/\buserContentWrapper\b/.test(added[i].className)) {
                    processFilter(added[i]);
                }
            }
        });        
    });    
    var obj = {childList: true, subtree: true, attributes: true};
    observer.observe(document.documentElement, obj);
};

I can only assume that the observer is analyzing the added node before it's fully formed with all the attributes in place. How can I make the observer wait to process the node until it's fully complete? Or am I not understanding the problem?

Thanks in advance...


Solution

  • Some of the added nodes are containers so you should check their insides:

    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
          if (node.classList.contains('userContentWrapper')) {
            found.push(node);
          } else if (node.firstElementChild) {
            found.push(...node.getElementsByClassName('userContentWrapper'));
          }
        }
      }
      found.forEach(processFilter);
    }
    

    MutationObserver callback is executed as a microtask that blocks DOM and JS engine so try to make it fast, especially if it runs on a complex site such as facebook that generates lots of DOM mutations. This can be tested in devtools (F12 key) profiler/timeline panels.