Unverified Commit 67e76624 authored by lauriii's avatar lauriii
Browse files

Issue #3191692 by mherchel, Gauravmahlawat, BhumikaVarshney, bnjmnm,...

Issue #3191692 by mherchel, Gauravmahlawat, BhumikaVarshney, bnjmnm, katannshaw: Have secondary menus close on blur
parent d91377b3
...@@ -6,4 +6,5 @@ node_modules/**/* ...@@ -6,4 +6,5 @@ node_modules/**/*
modules/locale/tests/locale_test.es6.js modules/locale/tests/locale_test.es6.js
!tests/Drupal/Nightwatch/**/*.js !tests/Drupal/Nightwatch/**/*.js
misc/polyfills/array.find.es6.js misc/polyfills/array.find.es6.js
misc/polyfills/element.closest.es6.js
misc/polyfills/object.assign.es6.js misc/polyfills/object.assign.es6.js
...@@ -280,6 +280,13 @@ drupal.dropbutton: ...@@ -280,6 +280,13 @@ drupal.dropbutton:
- core/drupalSettings - core/drupalSettings
- core/jquery.once - core/jquery.once
drupal.element.closest:
version: VERSION
js:
misc/polyfills/element.closest.js: { weight: -20 }
dependencies:
- core/drupal.element.matches
drupal.element.matches: drupal.element.matches:
version: VERSION version: VERSION
js: js:
......
/**
* @file
* Provides a polyfill for Element.prototype.closest().
*
* This is needed for Internet Explorer 11 and Opera Mini.
*
* This has been copied from MDN Web Docs code samples. Code samples in the MDN
* Web Docs are licensed under CC0.
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/Element/closest#polyfill
* @see https://developer.mozilla.org/en-US/docs/MDN/About#Code_samples_and_snippets
*/
if (!Element.prototype.closest) {
Element.prototype.closest = function (s) {
var el = this;
do {
if (Element.prototype.matches.call(el, s)) return el;
el = el.parentElement || el.parentNode;
} while (el !== null && el.nodeType === 1);
return null;
};
}
/**
* DO NOT EDIT THIS FILE.
* See the following change record for more information,
* https://www.drupal.org/node/2815083
* @preserve
**/
if (!Element.prototype.closest) {
Element.prototype.closest = function (s) {
var el = this;
do {
if (Element.prototype.matches.call(el, s)) return el;
el = el.parentElement || el.parentNode;
} while (el !== null && el.nodeType === 1);
return null;
};
}
\ No newline at end of file
...@@ -68,4 +68,29 @@ module.exports = { ...@@ -68,4 +68,29 @@ module.exports = {
'true', 'true',
); );
}, },
'Verify secondary navigation close on blur': (browser) => {
browser
.drupalRelativeURL('/node')
.waitForElementVisible(headerNavSelector)
.click(`[aria-controls="${linkSubMenuId}"]`)
.assert.attributeEquals(
`[aria-controls="${linkSubMenuId}"]`,
'aria-expanded',
'true',
);
browser
.execute(
// eslint-disable-next-line func-names, prefer-arrow-callback, no-shadow
function () {
document.querySelector('.site-branding__name a').focus();
},
[],
)
.pause(400)
.assert.attributeEquals(
`[aria-controls="${linkSubMenuId}"]`,
'aria-expanded',
'false',
);
},
}; };
...@@ -47,6 +47,25 @@ ...@@ -47,6 +47,25 @@
Drupal.olivero.toggleSubNav = toggleSubNav; Drupal.olivero.toggleSubNav = toggleSubNav;
/**
* Sets a timeout and closes current desktop navigation submenu if it
* does not contain the focused element.
*
* @param {object} e - event object
*/
function handleBlur(e) {
if (!Drupal.olivero.isDesktopNav()) return;
setTimeout(() => {
const menuParentItem = e.target.closest(
'.primary-nav__menu-item--has-children',
);
if (!menuParentItem.contains(document.activeElement)) {
toggleSubNav(menuParentItem, false);
}
}, 200);
}
// Add event listeners onto each sub navigation parent and button. // Add event listeners onto each sub navigation parent and button.
secondLevelNavMenus.forEach((el) => { secondLevelNavMenus.forEach((el) => {
const button = el.querySelector( const button = el.querySelector(
...@@ -96,6 +115,8 @@ ...@@ -96,6 +115,8 @@
toggleSubNav(el, false); toggleSubNav(el, false);
} }
}); });
el.addEventListener('blur', handleBlur, true);
}); });
/** /**
......
...@@ -32,6 +32,18 @@ ...@@ -32,6 +32,18 @@
} }
Drupal.olivero.toggleSubNav = toggleSubNav; Drupal.olivero.toggleSubNav = toggleSubNav;
function handleBlur(e) {
if (!Drupal.olivero.isDesktopNav()) return;
setTimeout(function () {
var menuParentItem = e.target.closest('.primary-nav__menu-item--has-children');
if (!menuParentItem.contains(document.activeElement)) {
toggleSubNav(menuParentItem, false);
}
}, 200);
}
secondLevelNavMenus.forEach(function (el) { secondLevelNavMenus.forEach(function (el) {
var button = el.querySelector('.primary-nav__button-toggle, .primary-nav__menu-link--button'); var button = el.querySelector('.primary-nav__button-toggle, .primary-nav__menu-link--button');
button.removeAttribute('aria-hidden'); button.removeAttribute('aria-hidden');
...@@ -60,6 +72,7 @@ ...@@ -60,6 +72,7 @@
toggleSubNav(el, false); toggleSubNav(el, false);
} }
}); });
el.addEventListener('blur', handleBlur, true);
}); });
function closeAllSubNav() { function closeAllSubNav() {
......
...@@ -61,6 +61,7 @@ global-styling: ...@@ -61,6 +61,7 @@ global-styling:
js/navigation.js: {} js/navigation.js: {}
js/second-level-navigation.js: {} js/second-level-navigation.js: {}
dependencies: dependencies:
- core/drupal.element.closest
- core/drupal.element.matches - core/drupal.element.matches
- core/drupal.nodelist.foreach - core/drupal.nodelist.foreach
- core/drupal - core/drupal
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment