← Teacher guide

Final challenge: a quiz page

Students build and extend a quiz page from an array of questions, buttons made for each choice, click handlers, a score and a question number, fix an answer check that is always true, add colour feedback and a total, and make a quiz of their own.

The DOM and the browser console · Final challenge: a quiz page · about 65 minutes · Open the student lesson

Classroom resources

Load these into Waypoints Prepare: choose Load URL and paste the copied address, or download the file and import it. In Prepare, the worksheet's Teacher edition shows the answers; the student copy hides them.

Students will be able to

Timing

Predict and Run 10 min · Investigate 15 min · Modify 15 min · Make 25 min

Before class

Read the unit primer first. This is the final challenge; it marks "Challenge complete". It mirrors the p5.js and Python challenges: a list of data, a loop, a handler, a score. Everything has been taught; the new part is putting it together. The questions are an array of objects, buttons are made from the choices, check(choice) is the handler, current and score are the only variables that change. The bug is a single = in an if: no error, every answer is right; the p5 course had > where < belonged. Quizzes that save results or send them anywhere are out of scope: the playground sends nothing. Large projects belong to the teacher (a unit project, a class quiz bank).

Running the lesson

  1. Predict: ask what the page says after each click.
  2. Run: let students play and call out scores.
  3. Investigate: for the bug, ask "does one = compare, or put?"
  4. Modify: ask which two variables change when a question is answered.
  5. Make: pairs write their questions on paper first; swap and play before changing.

The hard part (on purpose)

Where the data lives: the page is built from the array, and only current and score change. Draw those two boxes on the board.

When students get stuck

What you will seeA question to askThe fix
Every answer is correct.Does the check use ===?Compare with three equal signs.
Cannot read properties of undefined (reading text).Has current gone past the end of the array?Stop at questions.length before showing the next question.
The buttons pile up.Is the old choices box emptied first?Set choicesEl.textContent = "" before making new buttons.
The score is wrong after Play again.Was the score set back to 0?Reset current, score and the text on the page.

Answers to the checks

  1. Predict: A student clicks 6, then clicks 7. What does the result say at the end?
    Correct! Each click runs pick and sets the result. The second click replaces the first message: textContent replaces the words.
  2. Which piece does what?: Match each piece with what it does.
    questions[current].answer → A. the right answer shown now; for (const c of q.choices) { … } → B. makes one button for each choice; current = current + 1; → C. moves on to the next question; if (current < questions.length) { … } else { … } → D. next question or the end
  3. A fourth question: You want to add a fourth question. What is the smallest change?
    Add one more object to the questions array
    The page is built from the array. One more object gives one more question, with its own choices and answer: nothing else needs to change.
  4. Spot the bug: Every answer says Correct!, even the wrong ones. There is no red error. Click the line that is wrong.
    line 27
    One = puts the answer into choice and is always true. Compare with three: choice === questions[current].answer.
  5. Where this leads: A bigger version of your quiz saves the best score for next time. What would it need that this page does not have?
    A way to store data between visits, such as a server or the browser's own storage
    A page forgets everything when it is closed. Remembering between visits needs somewhere to keep data: in the browser, or on a server, as in the Python web apps course.

Solutions

One possible solution for each task. Other correct programs are fine.

Modify › Colours

<h1>Capital cities quiz</h1>
<p id="question"></p>
<div id="choices"></div>
<p id="feedback"></p>
<p>Score: <span id="score">0</span></p>
<script>
  const questions = [
    { text: "What is the capital of France?", choices: ["Paris", "Rome", "Madrid"], answer: "Paris" },
    { text: "What is the capital of Japan?", choices: ["Seoul", "Tokyo", "Beijing"], answer: "Tokyo" },
    { text: "What is the capital of Australia?", choices: ["Sydney", "Canberra", "Perth"], answer: "Canberra" },
  ];
  let current = 0;
  let score = 0;
  const questionEl = document.querySelector("#question");
  const choicesEl = document.querySelector("#choices");
  const feedbackEl = document.querySelector("#feedback");
  const scoreEl = document.querySelector("#score");

  function showQuestion() {
    const q = questions[current];
    questionEl.textContent = q.text;
    choicesEl.textContent = "";
    for (const choice of q.choices) {
      const button = document.createElement("button");
      button.textContent = choice;
      button.addEventListener("click", function () {
        check(choice);
      });
      choicesEl.append(button);
    }
  }

  function check(choice) {
    if (choice === questions[current].answer) {
      score = score + 1;
      scoreEl.textContent = score;
      feedbackEl.textContent = "Correct!";
      feedbackEl.style.color = "green";
    } else {
      feedbackEl.textContent = "Not quite: it was " + questions[current].answer;
      feedbackEl.style.color = "crimson";
    }
    current = current + 1;
    if (current < questions.length) {
      showQuestion();
    } else {
      questionEl.textContent = "Finished! Score: " + score;
      choicesEl.textContent = "";
    }
  }

  showQuestion();
