I want to return the following function if the user clicks a children of the anchor:
<a href="/product/product-id">
I am a product
<div>
Add to favorites
</div>
</a>
const handleClick = (event) =>{
console.log(event);
// true -> if i click any of its children aka. the add to favorites
if(true){
event.preventDefault();
return;
}
// Route is about to change
NProgress.start();
}
document.addEventListener('click', handleClick);
How can i do such thing?
Edit 1:
This is my react.js/next13/next14 code:
'use client';
export default function NextNProgress() {
useEffect(() => {
NProgress.configure();
function isAnchorOfCurrentUrl(currentUrl: string, newUrl: string) {
const currentUrlObj = new URL(currentUrl);
const newUrlObj = new URL(newUrl);
// Compare hostname, pathname, and search parameters
if (
currentUrlObj.hostname === newUrlObj.hostname &&
currentUrlObj.pathname === newUrlObj.pathname &&
currentUrlObj.search === newUrlObj.search
) {
// Check if the new URL is just an anchor of the current URL page
const currentHash = currentUrlObj.hash;
const newHash = newUrlObj.hash;
return (
currentHash !== newHash &&
currentUrlObj.href.replace(currentHash, '') === newUrlObj.href.replace(newHash, '')
);
}
return false;
}
const htmlElements = document.querySelectorAll('html');
function findClosestAnchor(element: HTMLElement | null): HTMLAnchorElement | null {
while (element && element.tagName.toLowerCase() !== 'a') {
element = element.parentElement;
}
return element as HTMLAnchorElement;
}
function handleClick(event: MouseEvent) {
try {
const target = event.target as HTMLElement;
const anchor = findClosestAnchor(target);
const newUrl = anchor?.href;
if (newUrl) {
const currentUrl = window.location.href;
// const newUrl = (anchor as HTMLAnchorElement).href;
const isExternalLink = (anchor as HTMLAnchorElement).target === '_blank';
const isBlob = newUrl.startsWith('blob:');
const isAnchor = isAnchorOfCurrentUrl(currentUrl, newUrl);
if (newUrl === currentUrl || isAnchor || isExternalLink || isBlob || event.ctrlKey) {
NProgress.start();
NProgress.done();
[].forEach.call(htmlElements, function (el: Element) {
el.classList.remove('nprogress-busy');
});
} else {
NProgress.start();
(function (history) {
const pushState = history.pushState;
history.pushState = function () {
NProgress.done();
[].forEach.call(htmlElements, function (el: Element) {
el.classList.remove('nprogress-busy');
});
return pushState.apply(history, arguments as any);
};
})(window.history);
}
}
} catch (err) {
NProgress.start();
NProgress.done();
}
}
// Add the global click event listener
document.addEventListener('click', handleClick);
return () => {
document.removeEventListener('click', handleClick);
};
}, []);
return styles;
}
For those who were asking why i tagged this as react/next… this is the code i hacked to work with nprogress library… I think next will soon add router events back but for the mean time this is what i have done so far…
2
Answers
The easiest way of achieving your objective would be to add an event listener directly to the
div
inside the firsta
element:As there was nothing React specific in the question I provided the above answer for a page with Vanilla JavaScript. This is probably not "the React way" of doing things.
If you want to work with the "global event handler" you can try the following:
You can try using
event.stopPropagation
in your<div>
element.Something like this:
HTML
JS
I hope helped you