Reputation: 33
I want to create a listener that detects changes on a specified tag, when DOM updates have been applied to a new tag.
In this case, I have a chat app and I need to get all the new <audio>
tags, and apply a class on those new tags only.
How I create a specified listener just for one tag?
For performance reasons, I don't want to create a setInterval
. Is there another way to achieve this and how?
Upvotes: 2
Views: 1791
Reputation: 30360
If I understand correctly, you'd like to detect when an <audio/>
element is added to your document and, on detecting this event, assign a CSS class to that newly added audio
element.
One possibility that avoids polling, would be to use a MutationObserver - a simple solution would be to observe the body
element for any changes in it's childList
or subtree
and, for any changes that are detected that are caused by a newly added audio
node, add the required class to that audio
node:
/* Mutation handler will assign "addedAudio" class to
any newly added audio elements */
function onMutation(mutations) {
for (const mutation of mutations) {
if (mutation.type === 'childList') {
/* This mutation type is a change to tree nodes in dom */
for (const addedNode of mutation.addedNodes) {
if (addedNode.nodeName === 'AUDIO') {
/* The node triggering this mutation is an audio node */
addedNode.classList.add("addedAudio");
}
}
}
}
}
/* Create dom mutation observer with callback, and
bind observer to body (eg "root") of your web app
and watch all children and subtrees for any changes */
(new MutationObserver(onMutation))
.observe(document.querySelector("body"), {
childList: true,
subtree: true
})
/* For demo purpose only to simulate adding new audio element to document */
document.querySelector('button').addEventListener('click', () => {
const audio = document.createElement("audio");
audio.setAttribute('controls', true);
audio.setAttribute('src', 'https://www.w3schools.com/html/horse.ogg');
document.body.prepend(audio);
});
.addedAudio {
border: 1px solid red;
}
<button>Add audio</button>
Note that a more efficient approach would be to observe a DOM node that has fewer children, shallow sub-tree, etc. For instance, if all audio
elements are added to a common DOM element, consider observing that element instead, rather than the body
.
Hope that's of some user!
Upvotes: 3