</script>

Modify › Out of three

<h1>Capital cities quiz</h1>
<p id="question"></p>
<div id="choices"></div>
<p id="feedback"></p>
<p>Score: <span id="score">0</span></p>
<script>
  const questions = [
    { text: "What is the capital of France?", choices: ["Paris", "Rome", "Madrid"], answer: "Paris" },
    { text: "What is the capital of Japan?", choices: ["Seoul", "Tokyo", "Beijing"], answer: "Tokyo" },
    { text: "What is the capital of Australia?", choices: ["Sydney", "Canberra", "Perth"], answer: "Canberra" },
  ];
  let current = 0;
  let score = 0;
  const questionEl = document.querySelector("#question");
  const choicesEl = document.querySelector("#choices");
  const feedbackEl = document.querySelector("#feedback");
  const scoreEl = document.querySelector("#score");

  function showQuestion() {
    const q = questions[current];
    questionEl.textContent = q.text;
    choicesEl.textContent = "";
    for (const choice of q.choices) {
      const button = document.createElement("button");
      button.textContent = choice;
      button.addEventListener("click", function () {
        check(choice);
      });
      choicesEl.append(button);
    }
  }

  function check(choice) {
    if (choice === questions[current].answer) {
      score = score + 1;
      scoreEl.textContent = score;
      feedbackEl.textContent = "Correct!";
    } else {
      feedbackEl.textContent = "Not quite: it was " + questions[current].answer;
    }
    current = current + 1;
    if (current < questions.length) {
      showQuestion();
    } else {
      questionEl.textContent = "Finished! You scored " + score + " of " + questions.length;
      choicesEl.textContent = "";
    }
  }

  showQuestion();
</script>

your own quiz

<h1>Space quiz</h1>
<p id="question"></p>
<div id="choices"></div>
<p id="feedback"></p>
<p>Score: <span id="score">0</span></p>
<button id="again" class="hidden">Play again</button>
<style>.hidden { display: none; }</style>
<script>
  const questions = [
    { text: "Which planet is closest to the Sun?", choices: ["Mercury", "Venus", "Mars"], answer: "Mercury" },
    { text: "What is the Moon?", choices: ["A star", "A moon of Earth", "A planet"], answer: "A moon of Earth" },
    { text: "Which planet has rings you can see easily?", choices: ["Saturn", "Mars", "Earth"], answer: "Saturn" },
    { text: "What do we call our galaxy?", choices: ["Andromeda", "The Milky Way", "Orion"], answer: "The Milky Way" },
    { text: "How many planets orbit the Sun?", choices: ["Eight", "Nine", "Seven"], answer: "Eight" },
  ];
  let current = 0;
  let score = 0;
  const questionEl = document.querySelector("#question");
  const choicesEl = document.querySelector("#choices");
  const feedbackEl = document.querySelector("#feedback");
  const scoreEl = document.querySelector("#score");
  const again = document.querySelector("#again");

  function showQuestion() {
    const q = questions[current];
    questionEl.textContent = q.text;
    choicesEl.textContent = "";
    for (const choice of q.choices) {
      const button = document.createElement("button");
      button.textContent = choice;
      button.addEventListener("click", function () {
        check(choice);
      });
      choicesEl.append(button);
    }
  }

  function check(choice) {
    if (choice === questions[current].answer) {
      score = score + 1;
      scoreEl.textContent = score;
      feedbackEl.textContent = "Correct!";
    } else {
      feedbackEl.textContent = "Not quite: it was " + questions[current].answer;
    }
    current = current + 1;
    if (current < questions.length) {
      showQuestion();
    } else {
      questionEl.textContent = "Finished! You scored " + score + " of " + questions.length;
      choicesEl.textContent = "";
      again.classList.remove("hidden");
    }
  }

  again.addEventListener("click", function () {
    current = 0;
    score = 0;
    scoreEl.textContent = score;
    feedbackEl.textContent = "";
    again.classList.add("hidden");
    showQuestion();
  });

  showQuestion();
</script>

Stretch and support

Stretch: Shuffle the questions, add a timer with setInterval, or give harder questions more points using a property on each object.

Support: Give the whole quiz and ask students to add only questions of their own, then the colour feedback.

Exit ticket

Which two variables change as the quiz is played?

current, the number of the question on the screen, and score, how many were right.

What each step is for

Where it leads

Optional next lesson: the real browser console. Beyond the course: the Python web apps course, to keep results between visits.