Skip to content
Snippets Groups Projects
Unverified Commit 44a6c2a7 authored by Lauri Timmanee's avatar Lauri Timmanee
Browse files

Issue #3303112 by andy-blum, mherchel, Abhijith S, bronzehedwick: Olivero:...

Issue #3303112 by andy-blum, mherchel, Abhijith S, bronzehedwick: Olivero: When in Safari, clicking "X" when search is open does not collapse the search

(cherry picked from commit 45132e0c)
parent 9982e89c
No related branches found
No related tags found
23 merge requests!8506Draft: Issue #3456536 by ibrahim tameme,!5646Issue #3350972 by nod_: [random test failure]...,!5600Issue #3350972 by nod_: [random test failure]...,!5343Issue #3305066 by quietone, Rename RedirectLeadingSlashesSubscriber,!4350Issue #3307718: Implement xxHash for non-cryptographic use-cases,!3603#ISSUE 3346218 Add a different message on edit comment,!3555Issue #2473873: Views entity operations lack cacheability support, resulting in incorrect dropbuttons,!3494Issue #3327018 by Spokje, longwave, xjm, mondrake: Update PHPStan to 1.9.3 and...,!3410Issue #3340128: UserLoginForm::submitForm has some dead code,!3389Issue #3325184 by Spokje, andypost, xjm, smustgrave: $this->configFactory is...,!3381Issue #3332363: Refactor Claro's menus-and-lists stylesheet,!3307Issue #3326193: CKEditor 5 can grow past the viewport when there is a lot of content,!3236Issue #3332419: Refactor Claro's messages stylesheet,!3231Draft: Issue #3049525 by longwave, fougere, larowlan, kim.pepper, AaronBauman, Wim...,!3212Issue #3294003: Refactor Claro's entity-meta stylesheet,!3194Issue #3330981: Fix PHPStan L1 error "Relying on entity queries to check access by default is deprecated...",!3143Issue #3313342: [PHP 8.1] Deprecated function: strpos(): Passing null to parameter #1 LayoutBuilderUiCacheContext.php on line 28,!3024Issue #3307509: Empty option for views bulk form,!2972Issue #1845004: Replace custom password hashing library with PHP 5.5 password_hash(),!2719Issue #3110137: Remove Classy from core.,!2437Issue #3238257 by hooroomoo, Wim Leers: Fragment link pointing to <textarea>...,!2296Issue #3100732: Allow specifying `meta` data on JSON:API objects,!1626Issue #3256642: Make life better for database drivers that extend another database driver
/**
* @file
* Customization of search.
* Wide viewport search bar interactions.
*/
((Drupal) => {
const searchWideButton = document.querySelector(
'[data-drupal-selector="block-search-wide-button"]',
);
const searchWideWrapper = document.querySelector(
'[data-drupal-selector="block-search-wide-wrapper"]',
);
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.
......@@ -22,6 +22,63 @@
}
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') {
// eslint-disable-next-line no-use-before-define
toggleSearchVisibility(false);
}
}
/**
* Set focus for the search input element.
*/
......@@ -49,23 +106,29 @@
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;
document.addEventListener('keyup', (e) => {
if (e.key === 'Escape') {
toggleSearchVisibility(false);
}
});
searchWideButton.addEventListener('click', () => {
toggleSearchVisibility(!searchIsVisible());
});
/**
* Initializes the search wide button.
*
......@@ -76,26 +139,17 @@
*/
Drupal.behaviors.searchWide = {
attach(context) {
const searchWideButton = once(
const searchWideButtonEl = once(
'search-wide',
'[data-drupal-selector="block-search-wide-button"]',
searchWideButtonSelector,
context,
).shift();
if (searchWideButton) {
searchWideButton.setAttribute('aria-expanded', 'false');
if (searchWideButtonEl) {
searchWideButtonEl.setAttribute('aria-expanded', searchIsVisible());
searchWideButtonEl.addEventListener('click', () => {
toggleSearchVisibility(!searchIsVisible());
});
}
},
};
/**
* Close the wide search container if focus moves from either the container
* or its toggle button.
*/
document
.querySelector('[data-drupal-selector="search-block-form-2"]')
.addEventListener('focusout', (e) => {
if (!e.currentTarget.contains(e.relatedTarget)) {
toggleSearchVisibility(false);
}
});
})(Drupal);
......@@ -6,8 +6,10 @@
**/
(Drupal => {
const searchWideButton = document.querySelector('[data-drupal-selector="block-search-wide-button"]');
const searchWideWrapper = document.querySelector('[data-drupal-selector="block-search-wide-wrapper"]');
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);
function searchIsVisible() {
return searchWideWrapper.classList.contains('is-active');
......@@ -15,6 +17,36 @@
Drupal.olivero.searchIsVisible = searchIsVisible;
function watchForClickOut(e) {
const clickInSearchArea = e.target.matches(`
${searchWideWrapperSelector},
${searchWideWrapperSelector} *,
${searchWideButtonSelector},
${searchWideButtonSelector} *
`);
if (!clickInSearchArea && searchIsVisible()) {
toggleSearchVisibility(false);
}
}
function watchForFocusOut(e) {
if (e.relatedTarget) {
const inSearchBar = e.relatedTarget.matches(`${searchWideWrapperSelector}, ${searchWideWrapperSelector} *`);
const inSearchButton = e.relatedTarget.matches(`${searchWideButtonSelector}, ${searchWideButtonSelector} *`);
if (!inSearchBar && !inSearchButton) {
toggleSearchVisibility(false);
}
}
}
function watchForEscapeOut(e) {
if (e.key === 'Escape') {
toggleSearchVisibility(false);
}
}
function handleFocus() {
if (searchIsVisible()) {
searchWideWrapper.querySelector('input[type="search"]').focus();
......@@ -32,33 +64,41 @@
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;
document.addEventListener('keyup', e => {
if (e.key === 'Escape') {
toggleSearchVisibility(false);
}
});
searchWideButton.addEventListener('click', () => {
toggleSearchVisibility(!searchIsVisible());
});
Drupal.behaviors.searchWide = {
attach(context) {
const searchWideButton = once('search-wide', '[data-drupal-selector="block-search-wide-button"]', context).shift();
const searchWideButtonEl = once('search-wide', searchWideButtonSelector, context).shift();
if (searchWideButton) {
searchWideButton.setAttribute('aria-expanded', 'false');
if (searchWideButtonEl) {
searchWideButtonEl.setAttribute('aria-expanded', searchIsVisible());
searchWideButtonEl.addEventListener('click', () => {
toggleSearchVisibility(!searchIsVisible());
});
}
}
};
document.querySelector('[data-drupal-selector="search-block-form-2"]').addEventListener('focusout', e => {
if (!e.currentTarget.contains(e.relatedTarget)) {
toggleSearchVisibility(false);
}
});
})(Drupal);
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment