test
This commit is contained in:
parent
094929a2db
commit
fb78962fc1
|
|
@ -135,4 +135,151 @@ html {
|
|||
@keyframes fadeIn {
|
||||
from { opacity: 0; }
|
||||
to { opacity: 1; }
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
MENU UNIQUE OUVERT - STYLES AMÉLIORÉS
|
||||
============================================ */
|
||||
|
||||
/* Animation pour les sous-menus */
|
||||
@keyframes slideDown {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-10px);
|
||||
max-height: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
max-height: 500px;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slideUp {
|
||||
from {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
max-height: 500px;
|
||||
}
|
||||
to {
|
||||
opacity: 0;
|
||||
transform: translateY(-10px);
|
||||
max-height: 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Styles pour les sous-menus */
|
||||
.nav-submenu {
|
||||
max-height: 0;
|
||||
overflow: hidden;
|
||||
display: none;
|
||||
transition: max-height 0.3s ease, opacity 0.3s ease;
|
||||
}
|
||||
|
||||
.nav-submenu.show {
|
||||
display: block;
|
||||
animation: slideDown 0.3s ease forwards;
|
||||
}
|
||||
|
||||
.nav-submenu:not(.show) {
|
||||
animation: slideUp 0.3s ease forwards;
|
||||
}
|
||||
|
||||
/* Indicateur visuel pour le menu actif */
|
||||
.nav-link.active {
|
||||
background-color: rgba(255, 255, 255, 0.15) !important;
|
||||
color: white !important;
|
||||
font-weight: 500 !important;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.nav-link.active::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 3px;
|
||||
height: 60%;
|
||||
background-color: white;
|
||||
border-radius: 0 2px 2px 0;
|
||||
}
|
||||
|
||||
/* Flèche du menu */
|
||||
.nav-arrow {
|
||||
transition: transform 0.3s ease;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.nav-link[aria-expanded="true"] .nav-arrow {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
.nav-link[aria-expanded="false"] .nav-arrow {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
/* Hover amélioré */
|
||||
.nav-link:hover:not(.active) {
|
||||
background-color: rgba(255, 255, 255, 0.08) !important;
|
||||
}
|
||||
|
||||
/* Transition fluide pour les sous-menus actifs */
|
||||
.nav-submenu[data-parent-id].show {
|
||||
background-color: rgba(0, 0, 0, 0.1);
|
||||
border-radius: 6px;
|
||||
margin: 4px 16px 4px 16px;
|
||||
}
|
||||
|
||||
/* Élément actif dans le sous-menu */
|
||||
.nav-submenu .nav-link.active {
|
||||
background-color: rgba(255, 255, 255, 0.2) !important;
|
||||
font-weight: 600 !important;
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
RESPONSIVE - MENU MOBILE
|
||||
============================================ */
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.nav-submenu.show {
|
||||
animation: slideDown 0.2s ease forwards;
|
||||
}
|
||||
|
||||
.nav-submenu:not(.show) {
|
||||
animation: slideUp 0.2s ease forwards;
|
||||
}
|
||||
|
||||
/* Masquer les sous-menus par défaut sur mobile */
|
||||
.app-sidebar:not(.mobile-open) .nav-submenu {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.app-sidebar.mobile-open .nav-submenu.show {
|
||||
display: block !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
ACCESSIBILITÉ AMÉLIORÉE
|
||||
============================================ */
|
||||
|
||||
.nav-link:focus {
|
||||
outline: 2px solid rgba(255, 255, 255, 0.6);
|
||||
outline-offset: -2px;
|
||||
}
|
||||
|
||||
.nav-submenu .nav-link:focus {
|
||||
outline-offset: -4px;
|
||||
}
|
||||
|
||||
/* Focus visible pour navigation clavier */
|
||||
.nav-link:focus-visible {
|
||||
outline: 3px solid rgba(255, 255, 255, 0.8);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
/* Indicateur pour menu ouvert au clavier */
|
||||
.nav-link[aria-expanded="true"]:focus {
|
||||
background-color: rgba(255, 255, 255, 0.2) !important;
|
||||
}
|
||||
|
|
@ -81,60 +81,85 @@ class UXManager {
|
|||
}
|
||||
}
|
||||
|
||||
// Navigation Manager - Gestion des menus
|
||||
// Navigation Manager - Gestion des menus (VERSION CORRIGÉE)
|
||||
class NavigationManager {
|
||||
constructor() {
|
||||
this.currentOpenMenu = null;
|
||||
this.activeMenuId = null; // Menu actif basé sur la page courante
|
||||
}
|
||||
|
||||
init() {
|
||||
this.setupActiveMenu();
|
||||
this.setupMenuBehavior();
|
||||
this.setupKeyboardNavigation();
|
||||
this.setupActiveMenu();
|
||||
}
|
||||
|
||||
setupActiveMenu() {
|
||||
// Déterminer le menu actif basé sur la page courante
|
||||
const activeParentId = window.appConfig?.activeParentId;
|
||||
const activeLink = window.appConfig?.activeLink;
|
||||
|
||||
console.log('[Navigation] Page active:', activeLink, 'Parent ID:', activeParentId);
|
||||
|
||||
if (activeParentId !== null && activeParentId !== '') {
|
||||
this.activeMenuId = `submenu${activeParentId}`;
|
||||
console.log('[Navigation] Menu actif détecté:', this.activeMenuId);
|
||||
|
||||
// Ouvrir seulement le menu actif
|
||||
setTimeout(() => {
|
||||
this.openMenu(this.activeMenuId);
|
||||
this.currentOpenMenu = this.activeMenuId;
|
||||
}, 100);
|
||||
} else {
|
||||
console.log('[Navigation] Aucun menu actif détecté');
|
||||
// Fermer tous les menus par défaut
|
||||
this.closeAllMenus();
|
||||
}
|
||||
}
|
||||
|
||||
setupMenuBehavior() {
|
||||
// Désactiver le comportement Bootstrap par défaut
|
||||
// Pour chaque lien de menu avec sous-menu
|
||||
document.querySelectorAll('.nav-link[data-bs-toggle="collapse"]').forEach(link => {
|
||||
link.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
const targetId = link.getAttribute('href').substring(1);
|
||||
this.toggleMenu(targetId, e);
|
||||
console.log('[Navigation] Clic sur menu:', targetId);
|
||||
|
||||
// Si on clique sur le menu déjà ouvert, on le ferme
|
||||
if (this.currentOpenMenu === targetId) {
|
||||
this.closeMenu(targetId);
|
||||
this.currentOpenMenu = null;
|
||||
} else {
|
||||
// Fermer le menu précédent si différent
|
||||
if (this.currentOpenMenu && this.currentOpenMenu !== targetId) {
|
||||
this.closeMenu(this.currentOpenMenu);
|
||||
}
|
||||
|
||||
// Ouvrir le nouveau menu
|
||||
this.openMenu(targetId);
|
||||
this.currentOpenMenu = targetId;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Fermer le menu en cliquant ailleurs
|
||||
// Fermer les menus en cliquant ailleurs
|
||||
document.addEventListener('click', (e) => {
|
||||
if (!e.target.closest('.app-sidebar')) {
|
||||
this.closeAllMenus();
|
||||
// Ne pas fermer le menu actif s'il correspond à la page courante
|
||||
if (this.currentOpenMenu !== this.activeMenuId) {
|
||||
this.closeAllMenus();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
toggleMenu(menuId, event) {
|
||||
if (event) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
const menu = document.getElementById(menuId);
|
||||
const link = document.querySelector(`[href="#${menuId}"]`);
|
||||
|
||||
if (!menu || !link) return;
|
||||
|
||||
// Si ce menu est déjà ouvert, le fermer
|
||||
if (this.currentOpenMenu === menuId) {
|
||||
this.closeMenu(menuId);
|
||||
this.currentOpenMenu = null;
|
||||
} else {
|
||||
// Fermer le menu actuellement ouvert
|
||||
if (this.currentOpenMenu) {
|
||||
this.closeMenu(this.currentOpenMenu);
|
||||
}
|
||||
|
||||
// Ouvrir le nouveau menu
|
||||
this.openMenu(menuId);
|
||||
this.currentOpenMenu = menuId;
|
||||
}
|
||||
// Empêcher la fermeture du menu actif
|
||||
document.querySelectorAll('.nav-submenu').forEach(menu => {
|
||||
menu.addEventListener('click', (e) => {
|
||||
e.stopPropagation();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
openMenu(menuId) {
|
||||
|
|
@ -142,10 +167,29 @@ class NavigationManager {
|
|||
const link = document.querySelector(`[href="#${menuId}"]`);
|
||||
|
||||
if (menu && link) {
|
||||
// Retirer 'show' de tous les autres menus
|
||||
document.querySelectorAll('.nav-submenu.show').forEach(otherMenu => {
|
||||
if (otherMenu.id !== menuId) {
|
||||
otherMenu.classList.remove('show');
|
||||
const otherLink = document.querySelector(`[href="#${otherMenu.id}"]`);
|
||||
if (otherLink) {
|
||||
otherLink.setAttribute('aria-expanded', 'false');
|
||||
otherLink.classList.remove('active');
|
||||
const arrow = otherLink.querySelector('.nav-arrow');
|
||||
if (arrow) arrow.style.transform = 'rotate(0deg)';
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Ouvrir le menu sélectionné
|
||||
menu.classList.add('show');
|
||||
link.classList.add('active');
|
||||
link.setAttribute('aria-expanded', 'true');
|
||||
link.querySelector('.nav-arrow').style.transform = 'rotate(90deg)';
|
||||
link.classList.add('active');
|
||||
|
||||
const arrow = link.querySelector('.nav-arrow');
|
||||
if (arrow) arrow.style.transform = 'rotate(90deg)';
|
||||
|
||||
console.log('[Navigation] Menu ouvert:', menuId);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -154,19 +198,35 @@ class NavigationManager {
|
|||
const link = document.querySelector(`[href="#${menuId}"]`);
|
||||
|
||||
if (menu && link) {
|
||||
// Ne pas fermer le menu actif si c'est celui de la page courante
|
||||
if (menuId === this.activeMenuId) {
|
||||
console.log('[Navigation] Menu actif, ne pas fermer:', menuId);
|
||||
return;
|
||||
}
|
||||
|
||||
menu.classList.remove('show');
|
||||
link.classList.remove('active');
|
||||
link.setAttribute('aria-expanded', 'false');
|
||||
link.querySelector('.nav-arrow').style.transform = 'rotate(0deg)';
|
||||
link.classList.remove('active');
|
||||
|
||||
const arrow = link.querySelector('.nav-arrow');
|
||||
if (arrow) arrow.style.transform = 'rotate(0deg)';
|
||||
|
||||
console.log('[Navigation] Menu fermé:', menuId);
|
||||
}
|
||||
}
|
||||
|
||||
closeAllMenus() {
|
||||
// Ne fermer que les menus qui ne sont pas actifs
|
||||
document.querySelectorAll('.nav-submenu.show').forEach(menu => {
|
||||
const menuId = menu.id;
|
||||
this.closeMenu(menuId);
|
||||
if (menu.id !== this.activeMenuId) {
|
||||
this.closeMenu(menu.id);
|
||||
}
|
||||
});
|
||||
this.currentOpenMenu = null;
|
||||
|
||||
// Si aucun menu actif, réinitialiser
|
||||
if (!this.activeMenuId) {
|
||||
this.currentOpenMenu = null;
|
||||
}
|
||||
}
|
||||
|
||||
setupKeyboardNavigation() {
|
||||
|
|
@ -197,16 +257,15 @@ class NavigationManager {
|
|||
}
|
||||
}
|
||||
|
||||
setupActiveMenu() {
|
||||
// Ouvrir automatiquement le menu actif au chargement
|
||||
const activeParentId = window.appConfig.activeParentId;
|
||||
if (activeParentId !== null && activeParentId !== '') {
|
||||
const menuId = `submenu${activeParentId}`;
|
||||
setTimeout(() => {
|
||||
this.openMenu(menuId);
|
||||
this.currentOpenMenu = menuId;
|
||||
}, 100);
|
||||
}
|
||||
// Méthode publique pour forcer l'ouverture d'un menu
|
||||
openMenuById(menuId) {
|
||||
this.openMenu(menuId);
|
||||
this.currentOpenMenu = menuId;
|
||||
}
|
||||
|
||||
// Méthode publique pour forcer la fermeture
|
||||
closeAllExceptActive() {
|
||||
this.closeAllMenus();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
144
Vue/gabarit.php
144
Vue/gabarit.php
|
|
@ -294,8 +294,8 @@ foreach ($menus as $key0 => $menuParent) {
|
|||
}
|
||||
}
|
||||
|
||||
// Déterminer si le menu doit être ouvert
|
||||
$shouldBeOpen = $isParentActive || $hasActiveChild;
|
||||
// Déterminer si le menu DOIT être ouvert (seulement si actif)
|
||||
$shouldBeOpen = ($isParentActive || $hasActiveChild) && $activeParentId !== null;
|
||||
?>
|
||||
<div class="nav-item">
|
||||
<?php if (sizeof($menuChildrenLevelOne) > 0): ?>
|
||||
|
|
@ -304,14 +304,16 @@ foreach ($menus as $key0 => $menuParent) {
|
|||
data-bs-toggle="collapse"
|
||||
onclick="appNavigation.toggleMenu('submenu<?= $key0 ?>', event)"
|
||||
aria-expanded="<?= $shouldBeOpen ? 'true' : 'false' ?>"
|
||||
aria-controls="submenu<?= $key0 ?>">
|
||||
aria-controls="submenu<?= $key0 ?>"
|
||||
data-menu-id="submenu<?= $key0 ?>">
|
||||
<i class="<?= $menuParent['icone'] ?>"></i>
|
||||
<span class="nav-text"><?= $menuParent['libeleMenu'] ?></span>
|
||||
<i class="nav-arrow bi bi-chevron-right"></i>
|
||||
</a>
|
||||
|
||||
<div class="nav-submenu collapse <?= $shouldBeOpen ? 'show' : '' ?>"
|
||||
id="submenu<?= $key0 ?>">
|
||||
id="submenu<?= $key0 ?>"
|
||||
data-parent-id="submenu<?= $key0 ?>">
|
||||
<?php foreach ($menuChildrenLevelOne as $key1 => $menuChild):
|
||||
$childActive = (explode('/', $menuChild['lienMenu'])[0] ?? '') == $activeLink;
|
||||
?>
|
||||
|
|
@ -553,4 +555,136 @@ foreach ($menus as $key0 => $menuParent) {
|
|||
<!-- Service Worker Registration -->
|
||||
<script src="/Js/sw-register.js?ver=2025.12.22.00"></script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
<script>
|
||||
// Test du système de menus
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
console.group('=== TEST SYSTÈME DE MENUS ===');
|
||||
|
||||
// Vérifier l'état initial
|
||||
const activeMenuId = window.appConfig?.activeParentId !== null ?
|
||||
`submenu${window.appConfig.activeParentId}` : null;
|
||||
|
||||
console.log('Menu actif configuré:', activeMenuId);
|
||||
console.log('Page active:', window.appConfig?.activeLink);
|
||||
|
||||
// Compter les menus ouverts
|
||||
const openMenus = document.querySelectorAll('.nav-submenu.show');
|
||||
console.log('Menus initialement ouverts:', openMenus.length);
|
||||
|
||||
openMenus.forEach(menu => {
|
||||
console.log(' -', menu.id);
|
||||
});
|
||||
|
||||
// Vérifier que seul le menu actif est ouvert
|
||||
if (openMenus.length > 1) {
|
||||
console.warn('⚠️ Plusieurs menus sont ouverts!');
|
||||
console.warn('Seul le menu', activeMenuId, 'devrait être ouvert.');
|
||||
|
||||
// Corriger automatiquement
|
||||
if (activeMenuId && window.appNavigation) {
|
||||
console.log('Correction automatique en cours...');
|
||||
window.appNavigation.closeAllExceptActive();
|
||||
}
|
||||
} else if (openMenus.length === 1 && openMenus[0].id === activeMenuId) {
|
||||
console.log('✅ Parfait! Seul le menu actif est ouvert.');
|
||||
} else if (openMenus.length === 0 && !activeMenuId) {
|
||||
console.log('✅ Aucun menu ouvert - Comportement attendu.');
|
||||
}
|
||||
|
||||
// Exposer des fonctions de test
|
||||
window.menuTest = {
|
||||
openAllMenus: function() {
|
||||
document.querySelectorAll('.nav-submenu').forEach(menu => {
|
||||
menu.classList.add('show');
|
||||
const link = document.querySelector(`[href="#${menu.id}"]`);
|
||||
if (link) link.setAttribute('aria-expanded', 'true');
|
||||
});
|
||||
console.log('Tous les menus ouverts (test)');
|
||||
},
|
||||
|
||||
closeAllMenus: function() {
|
||||
document.querySelectorAll('.nav-submenu').forEach(menu => {
|
||||
menu.classList.remove('show');
|
||||
const link = document.querySelector(`[href="#${menu.id}"]`);
|
||||
if (link) link.setAttribute('aria-expanded', 'false');
|
||||
});
|
||||
console.log('Tous les menus fermés (test)');
|
||||
},
|
||||
|
||||
showMenuState: function() {
|
||||
const menus = document.querySelectorAll('.nav-submenu');
|
||||
console.log('État des menus:');
|
||||
menus.forEach(menu => {
|
||||
const isOpen = menu.classList.contains('show');
|
||||
const link = document.querySelector(`[href="#${menu.id}"]`);
|
||||
const ariaExpanded = link ? link.getAttribute('aria-expanded') : 'N/A';
|
||||
console.log(` ${menu.id}: ${isOpen ? 'OUVERT' : 'FERMÉ'} (aria-expanded: ${ariaExpanded})`);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
console.groupEnd();
|
||||
|
||||
// Ajouter un indicateur visuel de débogage
|
||||
if (window.appConfig?.debugMode) {
|
||||
const debugIndicator = document.createElement('div');
|
||||
debugIndicator.style.cssText = `
|
||||
position: fixed;
|
||||
bottom: 10px;
|
||||
left: 10px;
|
||||
background: rgba(0,0,0,0.8);
|
||||
color: #0f0;
|
||||
padding: 5px 10px;
|
||||
border-radius: 4px;
|
||||
font-family: monospace;
|
||||
font-size: 12px;
|
||||
z-index: 9999;
|
||||
pointer-events: none;
|
||||
`;
|
||||
debugIndicator.textContent = `Menu: ${activeMenuId || 'Aucun'}`;
|
||||
document.body.appendChild(debugIndicator);
|
||||
}
|
||||
});
|
||||
|
||||
// Fonction globale pour tester depuis la console
|
||||
function testMenuSystem() {
|
||||
console.log('=== TEST MANUEL DU SYSTÈME DE MENUS ===');
|
||||
|
||||
if (!window.appNavigation) {
|
||||
console.error('appNavigation non disponible');
|
||||
return;
|
||||
}
|
||||
|
||||
// Test 1: Fermer tous les menus
|
||||
console.log('Test 1: Fermeture de tous les menus...');
|
||||
window.appNavigation.closeAllMenus();
|
||||
|
||||
// Test 2: Ouvrir le menu actif
|
||||
setTimeout(() => {
|
||||
const activeId = window.appConfig?.activeParentId !== null ?
|
||||
`submenu${window.appConfig.activeParentId}` : null;
|
||||
|
||||
if (activeId) {
|
||||
console.log('Test 2: Ouverture du menu actif:', activeId);
|
||||
window.appNavigation.openMenuById(activeId);
|
||||
}
|
||||
|
||||
// Test 3: Vérification finale
|
||||
setTimeout(() => {
|
||||
const openMenus = document.querySelectorAll('.nav-submenu.show').length;
|
||||
console.log('Test 3: Résultat -', openMenus, 'menu(s) ouvert(s)');
|
||||
|
||||
if (openMenus === 1 || (openMenus === 0 && !activeId)) {
|
||||
console.log('✅ Système de menus fonctionne correctement!');
|
||||
} else {
|
||||
console.warn('⚠️ Problème détecté avec le système de menus');
|
||||
}
|
||||
}, 500);
|
||||
}, 500);
|
||||
}
|
||||
|
||||
// Exposer la fonction de test
|
||||
window.testMenuSystem = testMenuSystem;
|
||||
</script>
|
||||
Loading…
Reference in New Issue
Block a user