sliptype
sliptype

Reputation: 2964

MutationObserver class changes

I am using MutationObserver to detect when a specific class has been added to an element.

const observer = new MutationObserver((mutations) => { 
    mutations.forEach((mutation) => {
      const el = mutation.target;
      if ((!mutation.oldValue || !mutation.oldValue.match(/\bis-busy\b/)) 
        && mutation.target.classList 
        && mutation.target.classList.contains('is-busy')){
        alert('is-busy class added');
      }
    });
 });

observer.observe(document.querySelector('div'), { 
  attributes: true, 
  attributeOldValue: true, 
  attributeFilter: ['class'] 
});

My question is: Is there a better way to verify that this is a newly added class? Currently I am using regex to check that the class didn't exist previously and classList to check that the class exists now. Seems messy

Fiddle

Upvotes: 32

Views: 31050

Answers (3)

emir
emir

Reputation: 1406

For me the solution that Reena provided didn't work but I liked the solution. I had an error S2339: Property 'classList' does not exist on type 'Node'.

The solution was to save target as HTMLElement

let observer = new MutationObserver(function(mutations) {
    mutations.forEach(function(mutationRecord) {
        const targetElement = mutationRecord.target as HTMLElement;
        if (targetElement.className === "is-busy") {
            console.log("Class added....")

        } else {
            console.log("Class not added....")
        };
    })
});

Upvotes: 0

Reena Verma
Reena Verma

Reputation: 1685

You could try accessing classname on the target?

let observer = new MutationObserver(function(mutations) {
    mutations.forEach(function(mutationRecord) {
        if (mutationRecord.target.className === "is-busy") {
            console.log("Class added....")

        } else {
            console.log("Class not added....")
        };
    })
});

let target = document.querySelector("your-div");

// MDN documentation
// https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver/observe#attributefilter
observer.observe(target, {
 attributes : true,
 attributeFilter : ['style', 'class']
});

Upvotes: 4

Naman Sancheti
Naman Sancheti

Reputation: 565

@sliptype - You could do it in the below manner:

const element = document.querySelector('div');
let prevState = element.classList.contains('is-busy');
const observer = new MutationObserver((mutations) => { 
    mutations.forEach((mutation) => {
        const { target } = mutation;

        if (mutation.attributeName === 'class') {
            const currentState = mutation.target.classList.contains('is-busy');
            if (prevState !== currentState) {
                prevState = currentState;
                console.log(`'is-busy' class ${currentState ? 'added' : 'removed'}`);
            }
        }
    });
});

Upvotes: 18

Related Questions