I am developing a simple quiz using Javascript, HTML5 and CSS3.
Currently, when a user selects an answer, it proceeds to the next question regardless of whether the answer is correct or not.
I want to enable multiple attempts for the users. If the user selects the wrong option, that option will be marked red while giving the user another chance to select another option (like elimination process). The next question will only be shown until the user selects the correct answer.
Here are my codes:
game.js
const question = document.querySelector('#question'); //can target both the class and the ID
const choices = Array.from(document.querySelectorAll('.choice-text'));
const scoreText = document.querySelector('#score');
let currentQuestion = {}
let acceptingAnswers = true
let score = 0
let questionCounter = 0
let availableQuestions = []
let questions = [
{
question: 'What is 2 + 2?',
choice1: '5',
choice2: '10',
choice3: '1',
choice4: '4',
answer: 4
},
{
question: 'When is Christmas?',
choice1: '25 December',
choice2: '1 January',
choice3: '4 July',
choice4: '30 October',
answer: 1
},
{
question: 'What is the capital of Japan?',
choice1: 'Seoul',
choice2: 'Beijing',
choice3: 'Tokyo',
choice4: 'Washington D.C.',
answer: 3
},
{
question: 'What is the emergency number?',
choice1: '123',
choice2: '555',
choice3: '420',
choice4: '911',
answer: 4
}
]
const SCORE_POINTS = 10
const MAX_QUESTIONS = 4
startGame = () =>{
questionCounter = 0
score = 0
availableQuestions = [...questions]
getNewQuestion()
}
getNewQuestion = () => {
if(availableQuestions.length === 0 || questionCounter > MAX_QUESTIONS) {
localStorage.setItem('mostRecentScore', score)
return window.location.assign('end.html')
}
questionCounter++
const questionsIndex = Math.floor(Math.random() * availableQuestions.length)
currentQuestion = availableQuestions[questionsIndex]
question.innerText = currentQuestion.question
choices.forEach(choice => {
const number = choice.dataset['number']
choice.innerText= currentQuestion['choice' + number]
})
availableQuestions.splice(questionsIndex, 1)
acceptingAnswers = true
}
choices.forEach(choice => {
choice.addEventListener('click', e => {
if(!acceptingAnswers) return
acceptingAnswers = false
const selectedChoice = e.target
const selectedAnswer = selectedChoice.dataset['number']
let classToApply = selectedAnswer == currentQuestion.answer ? 'correct' : 'incorrect'
if(classToApply === 'correct') {
incrementScore(SCORE_POINTS)
}
selectedChoice.parentElement.classList.add(classToApply)
setTimeout(() => {
selectedChoice.parentElement.classList.remove(classToApply)
getNewQuestion()
}, 500)
})
})
incrementScore = num => {
score += num
scoreText.innerText = score
}
startGame()
game.html
<!DOCTYPE html>
<html>
<head>
<title>Trivia Quiz</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="style.css" rel="stylesheet">
<link href="game.css" rel="stylesheet">
</head>
<body>
<div class="container">
<div id="game" class="justify-center flex-column">
<div id="hud">
<div class="hud-item">
<p id="gameTitle" class="hud-prefix">
Trivia Quiz
</p>
<p id="quizMode" class="hud-prefix2">
<br>Normal Mode
</p>
</div>
<div class="hud-item">
<p id= "gamePoints" class="hud-prefix">
Points
</p>
<h1 class="hud-main-text" id="score">
0
</h1>
</div>
</div>
<h1 id="question">What is the answer?</h1>
<div class="choice-container">
<p class="choice-text" data-number="1">A</p>
</div>
<div class="choice-container">
<p class="choice-text" data-number="2">B</p>
</div>
<div class="choice-container">
<p class="choice-text" data-number="3">C</p>
</div>
<div class="choice-container">
<p class="choice-text" data-number="4">D</p>
</div>
</div>
</div>
<script src="game.js"></script>
</body>
</html>
Try this
const question = document.querySelector('#question'); //can target both the class and the ID
const choices = Array.from(document.querySelectorAll('.choice-text'));
const scoreText = document.querySelector('#score');
let currentQuestion = {}
let acceptingAnswers = true
let score = 0
let questionCounter = 0
let availableQuestions = []
let questions = [
{
question: 'What is 2 + 2?',
choice1: '5',
choice2: '10',
choice3: '1',
choice4: '4',
answer: 4
},
{
question: 'When is Christmas?',
choice1: '25 December',
choice2: '1 January',
choice3: '4 July',
choice4: '30 October',
answer: 1
},
{
question: 'What is the capital of Japan?',
choice1: 'Seoul',
choice2: 'Beijing',
choice3: 'Tokyo',
choice4: 'Washington D.C.',
answer: 3
},
{
question: 'What is the emergency number?',
choice1: '123',
choice2: '555',
choice3: '420',
choice4: '911',
answer: 4
}
]
const SCORE_POINTS = 10
const MAX_QUESTIONS = 4
startGame = () =>{
questionCounter = 0
score = 0
availableQuestions = [...questions]
getNewQuestion()
}
getNewQuestion = () => {
if(availableQuestions.length === 0 || questionCounter > MAX_QUESTIONS) {
localStorage.setItem('mostRecentScore', score)
return window.location.assign('end.html')
}
let container = document.getElementsByClassName('choice-container');
for(var i = 0; i < container.length; i++)
{
container[i].classList.remove('error', 'incorrect', 'correct');
}
questionCounter++
const questionsIndex = Math.floor(Math.random() * availableQuestions.length)
currentQuestion = availableQuestions[questionsIndex]
question.innerText = currentQuestion.question
choices.forEach(choice => {
const number = choice.dataset['number']
choice.innerText= currentQuestion['choice' + number]
})
availableQuestions.splice(questionsIndex, 1)
acceptingAnswers = true
}
for (i = 0; i < choices.length; i++) {
choices[i].addEventListener('click', e => {
// if(!acceptingAnswers) return
acceptingAnswers = false
const selectedChoice = e.target
const selectedAnswer = selectedChoice.dataset['number']
let classToApply = selectedAnswer == currentQuestion.answer ? 'correct' : 'incorrect'
if(classToApply === 'correct') {
incrementScore(SCORE_POINTS)
setTimeout(() => {
selectedChoice.parentElement.classList.remove(classToApply)
getNewQuestion()
}, 500)
} else {
selectedChoice.parentElement.classList.add("error")
}
selectedChoice.parentElement.classList.add(classToApply)
})
}
incrementScore = num => {
score += num
scoreText.innerText = score
}
startGame()
.error {
color: red;
}
<!DOCTYPE html>
<html>
<head>
<title>Trivia Quiz</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="style.css" rel="stylesheet">
<link href="game.css" rel="stylesheet">
</head>
<body>
<div class="container">
<div id="game" class="justify-center flex-column">
<div id="hud">
<div class="hud-item">
<p id="gameTitle" class="hud-prefix">
Trivia Quiz
</p>
<p id="quizMode" class="hud-prefix2">
<br>Normal Mode
</p>
</div>
<div class="hud-item">
<p id= "gamePoints" class="hud-prefix">
Points
</p>
<h1 class="hud-main-text" id="score">
0
</h1>
</div>
</div>
<h1 id="question">What is the answer?</h1>
<div class="choice-container">
<p class="choice-text" data-number="1">A</p>
</div>
<div class="choice-container">
<p class="choice-text" data-number="2">B</p>
</div>
<div class="choice-container">
<p class="choice-text" data-number="3">C</p>
</div>
<div class="choice-container">
<p class="choice-text" data-number="4">D</p>
</div>
</div>
</div>
<script src="game.js"></script>
</body>
</html>
Related
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>
I am doing a quiz that consists of 3 questions and each question has 3 options. Only one question is displayed on the screen at a time. For answer a the value is 2 points, for answer b the value is 1 point and for answer c the value is 0 points. I try to make a summation of each question so that at the end a message with the final score is displayed, but I'm stuck. Here my code so far.
Thank you in advance!
const qData = [
{
question: "Question1",
a: "Yes",
b: "No",
c: "Maybe",
},
{
question: "Question2",
a: "Always",
b: "Sometimes",
c: "Never",
},
{
question: "Question3",
a: "100%",
b: "50%",
c: "0%",
}
]
const questionE1 = document.getElementById("question");
const a_text = document.getElementById("a-text");
const b_text = document.getElementById("b-text");
const c_text = document.getElementById("c-text");
const submitBtn = document.getElementById("siguiente")
let currentQuiz = 0;
loadQuiz();
function loadQuiz() {
const currentQuizData = qData[currentQuiz];
questionE1.innerText = currentQuizData.question;
a_text.innerText = currentQuizData.a;
b_text.innerText = currentQuizData.b;
c_text.innerText = currentQuizData.c;
}
submitBtn.addEventListener("click", () => {
currentQuiz++;
});
const numericalValues = new Array();
numericalValues["a"]= 2;
numericalValues["b"]= 1;
numericalValues["c"]= 0;
function getscore() {
var puntos = 0;
var answer = document.getElementById("answer");
for(var i=0; i<answer.length; i++)
{
if(answer[i]) {
puntos = numericalValues[answer[i].value];
}
}
return puntos;
};
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Quiz</title>
<link rel="stylesheet" href="style.css">
<script src="./script.js" defer></script>
</head>
<body>
<h1>Quiz</h1>
<div class="container">
<div class="score">
<h2 id="question">Question text</h2>
<ul>
<li><input type="radio" id="a" name="answer" class="answer"><label id="a-text" for="a">Question</label></li>
<li><input type="radio" id="b" name="answer" class="answer"><label id="b-text" for="b">Question</label></li>
<li><input type="radio" id="c" name="answer" class="answer"><label id="c-text" for="c">Question</label></li>
</ul>
<button id="siguiente">Next</button>
</div>
</div>
<p id="result">Final Score</p>
</body>
</html>
I've rebuild your structure of data by adding answer property to each object, otherwise there"s no way to know if the user answers the right answer!
Also checked if the user choose an answer before move to the next!
const qData = [
{
question: "Question1",
a: "Yes",
b: "No",
c: "Maybe",
answer: "a",
},
{
question: "Question2",
a: "Always",
b: "Sometimes",
c: "Never",
answer: "b",
},
{
question: "Question3",
a: "100%",
b: "50%",
c: "0%",
answer: "c",
},
];
let currInd = -1;
let rightAnswers = 0;
function renderQuestion() {
++currInd;
if (currInd != qData.length) {
const question = document.getElementById("question");
question.innerText = qData[currInd].question;
const { a, b, c } = qData[currInd];
document.getElementById("a-text").innerText = a;
document.getElementById("b-text").innerText = b;
document.getElementById("c-text").innerText = c;
} else {
document.getElementById(
"result"
).innerText = `You got ${rightAnswers} right answers, and you lost ${
qData.length - rightAnswers
} questions`;
document.querySelector(".container").style.display = "none";
document.querySelector(".result").style.display = "block";
}
}
//render first question:
renderQuestion();
document.getElementById("nextBtn").addEventListener("click", nextQuestion);
function nextQuestion() {
let options = [...document.querySelectorAll(".answer")];
let gaveAnswer =
options.map((option) => option.checked).filter(Boolean).length == 1;
let answerMapping = {
0: "a",
1: "b",
2: "c",
};
//check the answer before move to the next question
if (gaveAnswer) {
let answerInd = options
.map((option) => option.checked)
.map(Number)
.findIndex((ind) => ind == 1);
let isRightAnswer = answerMapping[answerInd] == qData[currInd].answer;
rightAnswers += isRightAnswer;
renderQuestion();
//empty the current checked option
options.forEach((option) => {
option.checked = false;
});
} else {
alert("choose an answer");
}
}
.result {
display: none;
}
<h1>Quiz</h1>
<div class="container">
<div class="score">
<h2 id="question"></h2>
<ul id="options">
<li>
<input type="radio" id="a" name="answer" class="answer" /><label
id="a-text"
for="a"
></label>
</li>
<li>
<input type="radio" id="b" name="answer" class="answer" /><label
id="b-text"
for="b"
></label>
</li>
<li>
<input type="radio" id="c" name="answer" class="answer" /><label
id="c-text"
for="c"
></label>
</li>
</ul>
<button id="nextBtn">Next</button>
</div>
</div>
<p class="result">Final Score: <span id="result"></span></p>
If you don't understand something comment it below, I'll explain to you!
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 created an array of objects with different properties but I am having problem displaying each properties of my object on the webpage. I have tried but I don't know where the problem is.
I have tried to access the objects individually but still not working please check the problem
//Get the id's of all elements
const intro = document.getElementById("introduction");
const continued = document.getElementById("continue");
const name = document.getElementById("name").value;
const wel = document.getElementById("wel")
const startt = document.getElementById("startt");
const start = document.getElementById("start");
const quiz = document.getElementById("quiz");
const question = document.getElementById("question");
const qImg = document.getElementById("qImg");
const choiceA = document.getElementById("A");
const choiceB = document.getElementById("B");
const choiceC = document.getElementById("C");
const choiceD = document.getElementById("D");
const counter = document.getElementById("counter");
const timeGauge = document.getElementById("timeGauge");
const progress = document.getElementById("progress");
const scoreDiv = document.getElementById("scoreContainer");
//Event listeners
continued.addEventListener('click', continueAfterIntro);
start.addEventListener('click', startQuiz);
//variable declarations
const lastQuestion = questions.length - 1;
var runningQuestion = 0;
var secs = 0;
var mins = 0;
var hrs = 0;
const questionTime = 60; // 60s
const gaugeWidth = 180; // 180px
const gaugeUnit = gaugeWidth / questionTime;
let TIMER;
let score = 0;
//Array object declaration
let questions = [{
question: "Who is the president Nigeria?",
choiceA: "Muhamadu Buhari",
choiceB: "Osibajo",
choiceC: "Obasanjo",
choiceD: "Green,Red,Green",
correct: "A"
}, {
question: "Who is the governor of oyo state?",
choiceA: "Abiola Ajumobi",
choiceB: "Seyi makinde",
choiceC: "Alao Akala",
choiceD: "Green,Red,Green",
correct: "B"
}, {
question: "What are the colors of the Nigerian Flag?",
choiceA: "Green,White,Blue",
choiceB: "Blue,White,Green",
choiceC: "Green,White,Green",
choiceD: "Green,Red,Green",
correct: "C"
}];
function continueAfterIntro() {
intro.style.display = 'none';
startt.style.display = 'block';
wel.innerHTML = `Hi ${name}`;
}
function renderQuestion() {
let q = questions[runningQuestion];
question.innerHTML = "<p>" + q.question + "</p>";
choiceA.innerHTML = q.choiceA;
choiceB.innerHTML = q.choiceB;
choiceC.innerHTML = q.choiceC;
}
function startQuiz() {
startt.style.display = "none";
quiz.style.display = "block";
renderQuestion();
}
<div id="container">
<div class="" id="introduction">
<div id="pimg"><img src="pic/thumbs.png" alt="WELCOME FACE"></div>
<div id="para1">
<p>Hey there i'm AFO by name whats yours</p>
</div>
<div id="name-button">
<span id="iName"><input type="text" id="name" placeholder="Type Your Name Here"></span>
<span id="continue"><input type="button" value="Continue" id="continue"></span>
</div>
</div>
<div id="startt" style="display: none">
<p id="wel"></p>
<div id="start">Start Quiz!</div>
</div>
<div id="quiz" style="display: none">
<div id="question"></div>
<div id="choices">
A.
<div class="choice" id="A" onclick="checkAnswer('A')"></div>
B.
<div class="choice" id="B" onclick="checkAnswer('B')"></div>
C.
<div class="choice" id="C" onclick="checkAnswer('C')"></div>
D.
<div class="choice" id="D" onclick="checkAnswer('D')"></div>
</div>
<div id="timer">
<div id="counter"></div>
<div id="btimeGauge"></div>
<div id="timeGauge"></div>
</div>
<div id="progress"></div>
</div>
<div id="scoreContainer" style="display: none"></div>
</div>
The function renderQuestion should display the questions and the choices on the webpage
When i run your project i got ReferenceError.
Uncaught ReferenceError: Cannot access 'questions' before initialization
That means you can't play around with Questions Array before initialization. For example:
const questionsLength = questions.length; // REFERENCE ERROR.
const questions = ['a', 'b', 'c'];
console.log(questionsLength);
Declare Questions Array before you inspect length:
const questions = ['a', 'b', 'c'];
const questionsLength = questions.length;
console.log(questionsLenght) // Returns 3
Working example:
//Get the id's of all elements
const intro = document.getElementById("introduction");
const continued = document.getElementById("continue");
const name = document.getElementById("name").value;
const wel = document.getElementById("wel")
const startt = document.getElementById("startt");
const start = document.getElementById("start");
const quiz = document.getElementById("quiz");
const question = document.getElementById("question");
const qImg = document.getElementById("qImg");
const choiceA = document.getElementById("A");
const choiceB = document.getElementById("B");
const choiceC = document.getElementById("C");
const choiceD = document.getElementById("D");
const counter = document.getElementById("counter");
const timeGauge = document.getElementById("timeGauge");
const progress = document.getElementById("progress");
const scoreDiv = document.getElementById("scoreContainer");
//Event listeners
continued.addEventListener('click',continueAfterIntro);
start.addEventListener('click',startQuiz);
//Array object declaration
let questions = [
{
question : "Who is the president Nigeria?",
choiceA : "Muhamadu Buhari",
choiceB : "Osibajo",
choiceC : "Obasanjo",
choiceD : "Green,Red,Green",
correct : "A"
},{
question : "Who is the governor of oyo state?",
choiceA : "Abiola Ajumobi",
choiceB : "Seyi makinde",
choiceC : "Alao Akala",
choiceD : "Green,Red,Green",
correct : "B"
},{
question : "What are the colors of the Nigerian Flag?",
choiceA : "Green,White,Blue",
choiceB : "Blue,White,Green",
choiceC : "Green,White,Green",
choiceD : "Green,Red,Green",
correct : "C"
}
];
//variable declarations
const lastQuestion = questions.length - 1;
var runningQuestion = 0;
var secs = 0;
var mins = 0;
var hrs = 0;
const questionTime = 60; // 60s
const gaugeWidth = 180; // 180px
const gaugeUnit = gaugeWidth / questionTime;
let TIMER;
let score = 0;
function continueAfterIntro(){
intro.style.display = 'none';
startt.style.display = 'block';
wel.innerHTML = `Hi ${name}`;
}
function renderQuestion(){
let q = questions[runningQuestion];
question.innerHTML = "<p>"+ q.question +"</p>";
choiceA.innerHTML = q.choiceA;
choiceB.innerHTML = q.choiceB;
choiceC.innerHTML = q.choiceC;
}
function startQuiz(){
startt.style.display = "none";
quiz.style.display = "block";
renderQuestion();
}
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="quiz.css">
<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>Document</title>
</head>
<body>
<div id="container">
<div class="" id="introduction">
<div id="pimg"><img src="pic/thumbs.png" alt="WELCOME FACE"></div>
<div id="para1"><p>Hey there i'm AFO by name whats yours</p> </div>
<div id="name-button">
<span id="iName"><input type="text" id="name" placeholder="Type Your Name Here"></span>
<span id="continue"><input type="button" value="Continue" id="continue"></span>
</div>
</div>
<div id="startt" style="display: none">
<p id="wel"></p>
<div id="start" >Start Quiz!</div>
</div>
<div id="quiz" style="display: none">
<div id="question"></div>
<div id="choices">
A.<div class="choice" id="A" onclick="checkAnswer('A')"></div>
B.<div class="choice" id="B" onclick="checkAnswer('B')"></div>
C.<div class="choice" id="C" onclick="checkAnswer('C')"></div>
D.<div class="choice" id="D" onclick="checkAnswer('D')"></div>
</div>
<div id="timer">
<div id="counter"></div>
<div id="btimeGauge"></div>
<div id="timeGauge"></div>
</div>
<div id="progress"></div>
</div>
<div id="scoreContainer" style="display: none"></div>
</div>
</body>
</html>
What ReferenceError mean MDN#ReferenceError
I am trying to calculate the sum of a dynamic div for different categories, and then place that value in a div. What I don't understand, is how to figure out the total based on different categories. Here is a screencast of what I am talking about https://www.screencast.com/t/js8LBNfXo9sa. Here is also a link to my code pen which houses my code https://codepen.io/nfinsand/project/full/ZLNEon/.
var addListItem = document.getElementById("add-more");
addListItem.addEventListener("click", function() {
createNewItem();
});
//Display Month and Day
var today = new Date();
var dd = today.getDate();
var mm = today.getMonth() + 1;
today = mm + "/" + dd;
document.getElementById("current-date").innerHTML = today;
//Creates new elements
function createNewItem() {
var u = document.getElementById("full-item-list");
var l = document.createElement("li");
var elinput = document.createElement('input');
var expenseName = document.createElement('input');
var icon = document.createElement('img');
var optionsArray = [{
'itemText': 'Category',
'itemDisabled': true,
'itemSelected': true
},
'Auto & Transport',
'Health & Fitness',
'Home',
'Personal Care',
'Pets',
'Shopping',
'Entertainment',
'Investments'
];
var selectElem = document.createElement('select');
selectElem.setAttribute('name', 'selectThis');
// iterate through the array of options
optionsArray.forEach(function(item) {
var text = (typeof(item) === 'string') ? item : item.itemText;
var option = document.createElement('option');
var optionText = document.createTextNode(text);
option.appendChild(optionText);
if (typeof(item) === 'object') {
// handle custom attributes
Object.keys(item).forEach(function(key) {
switch (key) {
case 'itemDisabled':
if (item[key]) {
option.setAttribute('disabled', true);
}
break;
case 'itemSelected':
if (item[key]) {
option.setAttribute('selected', true);
}
break;
default:
break;
}
});
}
selectElem.appendChild(option);
});
expenseName.setAttribute('type', 'text');
expenseName.setAttribute('placeholder', 'Expense name');
expenseName.setAttribute('class', 'expense-input-name')
expenseName.setAttribute('name', 'totalExpense');
elinput.setAttribute('type', 'number');
elinput.setAttribute('class', 'li-input');
elinput.setAttribute('placeholder', 'Enter amount');
elinput.setAttribute('name', 'qty');
l.setAttribute('class', 'list-item');
l.setAttribute('name', 'li-name');
icon.setAttribute('class', 'remove-icon');
icon.setAttribute('src', 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/375261/System_Delete.ico');
icon.setAttribute("id", "icon-id");
icon.addEventListener('click', function(e) {
thaticon(e);
}, false);
l.appendChild(selectElem);
l.appendChild(expenseName);
l.appendChild(elinput);
l.appendChild(icon);
u.appendChild(l);
}
//Deletes elements
function thaticon(e) {
console.log("test");
var el = e.target;
var elListItem = el.parentNode;
elFullList = elListItem.parentNode;
elFullList.removeChild(elListItem);
}
//Calculates and displays results
function displayResult() {
var arr = document.getElementsByName("qty");
var wage = document.getElementById("inputWage").value;
var jumboDiv = document.getElementById("jumbo-results").style.display = "block";
var tot = 0;
for (var i = 0; i < arr.length; i++) {
if (parseFloat(arr[i].value)) tot += parseFloat(arr[i].value);
}
document.getElementById("result").innerHTML = "Total Expenses: $" + tot.toFixed(2);
document.getElementById("left").innerHTML = "Left Over: $" + ((wage - tot).toFixed(2));
}
//Resets and clears entire entry
function resetForm() {
var jumboDiv = document.getElementById("jumbo-results").style.display = "none";
document.getElementById("full-item-list").innerHTML = "";
document.getElementById("inputWage").value = "";
document.getElementById("result").innerHTML = "";
document.getElementById("left").innerHTML = "";
document.getElementById("number-display").innerHTML = "";
}
//Displays the selected categories by user with the total sum for each one
function displayCategory() {
}
//Capture screen shots
/*function captureScreen() {
html2canvas(document.querySelector("#capture")).then(canvas => {
document.body.appendChild(canvas)
});
}*/
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Expense Tracker</title>
<link rel="stylesheet" href="css/style.css">
<link rel='stylesheet prefetch' href='https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.1/css/bootstrap.css'>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<link href="https://fonts.googleapis.com/css?family=Raleway:300" rel="stylesheet">
</head>
<body>
<div id="capture" class="container-fluid">
<div class="centerDiv">
<p class="mainHeading">Expense Calculator</p>
<p id="current-date"></p>
<div class="jumbotron jumbo2">
<h4>Categories</h4>
<div id="category-display"><br>
<div class="flex-container">
<div id="color-1"></div>
<div class="categoryItem">Auto & Transport</div>
<div class="well">$0.00</div>
</div>
<div class="flex-container">
<div id="color-2"></div>
<div class="categoryItem">Health & Fitness</div>
<div class="well">$0.00</div>
</div>
<div class="flex-container">
<div id="color-3"></div>
<div class="categoryItem">Home</div>
<div class="well">$0.00</div>
</div>
<div class="flex-container">
<div id="color-4"></div>
<div class="categoryItem">Personal Care</div>
<div class="well">$0.00</div>
</div>
<div class="flex-container">
<div id="color-5"></div>
<div class="categoryItem">Pets</div>
<div class="well">$0.00</div>
</div>
<div class="flex-container">
<div id="color-6"></div>
<div class="categoryItem">Shopping</div>
<div class="well">$0.00</div>
</div>
<div class="flex-container">
<div id="color-7"></div>
<div class="categoryItem">Entertainment</div>
<div class="well">$0.00</div>
</div>
<div class="flex-container">
<div id="color-8"></div>
<div class="categoryItem">Investments</div>
<div class="well">$0.00</div>
</div>
</div>
</div>
<div class="jumbotron">
<label class="expenseLabel">Income:</label><br>
<input id="inputWage" type="number" placeholder="Paycheck Amount"><br><br><br>
<label>Expenses:</label>
<ul id="full-item-list"></ul>
<div class="listItem">
<button id="add-more" class='btn btn-warning addExpenseBtn'>Add Expense</button>
<button class="btn btn-warning submitExpenseBtn" type="button" onclick="displayResult(); displayCategory()">Submit</button>
<button class="btn btn-warning resetExpenseBtn" type="button" onclick="resetForm()">Reset</button>
</div>
</div>
<div id="jumbo-results" class="jumbotron">
<p id="result"></p><br>
<p id="left"></p>
</div>
<button class="btn btn-warning captureBtn" onclick="captureScreen()">Save Me</button>
</div>
</div>
<footer>
<small>© Copyright 2018, Noble Finsand</small>
</footer>
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.1/js/bootstrap.min.js'></script>
<script src="js/index.js"></script>
<script src="js/html2canvas.js"></script>
<script src="js/html2canvas.min.js"></script>
</body>
</html>
In order to calculate the total based on the categories, you will need to create a list of objects that have all the data the user entered.
From a code hygiene perspective creating the list and performing calculations on it should be separate tasks.
Similar to how you are looping through all the qty fields entered by the user in displayResult you can build out your list of expenses and then process that final result. Handling validation of each part will be challenging as they are all different fields and not guaranteed to have valid data.
Something like Angular can make this a lot easier as the hard part of binding input fields to a model is taken care of for you.
Regardless of how you create the list calculating the total by category is simple.
Assuming you create a list like this
var myExpenses = [
{'category': 'Home', name: 'rent', 'amount': 500},
{'category': 'Pets', name: 'cat food', 'amount': 45},
{'category': 'Home', name: 'utilities', 'amount': 200},
{'category': 'Pets', name: 'vet', 'amount': 42},
{'category': 'Home', name: 'trash', 'amount': 50},
{'category': 'Entertainment', name: 'date night', 'amount': 80}
];
Then these functions will be able to return you the grand total of all the expenses and each expense based on your categories.
function totalExpenses (expenses) {
return expenses.reduce(function (total, expense) {
return total + expense.amount;
}, 0);
}
function totalExpenseByCategory(categories, expenses) {
var categorizedExpenses = [];
categories.map(function (category) {
var currentExpenses = expenses.filter(function (expense) {
return expense.category === category;
});
var total = totalExpenses(currentExpenses);
categorizedExpenses.push({'category': category, 'amount': total})
});
return categorizedExpenses;
}
These functions use Filter, Map and Reduce on arrays to calculate the totals. You can learn more about them here.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce