MutationObserver – The Coolest API I’m Not Using, But Should Be

Ninja Kick: WordPress Contact Form Plugin is a great plugin and well worth its modest cost. It provides a responsive, off-canvas solution for displaying forms. You can have multiple Ninja Kick forms on one page, but you can only configure the tab to display one label. In the example below, the default label is “Request a Demo”.

ninjakick

I wanted to dynamically change the label depending on the form that is currently displayed. I can change the label text with CSS, using the after pseudo-class to change the content.

.ncf_form_3 .nks_cc_trigger_tabs .ncf-tab-icon:after{
content: 'Download Data Sheet';
}

However, if a user closes the panel, I wanted to return to the default “Request a Demo” label and form. I needed to detect the close action. I could modify the Ninja Kick plugin’s Javascript, including my code as part of their close action, but those changes would be lost with each update.

As it turns out, as part of Ninja Kick’s close action, the class of the panel updates to include the ncf_shrinked class. If only there was a way to detect that class change and add my own code when that happens. Enter: MutationObserver.

The MutationObserver API is a lightweight listener for DOM changes and is well supported in modern browsers. For a good tutorial, check out David Walsh’s blog. Below is my example specific to my Ninja Kick forms use case.

var $div = $('.ncf_sidebar_cont');
var observer = new MutationObserver(function(mutations){
mutations.forEach(function(mutation) {
if(mutation.attributeName === "class"){
var attributeValue = $(mutation.target).prop(mutation.attributeName);
if(attributeValue == "ncf_sidebar_cont ncf_shrinked"){
// clear all ncf_form prefixed classes
$('body').removeClass(function(index, css){
return(css.match(/(^|\s)ncf_form_\S+/g) || []).join(' ');
});
}
}
});
});
observer.observe($div[0], {
attributes: true
});

I am detecting the class change of the ncf_sidebar_cont panel. When that change happens, I’m checking for the additional ncf_shrinked class. If that class is present, I remove my arbitrary classes — prefixed with ncf_form_ — from the body tag that I use to dynamically change the label. This reverts the label back to the default “Request a Demo”.

It works great, and it’s an API that I can see using in the future. Imagine having a well-supported, performant way to detect DOM changes that doesn’t require complex listeners or triggers. You have that capability now with MutationObserver.