A Guide to Listening for DOM Elements using MutationObserver
Detecting Element Creation and Modification: Mastering Real-Time DOM Interactions with MutationObserver
Welcome to my blog post, "Unlocking Web Interactivity: A Practical Guide to DOM Manipulation with Chrome Extensions"! As web developers and power users, we often find ourselves needing to interact with web pages in ways that were not originally intended by their creators. Chrome extensions offer a fantastic solution for this, allowing us to harness the power of the Document Object Model (DOM) and create customised experiences on the web.
In this comprehensive guide, we will delve into the art of DOM manipulation using Chrome extensions. We'll explore techniques for waiting for a DOM element to load, listening for changes on specified elements, and continuously monitoring element creation to capture them as they appear. Whether you're a seasoned developer or just starting out, this blog will equip you with the tools and knowledge you need to take your web page interactions to the next level. So, let's dive in and start unlocking the full potential of web interactivity!
Also, don’t forget to checkout my blog on How to Build a Chrome extension using Manifest version 3?
How to wait for a DOM element to load?
To wait for a particular DOM element to load using a Chrome extension, you can create a function that uses MutationObserver to monitor changes in the DOM and then checks if the element matching the specified selector is present. Here's a step-by-step guide on how to do this:
In your Chrome extension's content script, create a function called
waitForElementthat takes a selector as an argument:function waitForElement(selector) { return new Promise((resolve, reject) => { // Your code to wait for the DOM element will go here }); }Inside the
waitForElementfunction, create aMutationObserverto monitor changes in the DOM:const observer = new MutationObserver((mutations, observerInstance) => { // Your code to check for the DOM element will go here });Now, create a function to check if the element matching the specified selector is present in the DOM. If the element is present, resolve the promise and disconnect the
MutationObserver:const checkForElement = () => { const element = document.querySelector(selector); if (element) { resolve(element); observer.disconnect(); } };Call the
checkForElementfunction once before observing DOM changes to handle the case where the element is already present in the DOM:checkForElement();Set the
MutationObserverto observe the entire document and listen for changes in the child elements:observer.observe(document.documentElement, { childList: true, subtree: true, });The complete
waitForElementfunction should look like this:function waitForElement(selector) { return new Promise((resolve, reject) => { const observer = new MutationObserver((mutations, observerInstance) => { const checkForElement = () => { const element = document.querySelector(selector); if (element) { resolve(element); observer.disconnect(); } }; checkForElement(); }); checkForElement(); observer.observe(document.documentElement, { childList: true, subtree: true, }); }); }
To use this function, simply call it with the desired selector and wait for the returned promise to resolve
(async () => {
let element = await waitForElement('#your-selector')
})();How to listen for a particular element with a selector and perform an action when it appears?
To listen for a particular element with a selector and perform an action when it appears, you can use the MutationObserver API. Here's a step-by-step guide on how to do this:
Create a function called
observeElementCreationthat takes a selector and a callback function as arguments:function observeElementCreation(selector, callback) { // Your code to observe DOM changes will go here }Inside the
observeElementCreationfunction, create aMutationObserverto monitor changes in the DOM:const observer = new MutationObserver((mutations) => { // Your code to check for the DOM element will go here });For each mutation, check if any of the added nodes match the specified selector. If a matching node is found, call the provided callback function with the node as an argument:
mutations.forEach((mutation) => { for (const addedNode of mutation.addedNodes) { if (addedNode.matches && addedNode.matches(selector)) { callback(addedNode); } } });Set the
MutationObserverto observe the entire document and listen for changes in the child elements:observer.observe(document.documentElement, { childList: true, subtree: true, });The complete
observeElementCreationfunction should look like this:function observeElementCreation(selector, callback) { const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { for (const addedNode of mutation.addedNodes) { if (addedNode.matches && addedNode.matches(selector)) { callback(addedNode); } } }); }); observer.observe(document.documentElement, { childList: true, subtree: true, }); }
To use this function, simply call it with the desired selector and a callback function:
observeElementCreation('#your-selector', (element) => {
console.log('Element found:', element);
// Perform your desired action with the element here
});This function will continuously listen for the creation of DOM elements matching the specified selector, and call the provided callback function each time a matching element appears.

