1/** 2 * Hub des articles â filtrage de ce qui est déjà dans la page. 3 * Même principe que le glossaire : le serveur rend tout, le script masque. 4 */ 5(function () { 6 'use strict'; 7 8 var $$ = function (s, r) { return Array.prototype.slice.call((r || document).querySelectorAll(s)); }; 9 var cartes = $$('[data-hub-liste] .know-art-card'); 10 if (!cartes.length) { return; } 11 12 var pilules = $$('.know-cat-btn'); 13 var compte = document.querySelector('[data-hub-compte]'); 14 var vide = document.querySelector('[data-hub-vide]'); 15 var champ = document.querySelector('[data-hub-recherche] input'); 16 var effacer = document.querySelector('[data-hub-effacer]'); 17 var actif = ''; 18 var requete = []; 19 20 /* « cedule » doit trouver « cédule », et « Cédule » aussi : tout passe 21 par la même normalisation â minuscules, accents décomposés puis 22 retirés â des deux côtés de la comparaison. */ 23 function normaliser(t) { 24 return (t || '').toLowerCase().normalize('NFD').replace(/[\u0300-\u036f]/g, '').replace(/[^a-z0-9 ]+/g, ' ').replace(/\s+/g, ' ').trim(); 25 } 26 27 function appliquer() { 28 var n = 0; 29 cartes.forEach(function (c) { 30 /* Un article peut porter plusieurs thèmes : data-hub-int est 31 une liste de slugs séparés par des espaces. */ 32 var siens = (c.getAttribute('data-hub-int') || '').split(/\s+/); 33 var ok = !actif || siens.indexOf(actif) !== -1; 34 if (ok && requete.length) { 35 var index = c.getAttribute('data-hub-mot') || ''; 36 /* Chaque mot tapé doit se trouver quelque part dans l'index : 37 « ibgi remploi » réduit, il n'élargit pas. */ 38 ok = requete.every(function (mot) { return index.indexOf(mot) !== -1; }); 39 } 40 c.hidden = !ok; 41 if (ok) { n++; } 42 }); 43 if (compte) { 44 compte.textContent = (actif || requete.length) 45 ? n + (n > 1 ? ' articles' : ' article') 46 : ''; 47 } 48 if (vide) { vide.hidden = n !== 0; vide.textContent = n === 0 ? 'Aucun article dans cette sélection.' : ''; } 49 if (effacer) { effacer.hidden = !requete.length; } 50 } 51 52 function chercher(texte, pousserUrl) {
53 requete = normaliser(texte).split(' ').filter(Boolean); 54 appliquer(); 55 if (pousserUrl && window.history && history.replaceState) { 56 var u = new URL(location.href); 57 if (requete.length) { u.searchParams.set('q', texte.trim()); } else { u.searchParams.delete('q'); } 58 history.replaceState(history.state, '', u); 59 } 60 } 61 62 if (champ) { 63 var minuterie = null; 64 champ.addEventListener('input', function () { 65 clearTimeout(minuterie); 66 minuterie = setTimeout(function () { chercher(champ.value, true); }, 120); 67 }); 68 } 69 if (effacer && champ) { 70 effacer.addEventListener('click', function () { champ.value = ''; chercher('', true); champ.focus(); }); 71 } 72 73 function choisir(cible, pousser) { 74 actif = cible; 75 pilules.forEach(function (o) { 76 var on = (o.getAttribute('data-hub-int') || '') === actif; 77 o.classList.toggle('active', on); 78 if (on) { o.setAttribute('aria-current', 'page'); } else { o.removeAttribute('aria-current'); } 79 }); 80 appliquer(); 81 if (pousser && window.history && history.pushState) { 82 /* L'adresse suit le filtre â sans écraser une recherche en cours : 83 thème et mots-clés se combinent, l'URL porte les deux. */ 84 var u = new URL(location.href); 85 if (actif) { u.searchParams.set('theme', actif); } else { u.searchParams.delete('theme'); } 86 history.pushState({ hub: actif }, '', u); 87 } 88 } 89
90 pilules.forEach(function (b) { 91 b.addEventListener('click', function (e) { 92 /* Les pilules sont de vrais liens vers l'archive du thème, pour 93 que Google les suive. Ici on intercepte : filtrer sur place 94 vaut mieux qu'un rechargement. Un clic milieu, ctrl ou cmd 95 garde le comportement natif â on n'enlève pas à l'utilisateur 96 le droit d'ouvrir dans un onglet. */ 97 if (e.metaKey || e.ctrlKey || e.shiftKey || e.button !== 0) { return; } 98 e.preventDefault(); 99 var cible = b.getAttribute('data-hub-int') || ''; 100 choisir(actif === cible ? '' : cible, true); 101 var grille = document.getElementById('tous-les-articles'); 102 if (grille && cible) { grille.scrollIntoView({ behavior: 'smooth', block: 'start' }); } 103 }); 104 }); 105 106 window.addEventListener('popstate', function () { 107 choisir(new URLSearchParams(location.search).get('theme') || '', false); 108 }); 109 110 // Arrivée directe sur ?theme=⦠ou ?q=⦠â partage, signet, futur assistant. 111 var params = new URLSearchParams(location.search); 112 var voulu = params.get('theme'); 113 if (voulu) { choisir(voulu, false); } 114 var q = params.get('q'); 115 if (q && champ) { champ.value = q; chercher(q, false); } 116})();
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.