97 lines
3.7 KiB
JavaScript
97 lines
3.7 KiB
JavaScript
/* ==================================================================
|
|
Outils communs aux cours de traitement de texte (3e TQ, 4e TQ)
|
|
------------------------------------------------------------------
|
|
Trois briques réutilisables d'un module à l'autre :
|
|
quiz(element, questions) questionnaire à choix, correction immédiate
|
|
chasse(...) chasse aux fautes dans un texte
|
|
suivreSommaire() surligne l'entrée courante du sommaire
|
|
|
|
Chaque page de module charge ce fichier, puis déclare ses propres
|
|
données dans un <script> qui lui est propre.
|
|
================================================================== */
|
|
|
|
"use strict";
|
|
|
|
/* ---------- questionnaire à choix multiples ----------
|
|
questions : [{q: énoncé, r: [réponses], b: index de la bonne, e: explication}] */
|
|
function quiz(el, questions){
|
|
if (!el) return;
|
|
el.innerHTML = questions.map(function(q, i){
|
|
return '<div class="q" data-i="' + i + '"><p>' + (i + 1) + '. ' + q.q + '</p>' +
|
|
q.r.map(function(r, j){
|
|
return '<label><input type="radio" name="' + el.id + '-' + i + '" value="' + j + '">' + r + '</label>';
|
|
}).join('') +
|
|
'<div class="verdict" role="status" aria-live="polite"></div></div>';
|
|
}).join('');
|
|
|
|
el.addEventListener('change', function(e){
|
|
var bloc = e.target.closest('.q');
|
|
var i = +bloc.dataset.i, q = questions[i];
|
|
bloc.querySelectorAll('label').forEach(function(l, j){
|
|
l.className = (j === q.b) ? 'bon' : (l.querySelector('input').checked ? 'mauvais' : '');
|
|
});
|
|
bloc.querySelector('.verdict').textContent =
|
|
(+e.target.value === q.b ? 'Exact. ' : 'Non. ') + q.e;
|
|
});
|
|
}
|
|
|
|
/* ---------- chasse aux fautes ----------
|
|
jetons : [{t: mot, f: true si c'est une faute}] */
|
|
function chasse(conteneur, scoreEl, resetBtn, solBtn, jetons, total, motFinal){
|
|
if (!conteneur) return;
|
|
var trouves = new Set(), rates = new Set();
|
|
|
|
function maj(){
|
|
conteneur.querySelectorAll('span').forEach(function(s){
|
|
var i = +s.dataset.i;
|
|
s.className = trouves.has(i) ? 'trouve' : (rates.has(i) ? 'rate' : '');
|
|
});
|
|
scoreEl.textContent = trouves.size + ' sur ' + total + ' trouvées' +
|
|
(rates.size ? ', ' + rates.size + ' clic' + (rates.size > 1 ? 's' : '') + ' à côté' : '') +
|
|
(trouves.size === total ? '. ' + motFinal : '');
|
|
}
|
|
|
|
conteneur.innerHTML = jetons.map(function(j, i){
|
|
return '<span data-i="' + i + '">' + j.t + '</span>';
|
|
}).join(' ');
|
|
|
|
conteneur.addEventListener('click', function(e){
|
|
var s = e.target.closest('span');
|
|
if (!s) return;
|
|
var i = +s.dataset.i;
|
|
if (jetons[i].f) trouves.add(i); else rates.add(i);
|
|
maj();
|
|
});
|
|
resetBtn.addEventListener('click', function(){
|
|
trouves = new Set(); rates = new Set(); maj();
|
|
});
|
|
solBtn.addEventListener('click', function(){
|
|
jetons.forEach(function(j, i){ if (j.f) trouves.add(i); });
|
|
rates = new Set(); maj();
|
|
});
|
|
|
|
maj();
|
|
}
|
|
|
|
/* ---------- surlignage de l'entrée courante du sommaire ---------- */
|
|
function suivreSommaire(){
|
|
var liens = [].slice.call(document.querySelectorAll('.sommaire-lat a[href^="#"]'));
|
|
var cibles = liens
|
|
.map(function(a){ return document.getElementById(a.getAttribute('href').slice(1)); })
|
|
.filter(Boolean);
|
|
if (!cibles.length || !window.IntersectionObserver) return;
|
|
|
|
var obs = new IntersectionObserver(function(entrees){
|
|
entrees.forEach(function(en){
|
|
if (!en.isIntersecting) return;
|
|
liens.forEach(function(a){
|
|
a.classList.toggle('on', a.getAttribute('href') === '#' + en.target.id);
|
|
});
|
|
});
|
|
}, { rootMargin: '-10% 0px -80% 0px' });
|
|
|
|
cibles.forEach(function(c){ obs.observe(c); });
|
|
}
|
|
|
|
window.addEventListener('DOMContentLoaded', suivreSommaire);
|