Leçon 12 / 12
Leçon 12 · Partie 3 — JavaScript & le Web
Mini-projet : quiz interactif
Ce qu'on va construire
On assemble tout ce qu'on a appris pour créer un quiz interactif. L'utilisateur répond à des questions, voit si c'est correct, et obtient son score.
Ce projet combine :
- Un tableau d'objets pour les questions
- Des fonctions pour organiser le code
- Le DOM pour afficher les questions
- Les événements pour détecter les clics
- Les conditions pour vérifier les réponses
La structure HTML
index.html
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>Quiz JavaScript</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div id="quiz">
<div id="progression">Question <span id="numQuestion">1</span> / <span id="totalQuestions"></span></div>
<h2 id="question"></h2>
<div id="reponses"></div>
<p id="feedback"></p>
<button id="btnSuivant" style="display:none">Question suivante →</button>
</div>
<div id="resultat" style="display:none">
<h2>Quiz terminé !</h2>
<p id="score"></p>
<button id="btnRecommencer">Recommencer</button>
</div>
<script src="quiz.js"></script>
</body>
</html>
Le JavaScript complet — quiz.js
quiz.js
// ===== LES QUESTIONS DU QUIZ =====
const questions = [
{
texte: "Quel mot-clé utilise-t-on pour déclarer une variable qui ne changera pas ?",
reponses: ["var", "let", "const", "fixed"],
bonne: 2 // index 2 → "const"
},
{
texte: "Que retourne : typeof \"Bonjour\" ?",
reponses: ["\"text\"", "\"string\"", "\"char\"", "\"word\""],
bonne: 1
},
{
texte: "Comment ajoute-t-on un élément à la fin d'un tableau ?",
reponses: ["tableau.add()", "tableau.append()", "tableau.push()", "tableau.insert()"],
bonne: 2
},
{
texte: "Quel opérateur compare la valeur ET le type ?",
reponses: ["==", "===", "!=", "!=="],
bonne: 1
},
{
texte: "Comment sélectionner un élément HTML par son id ?",
reponses: [
"document.getElement(\"id\")",
"document.querySelector(\".monId\")",
"document.getElementById(\"monId\")",
"document.select(\"#monId\")"
],
bonne: 2
}
];
// ===== VARIABLES D'ÉTAT =====
let indexQuestion = 0; // question actuelle
let score = 0; // nombre de bonnes réponses
let aRepondu = false; // a-t-on déjà répondu à cette question ?
// ===== RÉCUPÉRATION DES ÉLÉMENTS DOM =====
const divQuiz = document.getElementById("quiz");
const divResultat = document.getElementById("resultat");
const elmNumQ = document.getElementById("numQuestion");
const elmTotal = document.getElementById("totalQuestions");
const elmQuestion = document.getElementById("question");
const divReponses = document.getElementById("reponses");
const elmFeedback = document.getElementById("feedback");
const btnSuivant = document.getElementById("btnSuivant");
const elmScore = document.getElementById("score");
const btnRecommencer= document.getElementById("btnRecommencer");
// ===== FONCTIONS =====
// Affiche la question actuelle
function afficherQuestion() {
const q = questions[indexQuestion];
// Mise à jour de la progression
elmNumQ.textContent = indexQuestion + 1;
elmTotal.textContent = questions.length;
// Affiche la question
elmQuestion.textContent = q.texte;
// Crée les boutons de réponse
divReponses.innerHTML = ""; // efface les réponses précédentes
q.reponses.forEach(function(reponse, index) {
const btn = document.createElement("button");
btn.textContent = reponse;
btn.className = "btn-reponse";
btn.addEventListener("click", () => verifierReponse(index));
divReponses.appendChild(btn);
});
// Réinitialise l'état
elmFeedback.textContent = "";
btnSuivant.style.display = "none";
aRepondu = false;
}
// Vérifie si la réponse choisie est correcte
function verifierReponse(indexChoisi) {
if (aRepondu) return; // on ne peut répondre qu'une fois
aRepondu = true;
const q = questions[indexQuestion];
const boutons = divReponses.querySelectorAll(".btn-reponse");
// Colore tous les boutons (vert = bonne réponse, rouge = mauvaise)
boutons.forEach((btn, i) => {
if (i === q.bonne) {
btn.classList.add("correct");
} else if (i === indexChoisi) {
btn.classList.add("incorrect");
}
btn.disabled = true; // désactive tous les boutons
});
// Message de feedback
if (indexChoisi === q.bonne) {
score++;
elmFeedback.textContent = "✅ Bonne réponse !";
} else {
elmFeedback.textContent = `❌ Mauvaise réponse. La bonne réponse était : "${q.reponses[q.bonne]}"`;
}
// Afficher le bouton "Suivant"
btnSuivant.style.display = "inline-block";
}
// Passe à la question suivante ou affiche le résultat
function questionSuivante() {
indexQuestion++;
if (indexQuestion < questions.length) {
afficherQuestion();
} else {
afficherResultat();
}
}
// Affiche le score final
function afficherResultat() {
divQuiz.style.display = "none";
divResultat.style.display = "block";
const pct = Math.round(score / questions.length * 100);
let mention;
if (pct >= 80) mention = "🏆 Excellent !";
else if (pct >= 60) mention = "👍 Bien joué !";
else mention = "📚 Continue à pratiquer !";
elmScore.innerHTML = `
Tu as obtenu <strong>${score}/${questions.length}</strong> (${pct}%)
${mention}
`;
}
// ===== ÉVÉNEMENTS =====
btnSuivant.addEventListener("click", questionSuivante);
btnRecommencer.addEventListener("click", function() {
indexQuestion = 0;
score = 0;
divQuiz.style.display = "block";
divResultat.style.display = "none";
afficherQuestion();
});
// ===== DÉMARRAGE =====
afficherQuestion();
Points clés à retenir de ce projet
Ce quiz utilise tout ce qu'on a vu :
- Un tableau d'objets pour les questions
- Des variables d'état (
indexQuestion,score,aRepondu) pour suivre la progression - Des fonctions séparées : une pour afficher, une pour vérifier, une pour passer à la suivante
forEachpour créer les boutonsaddEventListenersur chaque boutonclassList.addpour colorer les réponses en vert/rouge- DOM pour afficher ou cacher des sections
Pour aller plus loin : améliore ce quiz ! Idées : ajouter une barre de progression, mélanger les questions avec sort(() => Math.random() - 0.5), sauvegarder le meilleur score dans localStorage, ajouter un timer…
// Félicitations !
- Tu maîtrises les bases de JavaScript
- Variables, types, opérateurs, conditions, boucles, fonctions : tu sais les utiliser
- Tu peux accéder au DOM et modifier une page
- Tu sais réagir aux clics et événements
- Prochaine étape : API du navigateur, requêtes réseau (fetch), frameworks Vue.js ou React