1document.addEventListener('DOMContentLoaded', function(){ 2 document.querySelectorAll('[data-kdm]').forEach(function(nav){ 3 const drawer = nav.querySelector('.kdmM__drawer'); 4 const track = nav.querySelector('.kdmM__track'); 5 const toggle = nav.querySelector('[data-toggle]'); 6 if(!drawer || !track || !toggle) return; 7 8 // Breakpoint : vide => burger toujours 9 const bpRaw = (window.KDM && typeof KDM.breakpoint === 'string') ? KDM.breakpoint.trim() : ''; 10 const bp = bpRaw === '' ? null : Number(bpRaw); 11 12 function isMobile(){ 13 if(bp === null || Number.isNaN(bp)) return true; 14 return window.matchMedia('(max-width:'+bp+'px)').matches; 15 } 16 17 // ===== Drilldown ===== 18 const panels = Array.from(nav.querySelectorAll('.kdmM__panel')); 19 const byName = new Map(panels.map(p => [p.dataset.panel, p])); 20 21 function getActiveName(){ 22 const p = panels.find(x => x.dataset.active === "1"); 23 return p ? p.dataset.panel : "root"; 24 } 25 26 function setActive(name){ 27 const p = byName.get(name) || byName.get('root'); 28 const path = new Set(); 29 let cur = p; 30 while(cur && !path.has(cur)){ 31 path.add(cur); 32 cur = byName.get(cur.dataset.parent); 33 } 34 35 // Le rail contient uniquement la branche choisie : un panneau par niveau. 36 // Sinon, toutes les rubriques d'une même profondeur montrent le même panneau. 37 panels.forEach(panel => { 38 delete panel.dataset.active; 39 panel.hidden = !path.has(panel); 40 panel.inert = panel !== p; 41 }); 42 if(p) p.dataset.active = "1"; 43 44 const depth = Math.max(0, path.size - 1); 45 track.style.transform = 'translateX(' + (-100 * depth) + '%)'; 46 } 47 48 function onKey(e){ 49 if(e.key === 'Escape') closeDrawer(); 50 } 51 52 function openDrawer(){ 53 drawer.hidden = false; 54 toggle.setAttribute('aria-expanded','true'); 55 setActive('root'); 56 document.addEventListener('keydown', onKey); 57 } 58 59 function closeDrawer(){ 60 drawer.hidden = true; 61 toggle.setAttribute('aria-expanded','false'); 62 document.removeEventListener('keydown', onKey); 63 } 64 65 toggle.addEventListener('click', function(){ 66 if(!isMobile()) return; 67 drawer.hidden ? openDrawer() : closeDrawer(); 68 }); 69 70 nav.addEventListener('click', function(e){ 71 if(!isMobile()) return; 72 73 // Fermer (croix) 74 const closeBtn = e.target.closest('[data-close]'); 75 if(closeBtn){ 76 e.preventDefault(); 77 closeDrawer(); 78 return; 79 } 80 81 // Lien "#" => ouvrir sous-menu 82 const link = e.target.closest('.kdmM__link'); 83 if(link){ 84 const href = (link.getAttribute('href') || '').trim(); 85 if(href === '' || href === '#'){ 86 const item = link.closest('.kdmM__item'); 87 if(item){ 88 const nextBtn = item.querySelector('[data-open]'); 89 if(nextBtn){ 90 e.preventDefault(); 91 const target = nextBtn.getAttribute('data-open'); 92 if(byName.has(target)) setActive(target); 93 return; 94 } 95 } 96 } 97 } 98 99 // Ouvrir sous-menu (flèche) 100 const openBtn = e.target.closest('[data-open]'); 101 if(openBtn){ 102 e.preventDefault(); 103 const target = openBtn.getAttribute('data-open'); 104 if(byName.has(target)) setActive(target); 105 return; 106 } 107 108 // Retour 109 const backBtn = e.target.closest('[data-back]'); 110 if(backBtn){ 111 e.preventDefault(); 112 const active = byName.get(getActiveName()); 113 const parent = active ? active.dataset.parent : 'root'; 114 setActive(parent || 'root'); 115 return; 116 } 117 }); 118 119 window.addEventListener('resize', function(){ 120 if(!isMobile() && !drawer.hidden) closeDrawer(); 121 }); 122 }); 123});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.