Project 1: Interactive Quiz App
📖 Concept
Build an interactive quiz application that tests JavaScript knowledge. This project practices DOM manipulation, event handling, state management, and conditional logic.
Features:
- Multiple-choice questions with dynamic rendering
- Score tracking and progress bar
- Timer for each question
- Results summary with correct/wrong breakdown
- Ability to restart
Concepts practiced: DOM manipulation, Event listeners, Template literals, Arrays, Objects, Conditionals, setTimeout, CSS transitions
💻 Code Example
1// Quiz App — Core Architecture23class QuizApp {4 constructor(questions, container) {5 this.questions = this.shuffle(questions);6 this.container = container;7 this.currentIndex = 0;8 this.score = 0;9 this.answers = [];10 this.timePerQuestion = 30; // seconds11 this.timer = null;12 }1314 start() {15 this.currentIndex = 0;16 this.score = 0;17 this.answers = [];18 this.renderQuestion();19 }2021 renderQuestion() {22 const q = this.questions[this.currentIndex];23 const progress = ((this.currentIndex) / this.questions.length * 100);2425 this.container.innerHTML = `26 <div class="quiz-header">27 <div class="progress-bar">28 <div class="progress-fill" style="width: ${progress}%"></div>29 </div>30 <span class="question-count">31 Question ${this.currentIndex + 1} of ${this.questions.length}32 </span>33 <span class="timer" id="timer">${this.timePerQuestion}s</span>34 </div>35 <div class="question">36 <h2>${q.question}</h2>37 <div class="options">38 ${q.options.map((opt, i) => `39 <button class="option-btn" data-index="${i}">40 ${opt}41 </button>42 `).join("")}43 </div>44 </div>45 `;4647 // Event delegation for options48 this.container.querySelector(".options")49 .addEventListener("click", (e) => {50 if (e.target.matches(".option-btn")) {51 this.handleAnswer(parseInt(e.target.dataset.index));52 }53 });5455 this.startTimer();56 }5758 handleAnswer(selectedIndex) {59 clearInterval(this.timer);60 const q = this.questions[this.currentIndex];61 const correct = selectedIndex === q.correctIndex;62 if (correct) this.score++;6364 this.answers.push({65 question: q.question,66 selected: q.options[selectedIndex],67 correct: q.options[q.correctIndex],68 isCorrect: correct69 });7071 // Visual feedback72 const buttons = this.container.querySelectorAll(".option-btn");73 buttons[q.correctIndex].classList.add("correct");74 if (!correct) buttons[selectedIndex].classList.add("wrong");75 buttons.forEach(btn => btn.disabled = true);7677 setTimeout(() => {78 this.currentIndex++;79 if (this.currentIndex < this.questions.length) {80 this.renderQuestion();81 } else {82 this.showResults();83 }84 }, 1500);85 }8687 startTimer() {88 let timeLeft = this.timePerQuestion;89 const timerEl = this.container.querySelector("#timer");90 this.timer = setInterval(() => {91 timeLeft--;92 timerEl.textContent = `${timeLeft}s`;93 if (timeLeft <= 0) {94 clearInterval(this.timer);95 this.handleAnswer(-1); // Time's up96 }97 }, 1000);98 }99100 showResults() {101 const percentage = Math.round((this.score / this.questions.length) * 100);102 this.container.innerHTML = `103 <div class="results">104 <h2>Quiz Complete!</h2>105 <div class="score-circle">106 <span>${percentage}%</span>107 </div>108 <p>${this.score} / ${this.questions.length} correct</p>109 <button onclick="quiz.start()">Try Again</button>110 </div>111 `;112 }113114 shuffle(arr) {115 return [...arr].sort(() => Math.random() - 0.5);116 }117}118119// Sample questions120const questions = [121 {122 question: "What does typeof null return?",123 options: ['"null"', '"undefined"', '"object"', '"boolean"'],124 correctIndex: 2125 },126 {127 question: "Which is NOT a falsy value?",128 options: ['0', '""', '"false"', 'undefined'],129 correctIndex: 2130 }131];
🏋️ Practice Exercise
Build It Yourself:
- Create the HTML structure with a container div
- Style with CSS (dark theme, animations for correct/wrong answers)
- Add a question bank with at least 20 JavaScript questions
- Implement the timer with visual countdown
- Add local storage to save high scores
- Bonus: Add difficulty levels and categories
⚠️ Common Mistakes
Not clearing the timer when an answer is selected — causes unexpected behavior
Modifying the original questions array (mutation) — always work with a copy
Not removing old event listeners when re-rendering — causes duplicate handlers
Hardcoding the correct answer index — makes it easy to cheat via DevTools
Not handling the edge case when time runs out
💼 Interview Questions
🎤 Mock Interview
Mock interview is powered by AI for Project 1: Interactive Quiz App. Login to unlock this feature.