I am building a simple quiz with JavaScript, when the game starts everything works fine timer counts down, the score and questions both receive the correct values, but when the last question is answered the game will not end until the timer hits 0. I have moved where the timer starts and the game ends when time hits zero still to no success.
please check out the deployed page for a better view of the issue.
https://brycebann.github.io/The-Coding-Quiz/
//calling in id/class from HTML
const questionEl = document.getElementById("question")
const checkers = document.getElementById("right-wrong")
const timerEl = document.getElementsByClassName("timeSpan")
const answerOne = document.getElementById("answer1")
const answerTwo = document.getElementById("answer2")
const answerThree = document.getElementById("answer3")
const answerFour = document.getElementById("answer4")
const finalScoreEl = document.getElementById("pointScore")
const nameEl = document.getElementById("initials")
const highScoreEl = document.getElementById("highScoreList")
//const randomQuestionMix = mixedQ(); comment out to address later
//test question
var questionKey = [
{
question: "which variable has the value of a string.",
choiceOne: "x = 6",
choiceTwo: "x = \"87\"",
choiceThree: "x = true",
choiceFour: "x;",
answer: "x = \"87\""
},
{
question: "choose the operator that checks for value and type.",
choiceOne: "=",
choiceTwo: "+=",
choiceThree: "===",
choiceFour: "<=;",
answer: "==="
},
{
question: "choose the true statement.",
choiceOne: "4 != 4",
choiceTwo: "4 > 85",
choiceThree: "7 === \"7\"",
choiceFour: "7.6 == \"7.6\"",
answer: "7.6 == \"7.6\""
},
{
question: "which data type is not primitive.",
choiceOne: "boolean",
choiceTwo: "array",
choiceThree: "number",
choiceFour: "string",
answer: "array"
},
{
question: "Which one is the Increment operator.",
choiceOne: "**",
choiceTwo: "/",
choiceThree: "++",
choiceFour: "+=",
answer: "++"
}
];
//starting positions
let timeLeft = 60;
let score = 0;
let currentQuestion = -1
let finalScore;
//change div to start the test
function changeDiv(curr, next) {
document.getElementById(curr).classList.add('hide');
document.getElementById(next).removeAttribute('class')
};
//button to start the game, this button will start the functions to change the on screen div and start the count down timer
document.querySelector('#startButton').addEventListener('click', gameStart);
function gameStart() {
changeDiv('start', 'questionHolder');
currentQuestion = 0;
displayQuestion();
startTimer();
};
//timer function/Count down
function startTimer() {
let timeInterval = setInterval(
() => {
timeLeft--;
document.getElementById("timeSpan").innerHTML = timeLeft
if (timeLeft <= 0) {
clearInterval(timeInterval);
gameOver();
}
}, 1000);
};
function displayQuestion() {
questionEl.textContent = questionKey[currentQuestion].question
answerOne.textContent = questionKey[currentQuestion].choiceOne
answerTwo.textContent = questionKey[currentQuestion].choiceTwo
answerThree.textContent = questionKey[currentQuestion].choiceThree
answerFour.textContent = questionKey[currentQuestion].choiceFour
}
//will end game when all questions are completed as well as populate the next question
document.querySelector('#questionHolder').addEventListener('click', nextquestion);
function nextquestion(event) {
//console.log(event)
//console.log(event.target.className)
//console.log(event.target.textContent)
if (event.target.className === "btn") {
console.log(event.target.textContent, questionKey[currentQuestion].answer)
if (event.target.textContent === questionKey[currentQuestion].answer) {
score += 10
console.log("correct")
console.log(score)
} else {
if (timeLeft >= 10) {
console.log(timeLeft)
timeLeft = timeLeft - 10;
document.getElementById("timeSpan").innerHTML = timeLeft
console.log("not correct")
} else {
timeLeft = 0;
gameOver();
}
}
currentQuestion++;
displayQuestion();
}
};
//the game is over and logs your current score
function gameOver() {
timerEl.textContent = 0;
changeDiv('questionHolder', 'finishedPage');
finalScore = score;
finalScoreEl.textContent = finalScore;
};
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>The coding quiz</title>
<link rel="stylesheet" a href="./Main/style.css">
</head>
<body>
<!--Top of page-->
<header>
<div id="pageTop">
<h1>The coding quiz</h1>
</div>
</header>
<!--High score and timer div -->
<div id="scoreTime">
<p class="highscore">View highscores</p>
<p class="timer">Time left: <span id="timeSpan">60</span></p>
</div>
<!--Main quiz portion of the page-->
<div id="quizHolder">
<div id="start">
<h2>Basic Code Quiz</h2>
<p>Welcome to the basic coding quiz, this quiz will test you knoweledge on basic javascript.</p>
<button id="startButton" class="btn">Start</button>
</div>
<div id="questionHolder" class="hide">
<h2 id="question"></h2>
<button id="answer1" class="btn"></button>
<button id="answer2" class="btn"></button>
<button id="answer3" class="btn"></button>
<button id="answer4" class="btn"></button>
</div>
<!--Results and high score-->
<div id="finishedPage" class="hide">
<h2>Quiz Complete</h2>
<p>Your final score is <span id="pointScore"></span>/50</p>
<label>Enter your initials:</label>
<input type="text" id="initials">
<button id="sendScore" class="btn">Submit score</button>
</div>
</div>
<script src="Main/script.js"></script>
</body>
</html>
After you increment the "current question" counter, here currentQuestion++; check if the counter reached the length of your questions array questionKey:
// IF THERE ARE NO MORE QUESTIONS, CALL gameOver
if (currentQuestion == questionKey.length) {
gameOver();
} else {
displayQuestion();
}
//calling in id/class from HTML
const questionEl = document.getElementById("question")
const checkers = document.getElementById("right-wrong")
const timerEl = document.getElementsByClassName("timeSpan")
const answerOne = document.getElementById("answer1")
const answerTwo = document.getElementById("answer2")
const answerThree = document.getElementById("answer3")
const answerFour = document.getElementById("answer4")
const finalScoreEl = document.getElementById("pointScore")
const nameEl = document.getElementById("initials")
const highScoreEl = document.getElementById("highScoreList")
//const randomQuestionMix = mixedQ(); comment out to address later
//test question
var questionKey = [
{
question: "which variable has the value of a string.",
choiceOne: "x = 6",
choiceTwo: "x = \"87\"",
choiceThree: "x = true",
choiceFour: "x;",
answer: "x = \"87\""
},
{
question: "choose the operator that checks for value and type.",
choiceOne: "=",
choiceTwo: "+=",
choiceThree: "===",
choiceFour: "<=;",
answer: "==="
},
{
question: "choose the true statment.",
choiceOne: "4 != 4",
choiceTwo: "4 > 85",
choiceThree: "7 === \"7\"",
choiceFour: "7.6 == \"7.6\"",
answer: "7.6 == \"7.6\""
},
{
question: "which data type is not primitive.",
choiceOne: "boolean",
choiceTwo: "array",
choiceThree: "number",
choiceFour: "string",
answer: "array"
},
{
question: "Wich one is the Increment operator.",
choiceOne: "**",
choiceTwo: "/",
choiceThree: "++",
choiceFour: "+=",
answer: "++"
}
];
//starting postions
let timeLeft = 60;
let score = 0;
let currentQuestion = -1
let finalScore;
let timeInterval;
//change div to start the test
function changeDiv(curr, next) {
document.getElementById(curr).classList.add('hide');
document.getElementById(next).removeAttribute('class')
};
//button to start the game, this button will start the functions to cnage the on screen div and start the count down timer
document.querySelector('#startButton').addEventListener('click', gameStart);
function gameStart() {
changeDiv('start', 'questionHolder');
currentQuestion = 0;
displayQuestion();
startTimer();
};
//timer function/Count down
function startTimer() {
timeInterval = setInterval(
() => {
timeLeft--;
document.getElementById("timeSpan").innerHTML = timeLeft
if (timeLeft <= 0) {
clearInterval(timeInterval);
gameOver();
}
}, 1000);
};
function displayQuestion() {
questionEl.textContent = questionKey[currentQuestion].question
answerOne.textContent = questionKey[currentQuestion].choiceOne
answerTwo.textContent = questionKey[currentQuestion].choiceTwo
answerThree.textContent = questionKey[currentQuestion].choiceThree
answerFour.textContent = questionKey[currentQuestion].choiceFour
}
//will end game when all questions are completed as well as populate the next question
document.querySelector('#questionHolder').addEventListener('click', nextquestion);
function nextquestion(event) {
//console.log(event)
//console.log(event.target.className)
//console.log(event.target.textContent)
if (event.target.className === "btn") {
console.log(event.target.textContent, questionKey[currentQuestion].answer)
if (event.target.textContent === questionKey[currentQuestion].answer) {
score += 10
console.log("correct")
console.log(score)
} else {
if (timeLeft >= 10) {
console.log(timeLeft)
timeLeft = timeLeft - 10;
document.getElementById("timeSpan").innerHTML = timeLeft
console.log("not correct")
} else {
timeLeft = 0;
gameOver();
}
}
currentQuestion++;
// IF THERE ARE NO MORE QUESTIONS, CALL gameOver
if (currentQuestion == questionKey.length) {
clearInterval(timeInterval);
gameOver();
} else {
displayQuestion();
}
}
};
//the game is over and logs your current score
function gameOver() {
timerEl.textContent = 0;
changeDiv('questionHolder', 'finishedPage');
finalScore = score;
finalScoreEl.textContent = finalScore;
};
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>The coding quiz</title>
<link rel="stylesheet" a href="./Main/style.css">
</head>
<body>
<!--Top of page-->
<header>
<div id="pageTop">
<h1>The coding quiz</h1>
</div>
</header>
<!--High score and timer div -->
<div id="scoreTime">
<p class="highscore">View highscores</p>
<p class="timer">Time left: <span id="timeSpan">60</span></p>
</div>
<!--Main quiz portion of the page-->
<div id="quizHolder">
<div id="start">
<h2>Basic Code Quiz</h2>
<p>Welcome to the basic coding quiz, this quiz will test you knoweledge on basic javascript.</p>
<button id="startButton" class="btn">Start</button>
</div>
<div id="questionHolder" class="hide">
<h2 id="question"></h2>
<button id="answer1" class="btn"></button>
<button id="answer2" class="btn"></button>
<button id="answer3" class="btn"></button>
<button id="answer4" class="btn"></button>
</div>
<!--Results and high score-->
<div id="finishedPage" class="hide">
<h2>Quiz Complete</h2>
<p>Your final score is <span id="pointScore"></span>/50</p>
<label>Enter your initials:</label>
<input type="text" id="initials">
<button id="sendScore" class="btn">Submit score</button>
</div>
</div>
<script src="Main/script.js"></script>
</body>
</html>
Related
I’m making kind of a funny website where it gives you a scrambled word and you have to unscramble it. To add to the vibe of the page, I want to scramble the title every time you type a letter, just for the fun of it. Unfortunately, when using addEventListener, it seems to run the code then add the letter when I type in the box. You will see this if you type one letter or backspace one letter. If you have any other amount of letters though, it will be find. Is there a better way to see if I'm typing in the box to update the title?
var points = 0
function sleep(milliseconds) {
const date = Date.now();
let currentDate = null;
do {
currentDate = Date.now();
} while (currentDate - date < milliseconds);
}
function win() {
points += 1
document.getElementById('points').innerHTML = "Points:" + points
currentWord = words[Math.floor(Math.random() * words.length)]
document.getElementById('word').innerHTML = scramble(currentWord)
guess = ""
currentWord = words[Math.floor(Math.random() * words.length)]
document.getElementById('word').innerHTML = scramble(currentWord)
}
guess = ""
words = ["apple", "banana", "cherry", "orange", "pear", "grape", "peach", "mango", "strawberry", "blueberry", "blackberry", "raspberry", "watermelon", "cantaloupe", "pineapple", "kiwi", "avocado", "coconut", "papaya", "plum", "apricot", "lemon", "lime", "fig", "nectarine"]
function scramble(a) {
a = a.split("");
for (var b = a.length - 1; 0 < b; b--) {
var c = Math.floor(Math.random() * (b + 1));
d = a[b];
a[b] = a[c];
a[c] = d
}
return a.join("")
}
var textBox = document.getElementById('myTextBox');
var value = textBox.value;
textBox.addEventListener("keydown", (event) => {
console.log(currentWord)
if (event.isComposing || event.keyCode === 13) {
console.log(textBox.value)
guess = textBox.value
textBox.value = ""
document.getElementById('title').innerHTML = "Unscramble the Word"
if (guess === currentWord) {
console.log("YOU WINNNNNNNNNNNNNNNNNNN")
win()
}
return;
}
if (textBox.value === "") {
console.log("not working")
document.getElementById('title').innerHTML = "Unscramble the Word"
} else {
document.getElementById('title').innerHTML = scramble("Unscramble the Word")
}
});
currentWord = words[Math.floor(Math.random() * words.length)]
document.getElementById('word').innerHTML = scramble(currentWord)
html,
body {
height: 100%;
width: 100%;
}
body {
background: lightblue;
}
#center {
text-align: center;
}
#word {}
#myTextBox {}
#title {}
#party {}
#points {}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>Random</title>
<link href="style.css" rel="stylesheet" type="text/css" />
<div id="center">
<h1 id="title">Unscramble the Word</h1>
</div>
</head>
<body>
<div style="text-align: center;">
<p id="word">SOMTHING IS VERRY VERRY WRONG</p>
</div>
<div style="height:100px; text-align:center" id="party"></div>
style="text-align: center;"><input type="text" id="myTextBox" autocomplete="off"></div>
<div style="text-align: center;" "<p id="points " >Points:</p>
<script src="script.js "></script>
</body>
</html>
I think for you the input event would work the best; See https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/input_event
Demo:
const words = ["apple", "banana", "cherry", "orange"]
let currentWord;
function scramble(a) {
return a.split("").sort(x=>0.5-Math.random()).join("")
}
function reset() {
currentWord = words[Math.floor(Math.random() * words.length)]
document.getElementById('word').innerHTML = scramble(currentWord)
}
function win() {
alert("You win, it was "+currentWord+"! Try a new one!")
reset()
}
document.getElementById('guess').addEventListener("input", (e) => {
if (e.target.value === currentWord) {
e.target.value = ""
win()
}
})
reset()
<p>Your word is <b id="word"></b></p>
<input type="text" id="guess" autocomplete="off">
I am trying to create the below game. The Javascript textcontent however is not displaying anything.
The Computer selects a random "secret" number between some min and max.
The Player is tasked with guessing the number. For each guess, the application informs the user whether their number is higher or lower than the "secret" number.
Extra challenges:
Limit the number of guesses the Player has.
Keep track/report which numbers have been guessed.
My code is as follows:
const submitguess = document.querySelector('.submitguess');
const inputno = document.querySelector('#secretno');
const resultmatch = document.querySelector('#resultmatch');
const highorlow = document.querySelector('#highorlow');
const guesslist = document.querySelector('#guesslist');
let randomNumber = Math.floor(Math.random() * 10) + 1;
let count = 1;
let resetButton;
function guessvalid() {
let input = Number(inputno.value);
//alert('I am at 0');
if (count === 1) {
guesslist.textContent = 'Last guesses:';
}
guesslist.textContent += input + ', ';
if (randomNumber === input) {
//alert('I am here 1');
resultmatch.textContent = 'Bazingaa!!! You got it absolutely right';
highorlow.textContent = '';
guesslist.textContent = '';
GameOver();
} else if (count === 5) {
resultmatch.textContent = 'Game Over !! Thanks for playing.';
//alert('I am here 2');
highorlow.textContent = '';
guesslist.textContent = '';
GameOver();
} else {
//alert('I am here 3');
resultmatch.textContent = 'Sorry the secret no and your guess do not match.Please try again !!';
if (randomNumber > input) {
//alert('I am here 4');
highorlow.textContent = 'Hint.The guess was lower than the secret no.';
} else if (randomNumber < input) {
//alert('I am here 5');
highorlow.textContent = 'Hint.The guess was higher than the secret no.';
}
}
count = count + 1;
input.value = '';
}
submitguess.addEventListener('click', guessvalid);
function GameOver() {
inputno.disabled = true;
submitguess.disabled = true;
resetButton = document.createElement('button');
resetButton.textContent = 'Lets play again';
document.body.appendChild(resetButton);
resetButton.addEventListener('click', reset);
}
function reset() {
count = 1;
const newDisplay = document.querySelectorAll('.display p');
for(let k = 0 ; k < newDisplay.length ; k++) {
newDisplay[k].textContent = '';
}
resetButton.parentNode.removeChild(resetButton);
inputno.disabled = false;
submitguess.disabled = false;
inputno.value = '';
randomNumber = Math.floor(Math.random() * 10) + 1;
}
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'>
<meta name='viewport' content='width=device-width, initial-scale=1.0'>
<title>Hi Low</title>
<link rel='stylesheet' href='style.css'>
</head>
<body>
<header>
<h3>Lets guess the secret number between 1 and 10</h3>
<h4>You have 5 chances to guess </h4>
</header>
<br/>
<br/>
<form class='form'>
<div class='secretno'>
<label for='secretno'>Please enter your guess for secret no (between 1 and 10):</label>
<input id='secretno' type='number' name='secretno' step='1' min='1' max='10' required>
<span class='validity'></span>
<input type='button' class='submitguess' value='submit'>
</div>
</form>
<br/>
<br/>
<div class='display'>
<p id='resultmatch'> </p>
<p id='highorlow'> </p>
<p id='guesslist'> </p>
</div>
Because I don't have enough contribution I have to write as an answer.
First is here
<input type='submit' class='submitguess'>
you should prevent the form to be executed and refresh so you have to add preventdefault. or simply change input submit to button type="button"
Second
const resetParas = document.querySelectorAll('.display p');
You should check this one. resetParas set but you check display length.
I am creating a quiz. My quiz is divided in 4 parts and I have 50 questions total. There is a score and question counter, but I want to continue the question counter and score when the quiz jumped to the next part and I need a total score at the end. I am not expert in Javascript. I am just a beginner. So Please help me with the solution.
const choices = Array.from(document.getElementsByClassName("choice-text"));
const progressText = document.getElementById("progressText");
const scoreText = document.getElementById("score");
const progressBarFull = document.getElementById("progressBarFull");
let currentQuestion = {};
let acceptingAnswers = false;
let score = 0;
let questionCounter = 0;
let availableQuesions = [];
let questions = [
{
question: "Inside which HTML element do we put the JavaScript??",
choice1: "<script>",
choice2: "<javascript>",
choice3: "<js>",
choice4: "<scripting>",
answer: 1
},
{
question:
"What is the correct syntax for referring to an external script called 'xxx.js'?",
choice1: "<script href='xxx.js'>",
choice2: "<script name='xxx.js'>",
choice3: "<script src='xxx.js'>",
choice4: "<script file='xxx.js'>",
answer: 3
},
{
question: " How do you write 'Hello World' in an alert box?",
choice1: "msgBox('Hello World');",
choice2: "alertBox('Hello World');",
choice3: "msg('Hello World');",
choice4: "alert('Hello World');",
answer: 4
}
];
//CONSTANTS
const CORRECT_BONUS = 10;
const MAX_QUESTIONS = 3;
startGame = () => {
questionCounter = 0;
score = 0;
availableQuesions = [...questions];
getNewQuestion();
};
getNewQuestion = () => {
if (availableQuesions.length === 0 || questionCounter >= MAX_QUESTIONS) {
localStorage.setItem("mostRecentScore", score);
//go to the end page
return window.location.assign("/end.html");
}
questionCounter++;
progressText.innerText = `Question ${questionCounter}/${MAX_QUESTIONS}`;
//Update the progress bar
progressBarFull.style.width = `${(questionCounter / MAX_QUESTIONS) * 100}%`;
const questionIndex = Math.floor(Math.random() * availableQuesions.length);
currentQuestion = availableQuesions[questionIndex];
question.innerText = currentQuestion.question;
choices.forEach(choice => {
const number = choice.dataset["number"];
choice.innerText = currentQuestion["choice" + number];
});
availableQuesions.splice(questionIndex, 1);
acceptingAnswers = true;
};
choices.forEach(choice => {
choice.addEventListener("click", e => {
if (!acceptingAnswers) return;
acceptingAnswers = false;
const selectedChoice = e.target;
const selectedAnswer = selectedChoice.dataset["number"];
const classToApply =
selectedAnswer == currentQuestion.answer ? "correct" : "incorrect";
if (classToApply === "correct") {
incrementScore(CORRECT_BONUS);
}
selectedChoice.parentElement.classList.add(classToApply);
setTimeout(() => {
selectedChoice.parentElement.classList.remove(classToApply);
getNewQuestion();
}, 1000);
});
});
incrementScore = num => {
score += num;
scoreText.innerText = score;
};
startGame();
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Quick Quiz - Play</title>
<link rel="stylesheet" href="app.css" />
<link rel="stylesheet" href="game.css" />
</head>
<body>
<div class="container">
<div id="game" class="justify-center flex-column">
<div id="hud">
<div id="hud-item">
<p id="progressText" class="hud-prefix">
Question
</p>
<div id="progressBar">
<div id="progressBarFull"></div>
</div>
</div>
<div id="hud-item">
<p class="hud-prefix">
Score
</p>
<h1 class="hud-main-text" id="score">
0
</h1>
</div>
</div>
<h2 id="question">What is the answer to this questions?</h2>
<div class="choice-container">
<p class="choice-prefix">A</p>
<p class="choice-text" data-number="1">Choice 1</p>
</div>
<div class="choice-container">
<p class="choice-prefix">B</p>
<p class="choice-text" data-number="2">Choice 2</p>
</div>
<div class="choice-container">
<p class="choice-prefix">C</p>
<p class="choice-text" data-number="3">Choice 3</p>
</div>
<div class="choice-container">
<p class="choice-prefix">D</p>
<p class="choice-text" data-number="4">Choice 4</p>
</div>
</div>
</div>
<script src="game.js"></script>
</body>
</html>
If your quiz contains or lasts throughout multiple pages and you want to communicate between those pages then you can use localStorage
When you're done with one part of the quiz, or even if you're not, just set the value of localStorage to the score, and read it on page load, or in general
incrementScore = num => {
if(typeof(localStorage.getItem("score") != "number"))
localStorage.setItem("score", 0)
score = localStorage.getItem("score")
score += num;
scoreText.innerText = score;
};
I am going through this JavaScript tutorial and ran into an issue that I hope someone can assist me with. After selecting the last question on the quiz, my showScore() function displays the results as "undefined". Through some further debugging, I found that it was a problem with my quiz object. In my PopulateQuestion() function, I am able to print out the quiz object before executing the showScore() function. However, when I attempt to print out the quiz object from within the showScore() function, it returns undefined.
I would like to work on my ability to debug issues that come up like this. Based on debugging that I have done so far, my educated guess is that this is a scope issue, but I am stuck. Does anyone have any suggestions for debugging this further?
Here is my code
Index.html
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>JS Quiz</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="main.css">
</head>
<body>
<div class="quiz-container">
<div id="quiz">
<h1>Star Wars Quiz</h1>
<hr style="margin-top: 20px;" />
<p id="question">Who is Darth Vader?</p>
<div class="buttons">
<button id="b0"><span id="c0"></span></button>
<button id="b1"><span id="c1"></span></button>
<button id="b2"><span id="c2"></span></button>
<button id="b3"><span id="c3"></span></button>
</div>
<hr style="margin-top: 50px" />
<footer>
<p id="progress">Question x of n</p>
</footer>
</div>
</div>
<script src="quiz-controller.js"></script>
<script src="question.js"></script>
<script src="app.js"></script>
</body>
</html>
app.js
function populateQuestion() {
if(quiz.isEnded()) {
// display score
console.log(quiz);
showScore();
} else {
// display question
var qElement = document.getElementById('question');
qElement.innerHTML = quiz.getCurrentQuestion().text;
// display choices
var choices = quiz.getCurrentQuestion().choices;
for(var i = 0; i < choices.length; i++) {
var choice = document.getElementById('c' + i);
choice.innerHTML = choices[i];
guess("b" + i, choices[i]);
}
showProgress();
}
}
function guess(id, guess) {
var button = document.getElementById(id);
button.onclick = function() {
quiz.guess(guess);
populateQuestion();
};
}
function showProgress() {
var currentQuestionNum = quiz.questionIndex + 1;
var progress = document.getElementById("progress");
progress.innerHTML = "Question " + currentQuestionNum + " of " + quiz.questions.length;
}
function showScore() {
console.log(quiz);
var resultsHTML = "<h1>Results</h1>";
resultsHTML += "<h2 id='score'>Your Score: " + quiz.getScore() + "</h2>";
var quiz = document.getElementById("quiz");
quiz.innerHTML = resultsHTML;
}
var questions = [
new Question("Who is Darth Vader?",
["Luke Skywalker", "Anakin Skywalker", "Your Mom", "Your Dad"],
"Anakin Skywalker"),
new Question("What is the name of the third episode?",
["Return of the Jedi", "Revenge of the Sith", "A New Hope", "The Empire Strikes Back"],
"Revenge of the Sith"),
new Question("Who is Anakin Skywalker's son?",
["Luke Skywalker", "Anakin Skywalker", "Your Mom", "Your Dad"],
"Luke Skywalker"),
new Question("What is the name of the sixth episode?",
["Return of the Jedi", "Revenge of the Sith", "A New Hope", "The Empire Strikes Back"],
"Return of the Jedi")
];
var quiz = new Quiz(questions);
populateQuestion();
question.js
function Question(text, choices, answer) {
this.text = text;
this.choices = choices;
this.answer = answer;
}
Question.prototype.correctAnswer = function(choice) {
return choice === this.answer;
};
quiz-controller.js
function Quiz(questions) {
this.score = 0;
this.questionIndex = 0;
this.questions = questions;
}
Quiz.prototype.getScore = function() {
return this.score;
};
Quiz.prototype.getCurrentQuestion = function() {
return this.questions[this.questionIndex];
};
Quiz.prototype.isEnded = function() {
return this.questionIndex === this.questions.length;
};
Quiz.prototype.guess = function(answer) {
if(this.getCurrentQuestion().correctAnswer(answer)) {
this.score++;
}
this.questionIndex++;
};
Your problem is that in the showScore() function you define a local variable with the name quiz. This local variable hides the global variable with the same name (even though it is defined later in the code).
You can easily fix that by renaming your local variable in showScore (below shown as q instead of quiz):
function populateQuestion() {
if(quiz.isEnded()) {
// display score
console.log(quiz);
showScore();
} else {
// display question
var qElement = document.getElementById('question');
qElement.innerHTML = quiz.getCurrentQuestion().text;
// display choices
var choices = quiz.getCurrentQuestion().choices;
for(var i = 0; i < choices.length; i++) {
var choice = document.getElementById('c' + i);
choice.innerHTML = choices[i];
guess("b" + i, choices[i]);
}
showProgress();
}
}
function guess(id, guess) {
var button = document.getElementById(id);
button.onclick = function() {
quiz.guess(guess);
populateQuestion();
};
}
function showProgress() {
var currentQuestionNum = quiz.questionIndex + 1;
var progress = document.getElementById("progress");
progress.innerHTML = "Question " + currentQuestionNum + " of " + quiz.questions.length;
}
function showScore() {
console.log(quiz);
var resultsHTML = "<h1>Results</h1>";
resultsHTML += "<h2 id='score'>Your Score: " + quiz.getScore() + "</h2>";
var q = document.getElementById("quiz");
q.innerHTML = resultsHTML;
}
var questions = [
new Question("Who is Darth Vader?",
["Luke Skywalker", "Anakin Skywalker", "Your Mom", "Your Dad"],
"Anakin Skywalker"),
new Question("What is the name of the third episode?",
["Return of the Jedi", "Revenge of the Sith", "A New Hope", "The Empire Strikes Back"],
"Revenge of the Sith"),
new Question("Who is Anakin Skywalker's son?",
["Luke Skywalker", "Anakin Skywalker", "Your Mom", "Your Dad"],
"Luke Skywalker"),
new Question("What is the name of the sixth episode?",
["Return of the Jedi", "Revenge of the Sith", "A New Hope", "The Empire Strikes Back"],
"Return of the Jedi")
];
function Question(text, choices, answer) {
this.text = text;
this.choices = choices;
this.answer = answer;
}
Question.prototype.correctAnswer = function(choice) {
return choice === this.answer;
};
function Quiz(questions) {
this.score = 0;
this.questionIndex = 0;
this.questions = questions;
}
Quiz.prototype.getScore = function() {
return this.score;
};
Quiz.prototype.getCurrentQuestion = function() {
return this.questions[this.questionIndex];
};
Quiz.prototype.isEnded = function() {
return this.questionIndex === this.questions.length;
};
Quiz.prototype.guess = function(answer) {
if(this.getCurrentQuestion().correctAnswer(answer)) {
this.score++;
}
this.questionIndex++;
};
var quiz = new Quiz(questions);
populateQuestion();
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>JS Quiz</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="main.css">
</head>
<body>
<div class="quiz-container">
<div id="quiz">
<h1>Star Wars Quiz</h1>
<hr style="margin-top: 20px;" />
<p id="question">Who is Darth Vader?</p>
<div class="buttons">
<button id="b0"><span id="c0"></span></button>
<button id="b1"><span id="c1"></span></button>
<button id="b2"><span id="c2"></span></button>
<button id="b3"><span id="c3"></span></button>
</div>
<hr style="margin-top: 50px" />
<footer>
<p id="progress">Question x of n</p>
</footer>
</div>
</div>
<script src="quiz-controller.js"></script>
<script src="question.js"></script>
<script src="app.js"></script>
</body>
</html>
There is private variable quiz in showScore
function which is getting hoisted to the top of the
function as follows:
Your code:
function showScore() {
console.log(quiz);
var resultsHTML = "<h1>Results</h1>";
resultsHTML += "<h2 id='score'>Your Score: " + quiz.getScore() + "</h2>";
var quiz = document.getElementById("quiz");
What internally happens:
function showScore() {
var quiz = undefined; // hoisting is happening here. So quiz is not reffering to public quiz variable anymore.
console.log(quiz);
var resultsHTML = "<h1>Results</h1>";
resultsHTML += "<h2 id='score'>Your Score: " + quiz.getScore() + "</h2>";
var quiz = document.getElementById("quiz");
I am new to the programming world and have been working on a trivia-game style project. The problem I am encountering is as follows: "Uncaught ReferenceError: answer is not defined at HTMLButtonElement.button.onclick".
My question is as follows: How are my question answers not being stored when pressing an answer and what is a better way to define answer in my code? Any help would greatly be appreciated.
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Trivia Game</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.2/css/bootstrap.min.css" />
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo"
crossorigin="anonymous"></script>
<link href="https://fonts.googleapis.com/css?family=Lora" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="assets/css/style.css" />
</head>
<body>
<div class="grid">
<div id="trivia">
<h1>A Golfer's Trivia</h1>
<!-- for question -->
<div id="questionName">
<p id="question"></p>
</div>
<p id="progress"></p>
<!-- options for the questions -->
<div class="buttons">
<button id="btn0"><span id="option0"></span></button>
<button id="btn1"><span id="option1"></span></button>
<button id="btn2"><span id="option2"></span></button>
<button id="btn3"><span id="option3"></span></button>
</div>
<div>
<p id="timer"></p>
<p id="show-clock"></p>
</div>
</div>
</div>
<script type="text/javascript" src="assets/javascript/game.js"></script>
</body>
</html>``
JAVASCRIPT
// Keeping score
var unanswered = 0;
var questionIndex = 0;
var score = 0;
var questions = 0;
var answer;
function Quiz(questions) {
this.score = 0;
this.questions = questions;
this.questionIndex = 0;
}
function getQuestionIndex() {
return this.questions[this.questionIndex];
}
function endGame() {
return this.questions.length === this.questionIndex;
}
function guess(answer) {
if (this.getQuestionIndex() === correctAnswer(answer)) {
this.score++;
}
this.questionIndex++;
}
// functions for questions
function Question(text, choices, answer) {
this.text = text;
this.choices = choices;
this.answer = answer;
}
// check user answer
function correctAnswer(choice) {
return choice === this.answer;
}
// have questions appear if game is still going
function populate() {
console.log("populating");
if (endGame()) {
showScores();
}
else {
var element = document.getElementById("question");
element.innerHTML = getQuestionIndex().text;
// have options appear for each question
var choices = getQuestionIndex().choices;
for (var i = 0; i < choices.length; i++) {
var element = document.getElementById("option" + i);
element.innerHTML = choices[i];
guess("btn" + i, choices[i]);
}
showProgress()
}
}
// store user guess
function guess(id) {
var button = document.getElementById(id);
button.onclick = function () {
questionIndex++;
populate();
guess(answer);
}
}
// show which question player is on
function showProgress() {
var currentQuestionNumber = questionIndex + 1;
var element = document.getElementById("progress");
element.innerHTML = "Question " + currentQuestionNumber + " of " + questions.length;
}
// display scores at end of game
function showScores() {
var gameOver = "<h1>Results</h1>" + "<h2 class='corr score'> Correct Answers: " + score + "<h2>" + "<br>" + "<h2 class = 'wrong score'>Wrong Answers: " + (questions.length - score) + "<h2 class = 'unanswered score'>Unanswered: " + "<h2>";
var results = document.getElementById("trivia");
results.innerHTML = gameOver;
}
// sets of questions, options, answers
var questions = [
new Question("Where was the game of golf originally founded?",
["Scotland", "China", "England", "United States"],
"Scotland"),
new Question("Who is the only female golfer to make a cut at a PGA Tour event?",
["Michelle Wie", "Annika Sorensteim", "Lexi Thompson", "Babe Zaharias"],
"Babe Zaharias"),
new Question("What is the name for a hole-in-one on a par five?",
["Triple Eagle", "Double Ace", "Condor", "Albatross"],
"Condor"),
new Question("Who holds the record for the most PGA Tour victories?",
["Tiger Woods", "Jack Nicklaus", "Ben Hogan", "Sam Snead"],
"Sam Snead"),
new Question("What percentage of golfers will never achieve a handicap of 18 or less?",
["50 percent", "73 percent", "80 percent", "91 percent"],
"80 percent"),
new Question("How many dimples are on a standard regulation golf ball?",
["336", "402", "196", "468"],
"336"),
new Question("Who was considered the first professional golfer in history?",
["Bobby Jones", "Byron Nelson", "Walter Hagen", "Old Tom Morris"],
"Walter Hagen"),
new Question("Who is the youngest player to win the Masters?",
["Tiger Woods", "Jack Nicklaus", "Jordan Speith", "Arnold Palmer"],
"Tiger Woods")
];
populate();
var intervalId;
$("#btn").on("click", run);
// The run function sets an interval
function run() {
clearInterval(intervalId);
}
var timeLeft = 10;
var displayClock = document.getElementById('timer');
var timerId = setInterval(countdown, 1000);
function countdown() {
if (timeLeft === 0) {
unanswered++;
questionIndex++;
populate();
alert("You did not answer in time!");
timeLeft = 10;
// reset timer, pull question
run();
} else {
displayClock.innerHTML = timeLeft + ' seconds remaining';
timeLeft--;
}
}
run();
I guess you're facing another problem here. Here are 2 functions taken off your script:
guess(any) version 1
function guess(answer) {
if (this.getQuestionIndex() === correctAnswer(answer)) {
this.score++;
}
this.questionIndex++;
}
guess(any)version 2
function guess(id) {
var button = document.getElementById(id);
button.onclick = function () {
questionIndex++;
populate();
guess(answer);
}
}
You have 2 of a function named guess(). Although the names of both values vary, from Javascript's standpoint they both look like this:
function guess(value){}
How is JS supposed to know which of them you intend to call?
Rename at least one of them in order to having total unambiguousness among your function names. And try again.