javascriptmutation-observers

Show div based on changed span class


Let's say that I have two span elements. Class is changing width "selected" based on which one is selected. I just need to know when span2 is selected or not.

<span class="swatch swatch-image span1">
<span class="swatch swatch-image span2 selected">

I'm trying to listen which one is selected (which one has class "selected") and then show or don't show div in other place. Is it possible?

I've tried this way:

let targetNode = document.getElementsByClassName('swatch swatch-image span2 selected');

const config = { attributes: true, childList: false, subtree: false, attributeFilter: ['class'] };

const callback = function(mutationsList, observer) {
    for (let mutation of mutationsList) {
        if (mutation.attributeName === "class") {
            var classList = mutation.target.className;
            if(/red/.exec(classList).length > 0) {
                console.log('Found match');
            }
        }
    }
};

const observer = new MutationObserver(callback);

observer.observe(targetNode, config);

observer.disconnect();

Is MutationObserver is proper way to listen which span is selected? I'm not familiar with javascript, do I need to call MutationObserver somehow after constructing code?


Solution

  • Find the closest container enclosing the spans and delegate

    window.addEventListener('DOMContentLoaded',() => { // when page has loaded
      const container = document.getElementById('someContainer'); // change as needed 
      container.addEventListener('click', (e) => {
        const tgt = e.target.closest('span.swatch');
        if (!tgt) return; // not a swatch
        console.log(tgt.textContent, 'clicked')
        document.getElementById('showWhenSpan2').hidden = !tgt.matches('.span2')
      });
    
    // somewhere else out of your control
      document.addEventListener('click', (e) => {
        const tgt = e.target.closest('span.swatch');
        if (!tgt) return; // not a swatch
        document.querySelectorAll('span.swatch').forEach(span => span.classList.toggle('selected',span===tgt))
      });
    
    
    
    });
    .selected { border: 1px solid red; }
    <div id="someContainer">
    ...
    
    <span class="swatch swatch-image span1 selected">Span 1</span>
    <span class="swatch swatch-image span2">Span 2</span>
    
    
    ...
    </div>
    
    <div id="showWhenSpan2" hidden>Shown when span 2 is clicked</div>