When You Need To Modify An Element That Hasn’t Loaded Yet
When trying to apply ADA-compliant identifiers to elements that have been created from within a plugin, we can sometimes run into problems. Some plugins won’t let you modify the output, especially elements that need to have ADA specifications applied like a slider’s navigation, form labels, or other elements. You’re normally meant to utilize filters in order to control the HTML output of plugins, but oftentimes they aren’t offered by plugin manufacturers. You can’t hack the plugin files, because each plugin will need to be updated in the future for security and enhancements, so you may have to turn to JavaScript in these cases. But what happens when these elements are being loaded onto the screen with JavaScript and you’re unable to target any of them because they don’t exist on page load?
In the search for a solution to my problem, I found this wonderful answer on StackOverflow. User Yong Wang pointed both the asker of the question and me to a MutationObserver interface. This is something that can be used to watch the DOM and await the element you want to change. Yong Wang even provided a handy script that I was able to modify and use to fire a function once the element I needed to target was rendered.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | function waitForElm(selector) { return new Promise(resolve => { if (document.querySelector(selector)) { return resolve(document.querySelector(selector)); } const observer = new MutationObserver(mutations => { if (document.querySelector(selector)) { resolve(document.querySelector(selector)); observer.disconnect(); } }); observer.observe(document.body, { childList: true, subtree: true }); }); } |
What this nice little function does is set a watcher on the document that will trigger once the element appears. If you’re working with plugins that render HTML on page load, you will have to wait for those elements to appear in order to manipulate them. In the following example, we’re waiting for a slider’s navigation – using the class .nav-slidebuttons – to render in order to add aria-current values to the anchors within that element.
1 2 3 4 5 6 7 8 9 10 11 | waitForElm('.nav-slidebuttons').then((elm) => { var $div = $(".ls-bottom-slidebuttons a"); var numItems = $($div).length; var observer = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { var attributeValue = $(mutation.target).prop(mutation.attributeName); $('.nav-slidebuttons a').attr("aria-current","false"); $('.nav-slidebuttons a.nav-active').attr("aria-current","true"); }); }); }); |
This function waits for the .nav-slidebuttons container to be written by the plugin’s JavaScript and once it exists, sets the “aria-current” attribute to false for each of the anchor links inside of it. Then, we find the navigation item with the class .nav-active (the class that is applied to the currently active slide) and define aria-current to true. This allows screen readers the ability to identify which slide is active, helping out those with sight disabilities.
With the help of those who are gracious enough to answer questions on StackOverflow and similar sites, many of us are able to figure out the answers we sorely need. It is my opinion that being able to research and learn is what helps any and every developer succeed in their line of work.