Skip to content

Commit 88776c2

Browse files
authored
Merge pull request #30 from MEOM/fix/sub-sub-menu-closing
Allow only one sub sub menu to be open at once.
2 parents aa1a26c + b796d8b commit 88776c2

File tree

12 files changed

+4875
-9760
lines changed

12 files changed

+4875
-9760
lines changed

changelog.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
# Changelog
2+
## Version 1.1.0 released April 3, 2023
3+
- Fixed: show only one sub sub menu open at once.
4+
- Updated NPM packages.
25
## Version 1.0.5 released May 7, 2022
36
- Added `:hover` to sub menus in hover demo.
47
- Updated NPM packages.

demo/dist/navigation-multiple.js

Lines changed: 79 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,23 @@
55
return;
66
}
77
elem.classList.add(animation);
8-
elem.addEventListener("animationend", function endAnimation() {
9-
elem.classList.remove(animation);
10-
if (hide) {
11-
elem.classList.remove(hide);
12-
}
13-
elem.removeEventListener("animationend", endAnimation, false);
14-
}, false);
8+
elem.addEventListener(
9+
"animationend",
10+
function endAnimation() {
11+
elem.classList.remove(animation);
12+
if (hide) {
13+
elem.classList.remove(hide);
14+
}
15+
elem.removeEventListener("animationend", endAnimation, false);
16+
},
17+
false
18+
);
1519
}
1620
function updateAria(el, aria) {
17-
if (typeof el === "undefined" || 0 >= aria.length) {
21+
if ("undefined" === typeof el || 0 >= aria.length) {
1822
return;
1923
}
20-
const hiddenEl = el.getAttribute(`aria-${aria}`) === "true" ? "false" : "true";
24+
const hiddenEl = "true" === el.getAttribute(`aria-${aria}`) ? "false" : "true";
2125
el.setAttribute(`aria-${aria}`, hiddenEl);
2226
}
2327
var TAB_KEY = 9;
@@ -51,8 +55,10 @@
5155
this._handleCloseNav = this.handleCloseNav.bind(this);
5256
this._handleCloseSubNav = this.handleCloseSubNav.bind(this);
5357
this._closeAllSubMenus = this.closeAllSubMenus.bind(this);
58+
this._closeAllSubSubMenus = this.closeAllSubSubMenus.bind(this);
5459
this._setSubMenu = this.setSubMenu.bind(this);
5560
this._closeAllSubMenuToggles = this.closeAllSubMenuToggles.bind(this);
61+
this._closeAllSubSubMenuToggles = this.closeAllSubSubMenuToggles.bind(this);
5662
this._handleDocClick = this.handleDocClick.bind(this);
5763
this._handleFocus = this.handleFocus.bind(this);
5864
const settings = { ...defaults, ...options };
@@ -61,13 +67,15 @@
6167
this.settings = settings;
6268
this.navOpened = false;
6369
this.$subNavs = this.$element.querySelectorAll(this.settings.subNavAnchors);
64-
this.$subSubNavs = this.$element.querySelectorAll(this.settings.subSubNavAnchors);
70+
this.$subSubNavs = this.$element.querySelectorAll(
71+
this.settings.subSubNavAnchors
72+
);
6573
this.create();
6674
}
6775
Navigation.prototype.create = function() {
6876
this.$toggle.setAttribute("aria-expanded", "false");
6977
this.$element.setAttribute("data-meom-nav", "navigation");
70-
this.$subNavs.forEach(function(subNav, index) {
78+
this.$subNavs.forEach(function(subNav) {
7179
if (this.settings.action === "click") {
7280
subNav.setAttribute("hidden", "");
7381
}
@@ -138,14 +146,24 @@
138146
Navigation.prototype.handleSubNav = function(event) {
139147
const target = event.target;
140148
const closestSubButton = target.closest('[data-meom-nav="sub-toggle"]');
141-
const closestSubSubButton = target.closest('[data-meom-nav="sub-sub-toggle"]');
149+
const closestSubSubButton = target.closest(
150+
'[data-meom-nav="sub-sub-toggle"]'
151+
);
142152
if (!closestSubButton && !closestSubSubButton) {
143153
return this;
144154
}
145-
if (!target.nextElementSibling.classList.contains(this.settings.toggleSubNavClassValue) && !target.matches('[data-meom-nav="sub-sub-toggle"]')) {
155+
if (!target.nextElementSibling.classList.contains(
156+
this.settings.toggleSubNavClassValue
157+
) && !target.matches('[data-meom-nav="sub-sub-toggle"]')) {
146158
this._closeAllSubMenus();
147159
this._closeAllSubMenuToggles();
148160
}
161+
if (!target.nextElementSibling.classList.contains(
162+
this.settings.toggleSubNavClassValue
163+
) && target.matches('[data-meom-nav="sub-sub-toggle"]')) {
164+
this._closeAllSubSubMenus();
165+
this._closeAllSubSubMenuToggles();
166+
}
149167
updateAria(target, "expanded");
150168
if (target.nextElementSibling) {
151169
this._setSubMenu(target.nextElementSibling, event);
@@ -159,7 +177,9 @@
159177
return this;
160178
};
161179
Navigation.prototype.handleCloseSubNav = function(event) {
162-
const openSubMenu = document.querySelector(`${this.settings.subNavClass}.${this.settings.toggleSubNavClassValue}`);
180+
const openSubMenu = document.querySelector(
181+
`${this.settings.subNavClass}.${this.settings.toggleSubNavClassValue}`
182+
);
163183
if (openSubMenu) {
164184
const focusableElements = openSubMenu.querySelectorAll([
165185
"a[href]",
@@ -181,13 +201,17 @@
181201
}
182202
}
183203
if (ESCAPE_KEY === event.keyCode) {
184-
if (event.target.matches('[data-meom-nav="sub-toggle"][aria-expanded="true"]')) {
204+
if (event.target.matches(
205+
'[data-meom-nav="sub-toggle"][aria-expanded="true"]'
206+
)) {
185207
this._handleSubNav(event);
186208
this._closeAllSubMenus();
187209
this._closeAllSubMenuToggles();
188210
return this;
189211
}
190-
const parentSubMenu = event.target.closest(`${this.settings.subNavClass}.${this.settings.toggleSubNavClassValue}`);
212+
const parentSubMenu = event.target.closest(
213+
`${this.settings.subNavClass}.${this.settings.toggleSubNavClassValue}`
214+
);
191215
if (parentSubMenu) {
192216
const subMenuToggle = parentSubMenu.previousElementSibling;
193217
if (subMenuToggle) {
@@ -230,12 +254,23 @@
230254
return this;
231255
};
232256
Navigation.prototype.closeAllSubMenus = function() {
233-
const openSubMenus = document.querySelectorAll(`${this.settings.subNavClass}.${this.settings.toggleSubNavClassValue}`);
257+
const openSubMenus = document.querySelectorAll(
258+
`${this.settings.subNavClass}.${this.settings.toggleSubNavClassValue}`
259+
);
234260
openSubMenus.forEach(function(openSubMenu) {
235261
this._setSubMenu(openSubMenu);
236262
}, this);
237263
return this;
238264
};
265+
Navigation.prototype.closeAllSubSubMenus = function() {
266+
const openSubSubMenus = document.querySelectorAll(
267+
`${this.settings.subNavClass} ${this.settings.subNavClass}.${this.settings.toggleSubNavClassValue}`
268+
);
269+
openSubSubMenus.forEach(function(openSubSubMenu) {
270+
this._setSubMenu(openSubSubMenu);
271+
}, this);
272+
return this;
273+
};
239274
Navigation.prototype.setSubMenu = function(submenu, event) {
240275
if (!submenu) {
241276
return this;
@@ -246,22 +281,45 @@
246281
animate(submenu, this.settings.animateSubNavClass);
247282
}
248283
if (this.settings.onOpenSubNav && typeof this.settings.onOpenSubNav === "function") {
249-
this.settings.onOpenSubNav(this.$element, this.$toggle, submenu, event);
284+
this.settings.onOpenSubNav(
285+
this.$element,
286+
this.$toggle,
287+
submenu,
288+
event
289+
);
250290
}
251291
} else {
252292
submenu.classList.remove(this.settings.toggleSubNavClassValue);
253293
if (this.settings.onCloseSubNav && typeof this.settings.onCloseSubNav === "function") {
254-
this.settings.onCloseSubNav(this.$element, this.$toggle, submenu, event);
294+
this.settings.onCloseSubNav(
295+
this.$element,
296+
this.$toggle,
297+
submenu,
298+
event
299+
);
255300
}
256301
}
257302
return this;
258303
};
259304
Navigation.prototype.closeAllSubMenuToggles = function() {
260-
const openSubMenuToggles = document.querySelectorAll('[data-meom-nav="sub-toggle"][aria-expanded="true"]');
305+
const openSubMenuToggles = document.querySelectorAll(
306+
'[data-meom-nav="sub-toggle"][aria-expanded="true"]'
307+
);
261308
openSubMenuToggles.forEach(function(openSubMenuToggle) {
262309
updateAria(openSubMenuToggle, "expanded");
263310
});
264-
const openSubSubMenuToggles = document.querySelectorAll('[data-meom-nav="sub-sub-toggle"][aria-expanded="true"]');
311+
const openSubSubMenuToggles = document.querySelectorAll(
312+
'[data-meom-nav="sub-sub-toggle"][aria-expanded="true"]'
313+
);
314+
openSubSubMenuToggles.forEach(function(openSubSubMenuToggle) {
315+
updateAria(openSubSubMenuToggle, "expanded");
316+
});
317+
return this;
318+
};
319+
Navigation.prototype.closeAllSubSubMenuToggles = function() {
320+
const openSubSubMenuToggles = document.querySelectorAll(
321+
'[data-meom-nav="sub-sub-toggle"][aria-expanded="true"]'
322+
);
265323
openSubSubMenuToggles.forEach(function(openSubSubMenuToggle) {
266324
updateAria(openSubSubMenuToggle, "expanded");
267325
});

demo/dist/navigation.js

Lines changed: 79 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,23 @@
55
return;
66
}
77
elem.classList.add(animation);
8-
elem.addEventListener("animationend", function endAnimation() {
9-
elem.classList.remove(animation);
10-
if (hide) {
11-
elem.classList.remove(hide);
12-
}
13-
elem.removeEventListener("animationend", endAnimation, false);
14-
}, false);
8+
elem.addEventListener(
9+
"animationend",
10+
function endAnimation() {
11+
elem.classList.remove(animation);
12+
if (hide) {
13+
elem.classList.remove(hide);
14+
}
15+
elem.removeEventListener("animationend", endAnimation, false);
16+
},
17+
false
18+
);
1519
}
1620
function updateAria(el, aria) {
17-
if (typeof el === "undefined" || 0 >= aria.length) {
21+
if ("undefined" === typeof el || 0 >= aria.length) {
1822
return;
1923
}
20-
const hiddenEl = el.getAttribute(`aria-${aria}`) === "true" ? "false" : "true";
24+
const hiddenEl = "true" === el.getAttribute(`aria-${aria}`) ? "false" : "true";
2125
el.setAttribute(`aria-${aria}`, hiddenEl);
2226
}
2327
var TAB_KEY = 9;
@@ -51,8 +55,10 @@
5155
this._handleCloseNav = this.handleCloseNav.bind(this);
5256
this._handleCloseSubNav = this.handleCloseSubNav.bind(this);
5357
this._closeAllSubMenus = this.closeAllSubMenus.bind(this);
58+
this._closeAllSubSubMenus = this.closeAllSubSubMenus.bind(this);
5459
this._setSubMenu = this.setSubMenu.bind(this);
5560
this._closeAllSubMenuToggles = this.closeAllSubMenuToggles.bind(this);
61+
this._closeAllSubSubMenuToggles = this.closeAllSubSubMenuToggles.bind(this);
5662
this._handleDocClick = this.handleDocClick.bind(this);
5763
this._handleFocus = this.handleFocus.bind(this);
5864
const settings = { ...defaults, ...options };
@@ -61,13 +67,15 @@
6167
this.settings = settings;
6268
this.navOpened = false;
6369
this.$subNavs = this.$element.querySelectorAll(this.settings.subNavAnchors);
64-
this.$subSubNavs = this.$element.querySelectorAll(this.settings.subSubNavAnchors);
70+
this.$subSubNavs = this.$element.querySelectorAll(
71+
this.settings.subSubNavAnchors
72+
);
6573
this.create();
6674
}
6775
Navigation.prototype.create = function() {
6876
this.$toggle.setAttribute("aria-expanded", "false");
6977
this.$element.setAttribute("data-meom-nav", "navigation");
70-
this.$subNavs.forEach(function(subNav, index) {
78+
this.$subNavs.forEach(function(subNav) {
7179
if (this.settings.action === "click") {
7280
subNav.setAttribute("hidden", "");
7381
}
@@ -138,14 +146,24 @@
138146
Navigation.prototype.handleSubNav = function(event) {
139147
const target = event.target;
140148
const closestSubButton = target.closest('[data-meom-nav="sub-toggle"]');
141-
const closestSubSubButton = target.closest('[data-meom-nav="sub-sub-toggle"]');
149+
const closestSubSubButton = target.closest(
150+
'[data-meom-nav="sub-sub-toggle"]'
151+
);
142152
if (!closestSubButton && !closestSubSubButton) {
143153
return this;
144154
}
145-
if (!target.nextElementSibling.classList.contains(this.settings.toggleSubNavClassValue) && !target.matches('[data-meom-nav="sub-sub-toggle"]')) {
155+
if (!target.nextElementSibling.classList.contains(
156+
this.settings.toggleSubNavClassValue
157+
) && !target.matches('[data-meom-nav="sub-sub-toggle"]')) {
146158
this._closeAllSubMenus();
147159
this._closeAllSubMenuToggles();
148160
}
161+
if (!target.nextElementSibling.classList.contains(
162+
this.settings.toggleSubNavClassValue
163+
) && target.matches('[data-meom-nav="sub-sub-toggle"]')) {
164+
this._closeAllSubSubMenus();
165+
this._closeAllSubSubMenuToggles();
166+
}
149167
updateAria(target, "expanded");
150168
if (target.nextElementSibling) {
151169
this._setSubMenu(target.nextElementSibling, event);
@@ -159,7 +177,9 @@
159177
return this;
160178
};
161179
Navigation.prototype.handleCloseSubNav = function(event) {
162-
const openSubMenu = document.querySelector(`${this.settings.subNavClass}.${this.settings.toggleSubNavClassValue}`);
180+
const openSubMenu = document.querySelector(
181+
`${this.settings.subNavClass}.${this.settings.toggleSubNavClassValue}`
182+
);
163183
if (openSubMenu) {
164184
const focusableElements = openSubMenu.querySelectorAll([
165185
"a[href]",
@@ -181,13 +201,17 @@
181201
}
182202
}
183203
if (ESCAPE_KEY === event.keyCode) {
184-
if (event.target.matches('[data-meom-nav="sub-toggle"][aria-expanded="true"]')) {
204+
if (event.target.matches(
205+
'[data-meom-nav="sub-toggle"][aria-expanded="true"]'
206+
)) {
185207
this._handleSubNav(event);
186208
this._closeAllSubMenus();
187209
this._closeAllSubMenuToggles();
188210
return this;
189211
}
190-
const parentSubMenu = event.target.closest(`${this.settings.subNavClass}.${this.settings.toggleSubNavClassValue}`);
212+
const parentSubMenu = event.target.closest(
213+
`${this.settings.subNavClass}.${this.settings.toggleSubNavClassValue}`
214+
);
191215
if (parentSubMenu) {
192216
const subMenuToggle = parentSubMenu.previousElementSibling;
193217
if (subMenuToggle) {
@@ -230,12 +254,23 @@
230254
return this;
231255
};
232256
Navigation.prototype.closeAllSubMenus = function() {
233-
const openSubMenus = document.querySelectorAll(`${this.settings.subNavClass}.${this.settings.toggleSubNavClassValue}`);
257+
const openSubMenus = document.querySelectorAll(
258+
`${this.settings.subNavClass}.${this.settings.toggleSubNavClassValue}`
259+
);
234260
openSubMenus.forEach(function(openSubMenu) {
235261
this._setSubMenu(openSubMenu);
236262
}, this);
237263
return this;
238264
};
265+
Navigation.prototype.closeAllSubSubMenus = function() {
266+
const openSubSubMenus = document.querySelectorAll(
267+
`${this.settings.subNavClass} ${this.settings.subNavClass}.${this.settings.toggleSubNavClassValue}`
268+
);
269+
openSubSubMenus.forEach(function(openSubSubMenu) {
270+
this._setSubMenu(openSubSubMenu);
271+
}, this);
272+
return this;
273+
};
239274
Navigation.prototype.setSubMenu = function(submenu, event) {
240275
if (!submenu) {
241276
return this;
@@ -246,22 +281,45 @@
246281
animate(submenu, this.settings.animateSubNavClass);
247282
}
248283
if (this.settings.onOpenSubNav && typeof this.settings.onOpenSubNav === "function") {
249-
this.settings.onOpenSubNav(this.$element, this.$toggle, submenu, event);
284+
this.settings.onOpenSubNav(
285+
this.$element,
286+
this.$toggle,
287+
submenu,
288+
event
289+
);
250290
}
251291
} else {
252292
submenu.classList.remove(this.settings.toggleSubNavClassValue);
253293
if (this.settings.onCloseSubNav && typeof this.settings.onCloseSubNav === "function") {
254-
this.settings.onCloseSubNav(this.$element, this.$toggle, submenu, event);
294+
this.settings.onCloseSubNav(
295+
this.$element,
296+
this.$toggle,
297+
submenu,
298+
event
299+
);
255300
}
256301
}
257302
return this;
258303
};
259304
Navigation.prototype.closeAllSubMenuToggles = function() {
260-
const openSubMenuToggles = document.querySelectorAll('[data-meom-nav="sub-toggle"][aria-expanded="true"]');
305+
const openSubMenuToggles = document.querySelectorAll(
306+
'[data-meom-nav="sub-toggle"][aria-expanded="true"]'
307+
);
261308
openSubMenuToggles.forEach(function(openSubMenuToggle) {
262309
updateAria(openSubMenuToggle, "expanded");
263310
});
264-
const openSubSubMenuToggles = document.querySelectorAll('[data-meom-nav="sub-sub-toggle"][aria-expanded="true"]');
311+
const openSubSubMenuToggles = document.querySelectorAll(
312+
'[data-meom-nav="sub-sub-toggle"][aria-expanded="true"]'
313+
);
314+
openSubSubMenuToggles.forEach(function(openSubSubMenuToggle) {
315+
updateAria(openSubSubMenuToggle, "expanded");
316+
});
317+
return this;
318+
};
319+
Navigation.prototype.closeAllSubSubMenuToggles = function() {
320+
const openSubSubMenuToggles = document.querySelectorAll(
321+
'[data-meom-nav="sub-sub-toggle"][aria-expanded="true"]'
322+
);
265323
openSubSubMenuToggles.forEach(function(openSubSubMenuToggle) {
266324
updateAria(openSubSubMenuToggle, "expanded");
267325
});

0 commit comments

Comments
 (0)