From f017cacebe5e7abe7bc381c430d3fea75f91ab92 Mon Sep 17 00:00:00 2001 From: Kevin Veen-Birkenbach Date: Tue, 14 Jan 2025 17:34:30 +0100 Subject: [PATCH] Optimized logic in which direction menus open --- app/static/js/navigation.js | 84 +++++++++++++++++++++++-- app/templates/moduls/navigation.html.j2 | 5 +- 2 files changed, 81 insertions(+), 8 deletions(-) diff --git a/app/static/js/navigation.js b/app/static/js/navigation.js index 4569e03..055af5e 100644 --- a/app/static/js/navigation.js +++ b/app/static/js/navigation.js @@ -1,5 +1,6 @@ document.addEventListener('DOMContentLoaded', () => { - const menuItems = document.querySelectorAll('.nav-item.dropdown, .dropdown-submenu'); + const menuItems = document.querySelectorAll('.nav-item.dropdown'); + const subMenuItems = document.querySelectorAll('.dropdown-submenu'); menuItems.forEach(item => { let timeout; @@ -7,7 +8,7 @@ document.addEventListener('DOMContentLoaded', () => { // Öffnen beim Hovern item.addEventListener('mouseenter', () => { clearTimeout(timeout); - openMenu(item); + openMenu(item, true); }); // Verzögertes Schließen beim Verlassen @@ -21,20 +22,46 @@ document.addEventListener('DOMContentLoaded', () => { if (item.classList.contains('open')) { closeMenu(item); } else { - openMenu(item); + openMenu(item, true); + } + }); + }); + + subMenuItems.forEach(item => { + let timeout; + + // Öffnen beim Hovern + item.addEventListener('mouseenter', () => { + clearTimeout(timeout); + openMenu(item, false); + }); + + // Verzögertes Schließen beim Verlassen + item.addEventListener('mouseleave', () => { + timeout = setTimeout(() => closeMenu(item), 500); + }); + + // Offen lassen beim Klicken + item.addEventListener('click', (e) => { + e.stopPropagation(); // Verhindert das Schließen von Menüs bei Klick + if (item.classList.contains('open')) { + closeMenu(item); + } else { + openMenu(item, false); } }); }); // Globale Klick-Listener, um Menüs zu schließen, wenn außerhalb geklickt wird document.addEventListener('click', () => { - menuItems.forEach(item => closeMenu(item)); + [...menuItems, ...subMenuItems].forEach(item => closeMenu(item)); }); - function openMenu(item) { + function openMenu(item, isTopLevel) { item.classList.add('open'); const submenu = item.querySelector('.dropdown-menu'); if (submenu) { + adjustMenuPosition(submenu, item, isTopLevel); submenu.style.display = 'block'; submenu.style.opacity = '1'; submenu.style.visibility = 'visible'; @@ -50,4 +77,49 @@ document.addEventListener('DOMContentLoaded', () => { submenu.style.visibility = 'hidden'; } } -}); + + function adjustMenuPosition(submenu, parent, isTopLevel) { + const rect = submenu.getBoundingClientRect(); + const parentRect = parent.getBoundingClientRect(); + + // Platzberechnung + const spaceAbove = parentRect.top; + const spaceBelow = window.innerHeight - parentRect.bottom; + const spaceLeft = parentRect.left; + const spaceRight = window.innerWidth - parentRect.right; + + // Standardpositionierung + submenu.style.top = ''; + submenu.style.bottom = ''; + submenu.style.left = ''; + submenu.style.right = ''; + + if (isTopLevel) { + // Top-Level-Menüs öffnen nur nach oben oder unten + if (spaceBelow < rect.height && spaceAbove > rect.height) { + submenu.style.top = 'auto'; + submenu.style.bottom = '100%'; + } else { + submenu.style.top = '100%'; + submenu.style.bottom = 'auto'; + } + } else { + // Submenüs öffnen in die Richtung mit mehr Platz + if (spaceRight < rect.width && spaceLeft > rect.width) { + submenu.style.left = 'auto'; + submenu.style.right = '100%'; + } else { + submenu.style.left = '100%'; + submenu.style.right = 'auto'; + } + + if (spaceBelow < rect.height && spaceAbove > rect.height) { + submenu.style.top = 'auto'; + submenu.style.bottom = '100%'; + } else { + submenu.style.top = '0'; + submenu.style.bottom = 'auto'; + } + } + } +}); \ No newline at end of file diff --git a/app/templates/moduls/navigation.html.j2 b/app/templates/moduls/navigation.html.j2 index 3e8f292..4119e2e 100644 --- a/app/templates/moduls/navigation.html.j2 +++ b/app/templates/moduls/navigation.html.j2 @@ -3,7 +3,7 @@ {% for subitem in subitems %} {% if subitem.subitems %}