Skip to content

Commit 66a9b79

Browse files
Fix links not clickable on 3th level (#16671)
### What does it do? Hopefully it fixes #16667. ### How to test 1. Try clicking on all the links in the manager menu. Especially in the 3rd level. 2. Try navigating through the Manager Menu using the Tab key on your keyboard and clicking on the menu items using the Enter key. 3. Make sure there are no new errors 😸. ### Related issue(s)/PR(s) #16530 #16667 --------- Co-authored-by: Jason Coward <jason@opengeek.com>
1 parent 37e1833 commit 66a9b79

File tree

10 files changed

+44
-45
lines changed

10 files changed

+44
-45
lines changed

manager/assets/modext/core/modx.layout.js

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -62,14 +62,9 @@ Ext.extend(MODx.Layout, Ext.Viewport, {
6262
,splitBarMargin: 8
6363

6464
/**
65-
* @property {Array} focusRestoreEls - Set Focus back on the last Element in array on close
65+
* @property {Object} focusRestoreEl - Set Focus back on this Element
6666
*/
67-
,focusRestoreEls: []
68-
69-
/**
70-
* @property {bool} subNavOpen - Check if Subnav is opened
71-
*/
72-
,subNavOpen: false
67+
,focusRestoreEl: []
7368

7469
/**
7570
* @property {Function} getSplitBarMargin - Utility getter for splitBarMargin
@@ -493,9 +488,9 @@ Ext.extend(MODx.Layout, Ext.Viewport, {
493488
}
494489
}
495490
});
496-
buttons[i].addEventListener('click', function (e) {
491+
buttons[i].addEventListener('click', function(e) {
497492
e.stopPropagation();
498-
el.focusRestoreEls.push(this.querySelectorAll('a')[0]);
493+
el.focusRestoreEl = this.querySelectorAll('a')[0];
499494
el.showMenu(this);
500495
});
501496
}
@@ -514,30 +509,38 @@ Ext.extend(MODx.Layout, Ext.Viewport, {
514509
submenu.classList.remove('active');
515510
} else {
516511
this.hideMenu();
512+
var isClick = false;
517513
submenu.classList.add('active');
518514
setTimeout(() => {
519-
submenu.querySelectorAll('a')[0].focus();
515+
var firstFocusEl = submenu.querySelectorAll('a')[0];
516+
if (!firstFocusEl) {
517+
return;
518+
}
519+
firstFocusEl.focus();
520520
}, 50);
521+
var menuItemClicked = (e) => {
522+
isClick = true;
523+
window.removeEventListener('click', menuItemClicked);
524+
};
521525
var focusRestore = (e) => {
522-
setTimeout(() => {
523-
if (this.subNavOpen) {
524-
return;
525-
}
526+
requestAnimationFrame(() => {
526527
if (!submenu.contains(document.activeElement)) {
527-
this.focusRestoreEls?.pop()?.focus();
528+
if (!isClick) {
529+
this.focusRestoreEl?.focus();
530+
}
528531
this.hideMenu();
529532
window.removeEventListener('focusout', focusRestore);
530533
}
531-
}, 1);
534+
});
532535
};
533536
var menuArrowKeysNavigation = (e) => {
534537
if (e.code == 'Escape') {
535538
this.hideMenu();
536-
this.focusRestoreEls[0]?.focus();
537-
this.focusRestoreEls = [];
539+
this.focusRestoreEl?.focus();
538540
window.removeEventListener('keyup', menuArrowKeysNavigation);
539541
}
540542
};
543+
window.addEventListener('click', menuItemClicked);
541544
window.addEventListener('focusout', focusRestore);
542545
window.addEventListener('keyup', menuArrowKeysNavigation);
543546
}
@@ -552,7 +555,6 @@ Ext.extend(MODx.Layout, Ext.Viewport, {
552555
,initSubPopper: function () {
553556
var buttons = document.querySelectorAll('#modx-header .sub, #modx-footer .sub');
554557
var position = window.innerWidth <= 960 ? 'bottom' : 'right';
555-
var _this = this;
556558
for (var i = 0; i < buttons.length; i++) {
557559
let popperInstance = null;
558560

@@ -595,17 +597,14 @@ Ext.extend(MODx.Layout, Ext.Viewport, {
595597
}
596598

597599
function show(button) {
598-
var menu = button.getElementsByTagName('ul')[0];
600+
var submenu = button.getElementsByTagName('ul')[0];
599601
button.classList.add('active');
600-
menu.classList.add('active');
601-
_this.focusRestoreEls.push(button.querySelectorAll('a')[0]);
602-
_this.subNavOpen = true;
603-
create(button, menu);
602+
submenu.classList.add('active');
603+
create(button, submenu);
604604
var focusRestore = (e) => {
605605
requestAnimationFrame(() => {
606-
if (!menu.contains(document.activeElement)) {
607-
_this.focusRestoreEls?.pop()?.parentNode?.nextSibling?.focus();
608-
hide(button);
606+
if (!submenu.contains(document.activeElement)) {
607+
submenu.classList.remove('active');
609608
window.removeEventListener('focusout', focusRestore);
610609
}
611610
});
@@ -623,7 +622,6 @@ Ext.extend(MODx.Layout, Ext.Viewport, {
623622
submenu.removeAttribute('style');
624623
buttons[i].classList.remove('active');
625624
}
626-
_this.subNavOpen = false;
627625
destroy();
628626
}
629627
buttons[i].addEventListener('mouseenter', function (e) {
@@ -632,7 +630,9 @@ Ext.extend(MODx.Layout, Ext.Viewport, {
632630
});
633631
buttons[i].querySelectorAll('a')[0].addEventListener('focus', function (e) {
634632
e.stopPropagation();
635-
show(this.parentNode);
633+
requestAnimationFrame(() => {
634+
show(this.parentNode);
635+
});
636636
});
637637
buttons[i].addEventListener('mouseleave', function (e) {
638638
e.stopPropagation();

manager/assets/modext/modx.jsgrps-min.js

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

manager/templates/default/css/index-min.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

manager/templates/default/css/index.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
*
3-
* Copyright (C) 2024 MODX LLC
3+
* Copyright (C) 2025 MODX LLC
44
*
55
* This file is part of MODX Revolution and was compiled using Grunt.
66
*

manager/templates/default/css/login-min.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

manager/templates/default/css/login.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
*
3-
* Copyright (C) 2024 MODX LLC
3+
* Copyright (C) 2025 MODX LLC
44
*
55
* This file is part of MODX Revolution and was compiled using Grunt.
66
*

manager/templates/default/footer.tpl

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,6 @@
11
</div>
22
<!-- #modx-content-->
3-
<div id="modx-footer">
4-
{if $_search}
5-
<div class="modx-subnav" id="modx-manager-search-icon-submenu">
6-
<div class="modx-subnav-arrow"></div>
7-
<div id="modx-manager-search" role="search"></div>
8-
</div>
9-
{/if}
10-
</div>
3+
<div id="modx-footer"></div>
114
</div>
125
<!-- #modx-container -->
136

manager/templates/default/header.tpl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,12 @@
111111
</li>
112112
{/if}
113113
</ul>
114+
{if $_search}
115+
<div class="modx-subnav" id="modx-manager-search-icon-submenu">
116+
<div class="modx-subnav-arrow"></div>
117+
<div id="modx-manager-search" role="search"></div>
118+
</div>
119+
{/if}
114120
<ul id="modx-topnav">
115121
{eval var=$navb}
116122
</ul>

setup/assets/css/installer-min.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

setup/assets/css/installer.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
*
3-
* Copyright (C) 2024 MODX LLC
3+
* Copyright (C) 2025 MODX LLC
44
*
55
* This file is part of MODX Revolution and was compiled using Grunt.
66
*

0 commit comments

Comments
 (0)