I'm writing an add-on for a page to prevent <a href="#">
scrolling to the top when clicked.
I know href="#!"
, href="javascript:void(0);"
and during the click event event.preventDefault()
are all solutions.
As the page is dynamic, I'm considering 'absorbing' all clicks or using a MutationObserver
. At the moment I've implemented the 1st solution (code below).
I'm wondering if someone could help highlight the up and downsides of each solution to help my decision (or if there is an even better solution / improvement to my code). My concern is how each solution scales as the page becomes more dynamic / has more nodes.
I feel adding a click event for the whole document like I've done should scale the best?
document.body.addEventListener('click', function() {
var hash = false
for (const el of event.composedPath()) {
switch (el.hash) {
case "":
hash = true
case undefined:
continue
}
hash = false
break
}
if (hash) event.preventDefault()
})
To give some context, this is an html5 game and when busiest, there may be 10000+ <a>
tags in the document and maybe thousands being added/subtracted at a time. I don't want the user to experience noticeable lag with every click they make or when the page changes due to my add-on.
You could traverse up the DOM from the clicked element with Element.closest()
and target a link with the specific value in the href
attribute.
If the result is not null
then you use Event.preventDefault()
to cancel the anchor-scrolling from happening
document.addEventListener('click', event => {
const link = event.target.closest('a[href="#"]');
if (link === null) {
return;
}
event.preventDefault();
});