import getFocusable from '../dom/get-focusable';
/**
* @module focusLoop
* @description Loop through focusable els inside a container. Bound to a keydown listener usually.
*
* @since 1.0.0
*
* @param {KeyboardEvent} e The event object from the keyDown/keyUp listener using this.
* @param {HTMLElement} trigger The trigger that the user clicked to launch the element using focus loop.
* @param {HTMLElement} container The container the trigger focused.
* @param {Function} onEscape The function to call if the esc key is used.
*
* @requires getFocusable
*
* @return {void}
*
* @example
* import { focusLoop } from "@gravityforms/utils";
*
* const exampleContainer = document.getElementById( 'example-container' );
* const exampleTrigger = document.getElementById( 'example-trigger' );
*
* closeExample = () => {
* // close the container.
* }
*
* handleKeyEvents = ( e ) =>
* focusLoop(
* e,
* exampleTrigger,
* exampleContainer,
* closeExample
* );
*
* bindEvents = () => {
* exampleContainer.addEventListener( 'keydown', handleKeyEvents );
* };
*
* bindEvents();
*
*/
export default function focusLoop(
e = {},
trigger = null,
container = null,
onEscape = () => {}
) {
if ( ! container || ! trigger ) {
console.error(
'You need to pass a container and trigger node to focusLoop.'
);
return;
}
// esc key, refocus the settings trigger in the editor preview for the active field
if ( e.keyCode === 27 ) {
trigger.focus();
onEscape();
return;
}
// not tab key, exit
if ( e.keyCode !== 9 ) {
return;
}
// get visible focusable items
const focusable = getFocusable( container );
// store first and last visible item
const firstFocusableEl = focusable[ 0 ];
const lastFocusableEl = focusable[ focusable.length - 1 ];
// shiftkey was involved, we're going backwards, focus last el if we are leaving first
if ( e.shiftKey ) {
/* shift + tab */
if ( document.activeElement === firstFocusableEl ) {
lastFocusableEl.focus();
e.preventDefault();
}
// regular tabbing direction, bring us back to first el at reaching end
} /* tab */ else if ( document.activeElement === lastFocusableEl ) {
firstFocusableEl.focus();
e.preventDefault();
}
}