clone of olivero for island lives
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

154 lines
4.5 KiB

12 months ago
/**
* @file
* Wide viewport search bar interactions.
*/
((Drupal) => {
const searchWideButtonSelector =
'[data-drupal-selector="block-search-wide-button"]';
const searchWideButton = document.querySelector(searchWideButtonSelector);
const searchWideWrapperSelector =
'[data-drupal-selector="block-search-wide-wrapper"]';
const searchWideWrapper = document.querySelector(searchWideWrapperSelector);
/**
* Determine if search is visible.
*
* @return {boolean}
* True if the search wrapper contains "is-active" class, false if not.
*/
function searchIsVisible() {
return searchWideWrapper.classList.contains('is-active');
}
Drupal.olives.searchIsVisible = searchIsVisible;
/**
* Closes search bar when a click event does not happen at an (x,y) coordinate
* that does not overlap with either the search wrapper or button.
*
* @see https://bugs.webkit.org/show_bug.cgi?id=229895
*
* @param {Event} e click event
*/
function watchForClickOut(e) {
const clickInSearchArea = e.target.matches(`
${searchWideWrapperSelector},
${searchWideWrapperSelector} *,
${searchWideButtonSelector},
${searchWideButtonSelector} *
`);
if (!clickInSearchArea && searchIsVisible()) {
// eslint-disable-next-line no-use-before-define
toggleSearchVisibility(false);
}
}
/**
* Closes search bar when focus moves to another target.
* Avoids closing search bar if event does not have related target - required for Safari.
*
* @see https://bugs.webkit.org/show_bug.cgi?id=229895
*
* @param {Event} e focusout event
*/
function watchForFocusOut(e) {
if (e.relatedTarget) {
const inSearchBar = e.relatedTarget.matches(
`${searchWideWrapperSelector}, ${searchWideWrapperSelector} *`,
);
const inSearchButton = e.relatedTarget.matches(
`${searchWideButtonSelector}, ${searchWideButtonSelector} *`,
);
if (!inSearchBar && !inSearchButton) {
// eslint-disable-next-line no-use-before-define
toggleSearchVisibility(false);
}
}
}
/**
* Closes search bar on escape keyup, if open.
*
* @param {Event} e keyup event
*/
function watchForEscapeOut(e) {
if (e.key === 'Escape') {
// eslint-disable-next-line no-use-before-define
toggleSearchVisibility(false);
}
}
/**
* Set focus for the search input element.
*/
function handleFocus() {
if (searchIsVisible()) {
searchWideWrapper.querySelector('input[type="search"]').focus();
} else if (searchWideWrapper.contains(document.activeElement)) {
// Return focus to button only if focus was inside of the search wrapper.
searchWideButton.focus();
}
}
/**
* Toggle search functionality visibility.
*
* @param {boolean} visibility
* True if we want to show the form, false if we want to hide it.
*/
function toggleSearchVisibility(visibility) {
searchWideButton.setAttribute('aria-expanded', visibility === true);
searchWideWrapper.classList.toggle('is-active', visibility === true);
searchWideWrapper.addEventListener('transitionend', handleFocus, {
once: true,
});
if (visibility === true) {
Drupal.olives.closeAllSubNav();
document.addEventListener('click', watchForClickOut, { capture: true });
document.addEventListener('focusout', watchForFocusOut, {
capture: true,
});
document.addEventListener('keyup', watchForEscapeOut, { capture: true });
} else {
document.removeEventListener('click', watchForClickOut, {
capture: true,
});
document.removeEventListener('focusout', watchForFocusOut, {
capture: true,
});
document.removeEventListener('keyup', watchForEscapeOut, {
capture: true,
});
}
}
Drupal.olives.toggleSearchVisibility = toggleSearchVisibility;
/**
* Initializes the search wide button.
*
* @type {Drupal~behavior}
*
* @prop {Drupal~behaviorAttach} attach
* Adds aria-expanded attribute to the search wide button.
*/
Drupal.behaviors.searchWide = {
attach(context) {
const searchWideButtonEl = once(
'search-wide',
searchWideButtonSelector,
context,
).shift();
if (searchWideButtonEl) {
searchWideButtonEl.setAttribute('aria-expanded', searchIsVisible());
searchWideButtonEl.addEventListener('click', () => {
toggleSearchVisibility(!searchIsVisible());
});
}
},
};
})(Drupal);