The approach I took to solve this issue is as follows:
// using an IIFE ("Immediately-Invoked Function Expression"):
(function() {
'use strict';
// using Arrow function syntax to define the callback function
// supplied to the (later-created) mutation observer, with
// two arguments (supplied automatically by that mutation
// observer), the first 'mutationList' is an Array of
// MutationRecord Objects that list the changes that were
// observed, and the second is the observer that observed
// the change:
const nodeRemoval = (mutationList, observer) => {
// here we use Array.prototype.forEach() to iterate over the
// Array of MutationRecord Objects, using an Arrow function
// in which we refer to the current MutationRecord of the
// Array over which we're iterating as 'mutation':
mutationList.forEach( (mutation) => {
// if the mutation.addedNodes property exists and
// also has a non-falsy length (zero is falsey, numbers
// above zero are truthy and negative numbers - while truthy -
// seem invalid in the length property):
if (mutation.addedNodes && mutation.addedNodes.length) {
// here we retrieve a list of nodes that have the
// "aria-label" attribute-value equal to 'Advertiser link':
mutation.target.querySelectorAll('[aria-label="Advertiser link"]')
// we use NodeList.prototype.forEach() to iterate over
// the returned list of nodes (if any) and use (another)
// Arrow function:
.forEach(
// here we pass a reference to the current Node of the
// NodeList we're iterating over, and use
// ChildNode.remove() to remove each of the nodes:
(adLink) => adLink.remove() );
}
});
},
// here we retrieve the <body> element (since I can't find
// any element with a predictable class or ID that will
// consistently exist as an ancestor of the ad links):
targetNode = document.querySelector('body'),
// we define the types of changes we're looking for:
options = {
// we're looking for changes amongst the
// element's descendants:
childList: true,
// we're not looking for attribute-changes:
attributes: false,
(if this is false, or absent, we look only to
changes/mutations on the target element itself):
subtree: true
},
// here we create a new MutationObserver, and supply
// the name of the callback function:
observer = new MutationObserver(nodeRemoval);
// here we specify what the created MutationObserver
// should observe, supplying the targetNode (<body>)
// and the defined options:
observer.observe(targetNode, options);
})();
I realise that in your question you're looking for elements that match a different attribute and attribute-value (document.querySelector('a[href*="/ads/about"]')
) but as that attribute-value wouldn't match my own situation I couldn't use it in my code, but it should be as simple as replacing:
mutation.target.querySelectorAll('[aria-label="Advertiser link"]')
With:
mutation.target.querySelector('a[href*="/ads/about"]')
Though it's worth noting that querySelector()
will return only the first node that matches the selector, or null
; so you may need to incorporate some checks into your code.
While there may look to be quite a bit of code, above, uncommented this becomes merely:
(function() {
'use strict';
const nodeRemoval = (mutationList, observer) => {
mutationList.forEach( (mutation) => {
if (mutation.addedNodes && mutation.addedNodes.length) {
mutation.target.querySelectorAll('[aria-label="Advertiser link"]').forEach( (adLink) => adLink.remove() );
}
});
},
targetNode = document.querySelector('body'),
options = {
childList: true,
attributes: false,
subtree: true
},
observer = new MutationObserver(nodeRemoval);
observer.observe(targetNode, options);
})();
References: