1/* Galerie d'illustrations : filtrage par rubrique + visionneuse. 2 La visionneuse charge la version 900 px via l'URL /images/<fichier> 3 (href des vignettes) â l'original reste accessible en remplaçant 4 "images" par "zoom" dans cette URL. */ 5document.addEventListener('DOMContentLoaded', () => { 6 const grid = document.querySelector('.galerie__grid'); 7 if (!grid) return; 8 9 const items = [...grid.querySelectorAll('.illu')]; 10 const filters = [...document.querySelectorAll('.filterbar .filter, .galerie .filter')]; 11 12 /* ---------- Filtres ---------- */ 13 filters.forEach(btn => btn.addEventListener('click', () => { 14 // aria-pressed suit l'état visuel : sans lui, un lecteur d'écran ne sait 15 // pas quel filtre est actif (audit agentique du 26/7). 16 filters.forEach(b => { b.classList.remove('is-active'); b.setAttribute('aria-pressed', 'false'); }); 17 btn.classList.add('is-active'); 18 btn.setAttribute('aria-pressed', 'true'); 19 const active = btn.dataset.filter; 20 items.forEach(item => { 21 const rubs = (item.dataset.rubriques || '').split(',').map(s => s.trim()); 22 item.classList.toggle('is-hidden', active !== 'tous' && !rubs.includes(active)); 23 }); 24 // Amener le début des résultats sous la barre sticky. La marge est 25 // recalculée à chaque clic : la hauteur de la barre dépen
25d du nombre 26 // de lignes de pilules (viewport). 27 const header = document.querySelector('.site-header'); 28 const bar = document.querySelector('.filterbar'); 29 grid.style.scrollMarginTop = ((header?.offsetHeight || 0) + (bar?.offsetHeight || 0) + 24) + 'px'; 30 grid.scrollIntoView({ behavior: 'smooth' }); 31 })); 32 33 /* Filtre pré-activé par l'URL (#animaux, #medicalâ¦) â cible des 301 des 34 anciennes galeries thématiques WP (une page par rubrique). */ 35 const wanted = decodeURIComponent(location.hash.slice(1)); 36 if (wanted) { 37 const btn = filters.find(b => b.dataset.filter === wanted); 38 if (btn) btn.click(); 39 } 40 41 /* ---------- Visionneuse ---------- */ 42 const box = document.getElementById('lightbox'); 43 if (!box) return; 44 const img = box.querySelector('img'); 45 const caption = box.querySelector('figcaption'); 46 let current = -1; 47 48 const visibles = () => items.filter(i => !i.classList.contains('is-hidden')); 49 50 const show = (item) => { 51 const link = item.querySelector('.illu__link'); 52 img.src = link.href; 53 img.alt = caption.textContent = link.title; 54 current = visibles().indexOf(item); 55 if (!box.open) box.showModal(); 56 }; 57 58 const step = (dir) => { 59 const list = visibles(); 60 if (!list.length) return; 61 show(list[(current + dir + list.length) % list.length]); 62 }; 63 64 items.forEach(item => item.querySelector('.illu__link').addEventListener('click', (e) => { 65 e.preventDefault(); 66 show(item); 67 })); 68 69 box.querySelector('.lightbox__close').addEventListener('click', () => box.close()); 70 box.querySelector('.lightbox__nav--prev').addEventListener('click', () => step(-1)); 71 box.querySelector('.lightbox__nav--next').addEventListener('click', () => step(1)); 72 box.addEventListener('click', (e) => { if (e.target === box) box.close(); }); 73 box.addEventListener('keydown', (e) => { 74 if (e.key === 'ArrowLeft') step(-1); 75 if (e.key === 'ArrowRight') step(1); 76 }); 77 box.addEventListener('close', () => { img.src = ''; }); 78});
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.