|
| 1 | +// All global variables |
| 2 | +let STORE = []; // Array to store quiz questions and answers |
| 3 | +let questionNumber = 1; // Current question number |
| 4 | +let correctAnswers = 0; // Number of correct answers |
| 5 | +let incorrectAnswers = 0; // Number of incorrect answers |
| 6 | +let currentQuestion = 0; // Index of the current question |
| 7 | +let correctMessage; // Message to display for correct answers |
| 8 | +let incorrectMessage; // Message to display for incorrect answers |
| 9 | + |
| 10 | +// Runs when the window is loaded |
| 11 | +window.onload = function() { |
| 12 | + buttons(); // Attach event handlers to buttons |
| 13 | + $('.scoreboard').html(scores()); // Initialize the scoreboard |
| 14 | +}; |
| 15 | + |
| 16 | +// All of the button press options |
| 17 | +function buttons() { |
| 18 | + // Event handler for the "Begin" button |
| 19 | + $('.box').on('click', '#begin', function() { |
| 20 | + event.preventDefault(); // Prevent page reload |
| 21 | + let numQ = $('#numQ').val(); // Get the number of questions from the input |
| 22 | + let diff; |
| 23 | + let cat; |
| 24 | + |
| 25 | + // Check if difficulty is specified and construct URL |
| 26 | + if ($('#difficulty').val() === 'any') { |
| 27 | + diff = ''; |
| 28 | + } else { |
| 29 | + diff = `&difficulty=${$('#difficulty').val()}`; |
| 30 | + } |
| 31 | + |
| 32 | + // Check if category is specified and construct URL |
| 33 | + if ($('#category').val() === 'any') { |
| 34 | + cat = ''; |
| 35 | + } else { |
| 36 | + cat = `&category=${$('#category').val()}`; |
| 37 | + } |
| 38 | + |
| 39 | + // Display loading message and prevent multiple clicks |
| 40 | + $('#begin').replaceWith(`<p>Loading...</p>`); |
| 41 | + createQuestions(numQ, diff, cat); |
| 42 | + }); |
| 43 | + |
| 44 | + // Event handler for the "Next" button |
| 45 | + $('.box').on('click', '#next', function() { |
| 46 | + event.preventDefault(); |
| 47 | + handleNext(); |
| 48 | + }); |
| 49 | + |
| 50 | + // Event handler for the "Submit" button (when guessing) |
| 51 | + $('.box').on('click', '#guess', function() { |
| 52 | + event.preventDefault(); |
| 53 | + handleGuess(); |
| 54 | + }); |
| 55 | + |
| 56 | + // Event handler for the "New Quiz" button (restart) |
| 57 | + $('.box').on('click', '#restart', function() { |
| 58 | + event.preventDefault(); |
| 59 | + STORE = []; // Clear questions before starting a new game |
| 60 | + restartQuiz(); |
| 61 | + }); |
| 62 | +} |
| 63 | + |
| 64 | +// Uses fetch to utilize the API and sends the JSON data to the testData function |
| 65 | +function createQuestions(numQ, diff, cat) { |
| 66 | + let url = `https://opentdb.com/api.php?amount=${numQ}&type=multiple${diff}${cat}`; |
| 67 | + fetch(url) |
| 68 | + .then((response) => response.json()) |
| 69 | + .then((responseJson) => testData(responseJson, numQ, diff, cat)) |
| 70 | + .catch((error) => alert(error)); |
| 71 | +} |
| 72 | + |
| 73 | +// This makes sure the API has enough questions for requested specifications |
| 74 | +function testData(data, numQ, diff, cat) { |
| 75 | + if (data.response_code === 0) { |
| 76 | + createArr(data); // If enough questions are available, create an array of questions |
| 77 | + } else { |
| 78 | + numQ--; |
| 79 | + createQuestions(numQ, diff, cat); // Try again with fewer questions |
| 80 | + } |
| 81 | +} |
| 82 | + |
| 83 | +// creates the array of questions using the JSON data |
| 84 | +function createArr(data) { |
| 85 | + for (let question in data.results) { |
| 86 | + let arr = []; |
| 87 | + |
| 88 | + // Create an array of potential answers |
| 89 | + arr.push(data.results[question].correct_answer); |
| 90 | + arr.push(data.results[question].incorrect_answers[0]); |
| 91 | + arr.push(data.results[question].incorrect_answers[1]); |
| 92 | + arr.push(data.results[question].incorrect_answers[2]); |
| 93 | + |
| 94 | + // Shuffle the order of the answers |
| 95 | + for (let i = arr.length - 1; i > 0; i--) { |
| 96 | + let j = Math.floor(Math.random() * (i + 1)); |
| 97 | + [arr[i], arr[j]] = [arr[j], arr[i]]; |
| 98 | + } |
| 99 | + |
| 100 | + // Create an object containing the question, array of potential answers, and actual answer |
| 101 | + let newObj = { |
| 102 | + question: data.results[question].question, |
| 103 | + answers: arr, |
| 104 | + rightAnswer: data.results[question].correct_answer |
| 105 | + }; |
| 106 | + STORE.push(newObj); |
| 107 | + } |
| 108 | + renderQuestion(); // Display the first question |
| 109 | +} |
| 110 | + |
| 111 | +// Renders the question form |
| 112 | +function renderQuestion() { |
| 113 | + $('.box').html( |
| 114 | + ` |
| 115 | + <form> |
| 116 | + <fieldset name="question"> |
| 117 | + <legend>Question ${questionNumber} of ${STORE.length}</legend> |
| 118 | + ${STORE[currentQuestion].question} |
| 119 | + </fieldset> |
| 120 | + <fieldset name="answers"> |
| 121 | + <legend>Answers</legend> |
| 122 | + <input type="radio" name="answer" class="posAnswer" value="${STORE[currentQuestion] |
| 123 | + .answers[0]}" data-value= "${STORE[currentQuestion].answers[0]}"> ${STORE[currentQuestion] |
| 124 | + .answers[0]}<br> |
| 125 | + <input type="radio" name="answer" class="posAnswer" value="${STORE[currentQuestion] |
| 126 | + .answers[1]}" data-value= "${STORE[currentQuestion].answers[1]}"> ${STORE[currentQuestion] |
| 127 | + .answers[1]}<br> |
| 128 | + <input type="radio" name="answer" class="posAnswer" value="${STORE[currentQuestion] |
| 129 | + .answers[2]}" data-value= "${STORE[currentQuestion].answers[2]}"> ${STORE[currentQuestion] |
| 130 | + .answers[2]}<br> |
| 131 | + <input type="radio" name="answer" class="posAnswer" value="${STORE[currentQuestion] |
| 132 | + .answers[3]}" data-value= "${STORE[currentQuestion].answers[3]}"> ${STORE[currentQuestion] |
| 133 | + .answers[3]}<br> |
| 134 | + <button name="answer" id="guess">Submit</button> |
| 135 | + <button name="answer" id="next" class="hidden">Next</button> |
| 136 | + </fieldset> |
| 137 | + </form> |
| 138 | + <p class="hidden" id="message">Test</p> |
| 139 | + <p class="hidden wrong" id="error">"Please select an answer."</p> |
| 140 | + ` |
| 141 | + ); |
| 142 | +} |
| 143 | + |
| 144 | +// Handles when someone guesses an answer |
| 145 | +function handleGuess() { |
| 146 | + // Checks to see if an option is checked |
| 147 | + if ($("input[name='answer']:checked").data('value')) { |
| 148 | + guess(); |
| 149 | + } else { |
| 150 | + // Shows the error message if nothing is checked |
| 151 | + if ($('#error').hasClass('hidden')) { |
| 152 | + $('#error').toggleClass('hidden'); |
| 153 | + } |
| 154 | + } |
| 155 | +} |
| 156 | + |
| 157 | +// Checks whether answer is correct or not |
| 158 | +function guess() { |
| 159 | + if (!$('#error').hasClass('hidden')) { |
| 160 | + $('#error').toggleClass('hidden'); |
| 161 | + } |
| 162 | + |
| 163 | + // Disables ability to guess again on the current question |
| 164 | + $('input[type=radio]').attr('disabled', true); |
| 165 | + |
| 166 | + // Handle special characters in answers |
| 167 | + let encodedStr = STORE[currentQuestion].rightAnswer; |
| 168 | + let parser = new DOMParser(); |
| 169 | + let dom = parser.parseFromString('<!doctype html><body>' + encodedStr, 'text/html'); |
| 170 | + let decodedString = dom.body.textContent; |
| 171 | + |
| 172 | + correctMessage = `That is correct! Way to go!`; |
| 173 | + incorrectMessage = `That is incorrect. The correct answer is: ${decodedString}.`; |
| 174 | + |
| 175 | + if ($("input[name='answer']:checked").data('value') == decodedString) { |
| 176 | + $('#message').text(`${correctMessage}`); |
| 177 | + correctAnswers++; |
| 178 | + } else { |
| 179 | + $('#message').text(`${incorrectMessage}`); |
| 180 | + incorrectAnswers++; |
| 181 | + } |
| 182 | + toggleClasses(); // Toggle messages for correct/incorrect and update the score |
| 183 | +} |
| 184 | + |
| 185 | +// Toggles the messages for correct/incorrect and shows the new score |
| 186 | +function toggleClasses() { |
| 187 | + $('#message').toggleClass('hidden'); |
| 188 | + $('#guess').toggleClass('hidden'); |
| 189 | + $('#next').toggleClass('hidden'); |
| 190 | + $('.scoreboard').html(scores()); // Update the scoreboard |
| 191 | +} |
| 192 | + |
| 193 | +// Handles when someone presses the next button |
| 194 | +function handleNext() { |
| 195 | + if (questionNumber != STORE.length) { |
| 196 | + currentQuestion++; |
| 197 | + questionNumber++; |
| 198 | + renderQuestion(); // Display the next question |
| 199 | + } else { |
| 200 | + $('.box').html(results()); // Display the results when all questions are answered |
| 201 | + } |
| 202 | +} |
| 203 | + |
| 204 | +// This is the display for the results page. |
| 205 | +function results() { |
| 206 | + // Messages given based on the score |
| 207 | + let goodScore = ' You really know your trivia!'; |
| 208 | + let okayScore = ' Try again and see if you can do better!'; |
| 209 | + let badScore = ' Better Luck Next Time.'; |
| 210 | + |
| 211 | + let scoreMessage; |
| 212 | + |
| 213 | + if (correctAnswers > STORE.length * 0.7) { |
| 214 | + scoreMessage = ' 😎👌' + goodScore; |
| 215 | + } else if (correctAnswers > STORE.length * 0.4) { |
| 216 | + scoreMessage = ' 😉' + okayScore; |
| 217 | + } else { |
| 218 | + scoreMessage = ' 😵' + badScore; |
| 219 | + } |
| 220 | + |
| 221 | + const resultBox = ` |
| 222 | + <div class='results'> |
| 223 | + <h2>Results</h2> |
| 224 | + <p> |
| 225 | + You got ${correctAnswers} out of ${STORE.length} questions correct. ${scoreMessage} |
| 226 | + </p> |
| 227 | + <button name="answer" id="restart" class="resultBtn">New Quiz</button> |
| 228 | + </div> |
| 229 | + `; |
| 230 | + return resultBox; |
| 231 | +} |
| 232 | + |
| 233 | +// Resets everything and starts fresh |
| 234 | +function restartQuiz() { |
| 235 | + questionNumber = 1; |
| 236 | + correctAnswers = 0; |
| 237 | + incorrectAnswers = 0; |
| 238 | + currentQuestion = 0; |
| 239 | + $('.box').html(` |
| 240 | + <form> |
| 241 | + <fieldset name="intro"> |
| 242 | + <legend>Try It Out</legend> |
| 243 | + Test your knowledge with a random quiz! |
| 244 | + </fieldset> |
| 245 | + <fieldset name="options"> |
| 246 | + <label for="numQ">Number of Questions</label> |
| 247 | + <input type="number" placeholder="10" id="numQ" s min="1" max="50" value="10" /> |
| 248 | + <br> |
| 249 | + <label for="difficulty">Choose a difficulty</label> |
| 250 | + <select name="difficulty" id="difficulty"> |
| 251 | + <option value="any">Mixed Difficulty</option> |
| 252 | + <option value="easy">Easy Questions</option> |
| 253 | + <option value="medium">Medium Questions</option> |
| 254 | + <option value="hard">Hard Questions</option> |
| 255 | + </select> |
| 256 | + <br> |
| 257 | + <label for="category">Select a Category: </label> |
| 258 | + <select name="category" id="category"> |
| 259 | + <!-- Categories options here --> |
| 260 | + </select> |
| 261 | + </fieldset> |
| 262 | + <button id="begin">Begin</button> |
| 263 | + </form> |
| 264 | + `); |
| 265 | + $('.scoreboard').html(scores()); // Update the scoreboard |
| 266 | +} |
| 267 | + |
| 268 | +// Handles the display of the scores |
| 269 | +function scores() { |
| 270 | + const scoreMake = ` |
| 271 | + <li class="scores">✅ Correct: ${correctAnswers}</li> |
| 272 | + <li class="scores">❌ Incorrect: ${incorrectAnswers}</li> |
| 273 | + `; |
| 274 | + return scoreMake; |
| 275 | +} |
0 commit comments