hooks_use-hijack-wp-menu.js
import { React } from '@gravityforms/libraries';
const { useEffect } = React;
/**
* @function addCurrentToMenuItem
* @description Add the current class and attributes to a menu item.
*
* @since 4.0.2
*
* @param {HTMLElement} item The menu item to add the current class and attributes to.
*/
const addCurrentToMenuItem = ( item ) => {
item.classList.add( 'current' );
const itemLink = item.querySelector( 'a' );
itemLink.classList.add( 'current' );
itemLink.setAttribute( 'aria-current', 'page' );
};
/**
* @function removeCurrentFromMenuItem
* @description Remove the current class and attributes from a menu item.
*
* @since 4.0.2
*
* @param {HTMLElement} item The menu item to remove the current class and attributes from.
*/
const removeCurrentFromMenuItem = ( item ) => {
item.classList.remove( 'current' );
const itemLink = item.querySelector( 'a' );
itemLink.classList.remove( 'current' );
itemLink.removeAttribute( 'aria-current' );
};
/**
* @module useHijackWpMenu
* @description Hijacks the click event on the menu.
*
* @since 4.0.2
*
* @param {string} menuId The ID of the menu to hijack.
* @param {Function} routeHandler The function to handle the routing.
* @param {object} options The options for the hook.
*/
const useHijackWpMenu = (
menuId = '',
routeHandler = () => {},
options = {
updateCurrent: true,
},
) => {
const menu = document.getElementById( menuId );
/**
* @function updateCurrentMenuItem
* @description Update the current menu item.
*
* @since 4.0.2
*
* @param {HTMLElement} link The link to update the current menu item.
*/
const updateCurrentMenuItem = ( link ) => {
const menuItems = menu.querySelectorAll( 'li:not(.wp-submenu-head)' );
const href = link.getAttribute( 'href' );
menuItems.forEach( removeCurrentFromMenuItem );
if ( link.classList.contains( 'menu-top' ) ) {
// Link is a top-level menu item, update classes and aria attributes.
menuItems.forEach( ( item ) => {
if ( item.querySelector( 'a' )?.getAttribute( 'href' ) !== href ) {
return;
}
addCurrentToMenuItem( item );
} );
} else {
// Link is a submenu item, update classes and aria attributes.
addCurrentToMenuItem( link.parentElement );
}
};
useEffect( () => {
if ( ! menu ) {
return;
}
/**
* @function hijackMenuClick
* @description Hijacks the click event on the menu.
*
* @since 4.0.2
*
* @param {Event} event The click event.
*/
const hijackMenuClick = ( event ) => {
event.preventDefault();
const link = event.currentTarget;
const href = link.getAttribute( 'href' );
if ( options.updateCurrent ) {
updateCurrentMenuItem( link );
}
const linkSearchParams = new URLSearchParams( href.split( '?' )[ 1 ] );
routeHandler( linkSearchParams );
};
const menuLinks = menu.querySelectorAll( 'a' );
menuLinks.forEach( ( link ) => {
link.addEventListener( 'click', hijackMenuClick );
} );
return () => {
menuLinks.forEach( ( link ) => {
link.removeEventListener( 'click', hijackMenuClick );
} );
};
}, [ menuId, routeHandler ] );
return {
updateCurrentMenuItem,
};
};
export default useHijackWpMenu;