123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155 |
- /**
- * @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.olivero.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' || e.key === 'Esc') {
- // 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.addEventListener('transitionend', handleFocus, {
- once: true,
- });
- if (visibility === true) {
- Drupal.olivero.closeAllSubNav();
- searchWideWrapper.classList.add('is-active');
- document.addEventListener('click', watchForClickOut, { capture: true });
- document.addEventListener('focusout', watchForFocusOut, {
- capture: true,
- });
- document.addEventListener('keyup', watchForEscapeOut, { capture: true });
- } else {
- searchWideWrapper.classList.remove('is-active');
- document.removeEventListener('click', watchForClickOut, {
- capture: true,
- });
- document.removeEventListener('focusout', watchForFocusOut, {
- capture: true,
- });
- document.removeEventListener('keyup', watchForEscapeOut, {
- capture: true,
- });
- }
- }
- Drupal.olivero.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);
|