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
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);
|