Created
June 24, 2023 09:46
-
-
Save revisualize/3c6bf297487dfa3ce38c2872735b6b5d to your computer and use it in GitHub Desktop.
useLinkHandler.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Turn all HTML <a> elements into client-side router links, no special framework-specific <Link> component necessary! | |
function useLinkHandler() { | |
function handleClick(e) { | |
const link = e.target.closest('a'); | |
const isAnchorLink = link && link.href && link.href.startsWith('#'); | |
// Check if the clicked element is a valid <a> tag and meets the navigation criteria | |
if ( | |
link && | |
link instanceof HTMLAnchorElement && | |
link.href && | |
(!link.target || link.target === '_self' || link.target === '_blank') && | |
(!link.origin || link.origin === location.origin) && | |
!link.hasAttribute('download') && | |
((e.button === 0 && !e.metaKey && !e.ctrlKey && !e.altKey && !e.shiftKey) || | |
(e.key === 'Enter' && !e.shiftKey)) && | |
!e.defaultPrevented | |
) { | |
e.preventDefault(); | |
// Handle the navigation based on whether it's an anchor link or a regular link | |
if (isAnchorLink) { | |
handleAnchorLink(link); | |
} else { | |
handleNavigation(link.href); | |
} | |
} | |
} | |
// Debounce the click event handler to improve performance | |
function debounce(func, delay) { | |
let timeout; | |
return function (...args) { | |
clearTimeout(timeout); | |
timeout = setTimeout(() => func.apply(this, args), delay); | |
}; | |
} | |
// Handle navigation for anchor links within the same page | |
function handleAnchorLink(link) { | |
const targetId = link.getAttribute('href').slice(1); | |
const targetElement = document.getElementById(targetId); | |
if (targetElement) { | |
smoothScrollTo(targetElement); | |
} | |
} | |
// Handle navigation for regular links | |
function handleNavigation(href) { | |
window.location.href = href; | |
} | |
// Smooth scroll to an element on the page | |
function smoothScrollTo(element) { | |
// Implement smooth scrolling logic here | |
// Example: window.scrollTo({ top: element.offsetTop, behavior: 'smooth' }); | |
} | |
useEffect(() => { | |
const debouncedHandleClick = debounce(handleClick, 300); | |
// Attach the click and keydown event listeners to the document | |
document.addEventListener('click', debouncedHandleClick, { capture: true }); | |
document.addEventListener('keydown', debouncedHandleClick, { capture: true }); | |
// Cleanup by removing the event listeners | |
return () => { | |
document.removeEventListener('click', debouncedHandleClick, { capture: true }); | |
document.removeEventListener('keydown', debouncedHandleClick, { capture: true }); | |
}; | |
}, []); | |
return null; | |
} | |
export default useLinkHandler; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment