I am currently trying to use the MutationObserver API to fire a message (which later will be functions) based on class change of an element.
I'm currently firing a log on mutation change, but I'm assuming there are mutations such as DOM position etc that are firing. Is there a way to make the MutationObserver
only look for specific attributes
in this case the class
?
As primarily a Drupal developer I'm used to using jQuery and that's why I have the classList function as I like chaining.
Here is my code:
var foo = document.getElementById("foo");
var wrapper = document.getElementById("wrapper");
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
if (mutation.attributeName === "class") {
var attributeValue = mutation.target.getAttribute(mutation.attributeName);
console.log("Class attribute changed to:", attributeValue);
}
});
});
function classList(el) {
var list = el.classList;
return {
add: function(c) {
if (!list.contains(c)){
console.log('Contains: '+list.contains(c));
list.add(c);
}
return this;
},
remove: function(c) {
if (!list.contains(c)){
list.remove(c);
}
return this;
}
};
}
observer.observe(foo, {
attributes: true
});
wrapper.addEventListener("scroll",function(){
classList(foo).add('red').remove('yellow');
if(wrapper.scrollTop > 500){
classList(foo).add('yellow').remove('red');
}
});
#wrapper {
height: 200px;
overflow: scroll;
}
#foo {
height: 1000px;
}
<div id="wrapper">
<div id="foo">Element</div>
</div>
Although @wOxxOm answered my question(negligence) in his comment, I applied the functionaily and realised that I no longer needed a forEach as I was only expecting a singular attribute, so the finished(test) code looks like:
var foo = document.getElementById("foo");
var wrapper = document.getElementById("wrapper");
var observer = new MutationObserver(function(mutation) {
console.log('Current class:' + mutation[0].target.className);
});
observer.observe(foo, {
attributes: true,
attributeFilter: ['class']
});
wrapper.addEventListener("scroll",function(){
if(wrapper.scrollTop > 500){
if(!foo.classList.contains('yellow')){
foo.classList.add('yellow');
foo.classList.remove('red');
}
} else {
if(!foo.classList.contains('red')){
foo.classList.add('red');
foo.classList.remove('yellow');
}
}
});
#wrapper {
height: 200px;
overflow: scroll;
}
#foo {
height: 1000px;
}
<div id="wrapper">
<div id="foo">Element</div>
</div>
I have tidied up the mutation observer to find the class name. I removed my function to allow me to chain the class elements, as I came across an issue where it was triggering the mutation even when the class was not changed, just because the element was being returned.