JAVASCRIPT
Observing and Reacting to DOM Changes with MutationObserver
Monitor specific DOM nodes for additions, removals, attribute changes, or text content modifications using the `MutationObserver` API for advanced reactivity.
function observeDOMChanges(targetNodeId, callback, options = {}) {
const targetNode = document.getElementById(targetNodeId);
if (!targetNode) {
console.error(`Target node with ID "${targetNodeId}" not found.`);
return null;
}
// Default options for common use cases
const observerOptions = {
childList: true, // Observe direct children additions/removals
subtree: false, // Observe descendants as well
attributes: false, // Observe attribute changes
attributeFilter: [], // Array of attribute names to observe
characterData: false, // Observe changes to text content
...options
};
const observer = new MutationObserver((mutationsList, observerInstance) => {
for (const mutation of mutationsList) {
callback(mutation, observerInstance);
}
});
observer.observe(targetNode, observerOptions);
return observer; // Return the observer instance so it can be disconnected later
}
// Example Usage:
// <div id="container-to-observe">
// <p>Initial paragraph</p>
// </div>
// <button id="add-element">Add Element</button>
// <button id="change-attr">Change Attribute</button>
// Add an element dynamically
// document.getElementById('add-element').addEventListener('click', () => {
// const newDiv = document.createElement('div');
// newDiv.textContent = 'Dynamically added item ' + Date.now();
// newDiv.className = 'new-item';
// document.getElementById('container-to-observe').appendChild(newDiv);
// });
// Change an attribute
// document.getElementById('change-attr').addEventListener('click', () => {
// const firstP = document.getElementById('container-to-observe').querySelector('p');
// if (firstP) {
// firstP.setAttribute('data-updated', Date.now());
// } else {
// const newP = document.createElement('p');
// newP.textContent = 'New P for attribute change';
// newP.setAttribute('data-updated', Date.now());
// document.getElementById('container-to-observe').appendChild(newP);
// }
// });
// Observe childList changes
// const observer1 = observeDOMChanges('container-to-observe', (mutation) => {
// if (mutation.type === 'childList') {
// console.log('Child list changed:', mutation.addedNodes, mutation.removedNodes);
// }
// }, { childList: true });
// Observe attribute changes on subtree
// const observer2 = observeDOMChanges('container-to-observe', (mutation) => {
// if (mutation.type === 'attributes') {
// console.log(`Attribute "${mutation.attributeName}" changed on:`, mutation.target);
// }
// }, { subtree: true, attributes: true });
// To stop observing later:
// observer1.disconnect();
How it works: `MutationObserver` is a powerful API that allows you to detect changes in the DOM tree. This snippet demonstrates how to create and use an observer to react to various modifications, such as adding or removing child nodes (`childList`), changing attributes (`attributes`), or modifying text content (`characterData`). It's highly useful for scenarios where you need to react to dynamic content loaded by other scripts or user interactions, providing a more robust alternative to polling.