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.
153 lines
4.5 KiB
153 lines
4.5 KiB
/** |
|
* @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);
|
|
|