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:
$(element).on("mouseover", event => $("<a/>").attr("href", "google.com").appendTo(event.target))
can do it. – BaresarkSponsored
is arole="button"
with tabindex 0, which reloads content on click and hover. You can see it in thenetwork
tab as well. Thea
is simply not there before that. It does not matter whether you hover it with DevTools open or not. – Pantelleria