feat: Improve dropdown menu handling and visibility for OTS-specific menus
This commit is contained in:
@@ -315,79 +315,63 @@
|
||||
group.classList.toggle('is-open', !isOpen);
|
||||
target.setAttribute('aria-expanded', (!isOpen).toString());
|
||||
submenu.style.display = isOpen ? 'none' : 'block';
|
||||
}, true);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize dropdown menus
|
||||
*/
|
||||
function initDropdowns() {
|
||||
const dropdowns = document.querySelectorAll('.dropdown');
|
||||
|
||||
dropdowns.forEach(dropdown => {
|
||||
const button = dropdown.querySelector('.dropdown-menu');
|
||||
|
||||
if (!button) return;
|
||||
|
||||
const menu = dropdown.querySelector('.dropdown-menu');
|
||||
|
||||
// Toggle menu on button click
|
||||
dropdown.addEventListener('click', function(e) {
|
||||
if (e.target.closest('.user-btn') || e.target.closest('[aria-label="User menu"]') || e.target.closest('#navbarUserMenu')) {
|
||||
e.preventDefault();
|
||||
const nowActive = !dropdown.classList.contains('active');
|
||||
dropdown.classList.toggle('active');
|
||||
// Only handle the user-menu dropdown.
|
||||
// Let Bootstrap handle topbar nav dropdowns (Schedule, Design, etc.) natively
|
||||
// so that links like Dayparting navigate normally.
|
||||
const userDropdown = document.querySelector('#navbarUserMenu') && document.querySelector('#navbarUserMenu').closest('.dropdown');
|
||||
if (!userDropdown) return;
|
||||
|
||||
// If the dropdown has a menu, float it out of any overflowed container
|
||||
try {
|
||||
const ddMenu = dropdown.querySelector('.dropdown-menu');
|
||||
if (ddMenu) {
|
||||
if (nowActive) {
|
||||
floatMenu(ddMenu, dropdown);
|
||||
} else {
|
||||
unfloatMenu(ddMenu);
|
||||
}
|
||||
}
|
||||
} catch (err) { /* ignore */ }
|
||||
const userMenu = userDropdown.querySelector('.dropdown-menu');
|
||||
if (!userMenu) return;
|
||||
|
||||
// If this dropdown contains the user menu, compute placement to avoid going off-screen
|
||||
const menu = dropdown.querySelector('.dropdown-menu.ots-user-menu');
|
||||
const trigger = dropdown.querySelector('#navbarUserMenu');
|
||||
if (menu && trigger) {
|
||||
// Reset any previous placement classes
|
||||
menu.classList.remove('dropdown-menu-left');
|
||||
menu.classList.remove('dropdown-menu-right');
|
||||
userDropdown.addEventListener('click', function(e) {
|
||||
if (e.target.closest('.user-btn') || e.target.closest('[aria-label="User menu"]') || e.target.closest('#navbarUserMenu')) {
|
||||
e.preventDefault();
|
||||
const nowActive = !userDropdown.classList.contains('active');
|
||||
userDropdown.classList.toggle('active');
|
||||
|
||||
// Use getBoundingClientRect for accurate placement
|
||||
const trigRect = trigger.getBoundingClientRect();
|
||||
// Ensure menu is in DOM and has an offsetWidth
|
||||
const menuWidth = menu.offsetWidth || 220; // fallback estimate
|
||||
// Float / unfloat the user menu
|
||||
try {
|
||||
if (nowActive) {
|
||||
floatMenu(userMenu, userDropdown);
|
||||
} else {
|
||||
unfloatMenu(userMenu);
|
||||
}
|
||||
} catch (err) { /* ignore */ }
|
||||
|
||||
const spaceRight = window.innerWidth - trigRect.right;
|
||||
const spaceLeft = trigRect.left;
|
||||
|
||||
// Prefer opening to the right where possible, otherwise open to the left
|
||||
if (spaceRight < menuWidth && spaceLeft > menuWidth) {
|
||||
// not enough space on the right, open to left
|
||||
menu.classList.add('dropdown-menu-left');
|
||||
} else {
|
||||
// default to right-aligned
|
||||
menu.classList.add('dropdown-menu-right');
|
||||
}
|
||||
// Compute placement to avoid going off-screen
|
||||
const trigger = userDropdown.querySelector('#navbarUserMenu');
|
||||
if (trigger) {
|
||||
userMenu.classList.remove('dropdown-menu-left', 'dropdown-menu-right');
|
||||
const trigRect = trigger.getBoundingClientRect();
|
||||
const menuWidth = userMenu.offsetWidth || 220;
|
||||
const spaceRight = window.innerWidth - trigRect.right;
|
||||
const spaceLeft = trigRect.left;
|
||||
if (spaceRight < menuWidth && spaceLeft > menuWidth) {
|
||||
userMenu.classList.add('dropdown-menu-left');
|
||||
} else {
|
||||
userMenu.classList.add('dropdown-menu-right');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Close menu when clicking outside
|
||||
document.addEventListener('click', function(e) {
|
||||
if (!dropdown.contains(e.target)) {
|
||||
const hasActive = dropdown.classList.contains('active');
|
||||
dropdown.classList.remove('active');
|
||||
if (hasActive) {
|
||||
try { const ddMenu = dropdown.querySelector('.dropdown-menu'); if (ddMenu) unfloatMenu(ddMenu); } catch (err) {}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Close user menu when clicking outside
|
||||
document.addEventListener('click', function(e) {
|
||||
if (!userDropdown.contains(e.target) && !userMenu.contains(e.target)) {
|
||||
const hadActive = userDropdown.classList.contains('active');
|
||||
userDropdown.classList.remove('active');
|
||||
if (hadActive) {
|
||||
try { unfloatMenu(userMenu); } catch (err) {}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user