Building a quiz - it works but only on the first question - javascript

I am in the process of building a quiz sort of game using JQuery. My game works how I wish it to currently, but only for the first question.
var progress = 0;
var score = 0;
var running = true;
var questions = [
{question: 'Which character is played by Robert Downey Junior?', answers: ['Thor', 'Iron Man', 'Captain America', 'Star Lord'], correct: 'Iron Man'},
{question: 'What colour is the star on Captain Americas shield?', answers: ['Red', 'Silver/Grey', 'Blue', 'Yellow/Gold'], correct: 'Silver/Grey'}
];
var $quiz = $('.quiz');
var $question = $('#quiz-question');
var $answers = $('#answers');
var $next = $('#next');
var $results = $('#results');
var showQuestion = q => {
if (progress < questions.length) {
$question.html(q.question);
$answers.html(' ');
q.answers.forEach(function(ans) {
$answers.append("<div class='answer'>" + ans + "</div>");
})
} else {
$results.html("<h2>Your Results:</h2><p>You scored " + score + "/" + questions.length + "</p>");
$quiz.hide();
$results.show();
}
};
showQuestion(questions[progress]);
$(document).ready(function(){
$next.hide();
$results.hide();
$('.answer').on('click', function(){
if($(this).html() === questions[progress].correct && running) {
progress++;
running = false;
score++;
$(this).css('color', 'green');
$(this).css('border', '3px solid green');
$(this).css('font-weight', 'bold');
$next.show();
} else if ($(this).html() !== questions[progress] && running) {
$(this).css('color', 'red');
$(this).css('border', '3px solid red');
$(this).css('font-weight', 'bold');
progress++;
running = false;
$next.show();
}
})
$next.on('click', function() {
running = true;
showQuestion(questions[progress]);
})
})
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
body {
background-color: #c7ecee;
font-family: 'Karla', sans-serif;
}
main {
min-height: 500px;
width: 100%;
display: flex;
align-items: flex-end;
}
main .quiz {
width: 40%;
margin: 0 auto;
text-align: center;
}
main .quiz #quiz-question {
font-size: 2rem;
width: 100%;
border: 2px solid #4d4d4d;
color: #fff;
background-color: #4d4d4d;
padding: 1rem;
}
main .quiz #answers {
font-size: 1.5rem;
border: 1px solid #4d4d4d;
}
main .quiz #answers .answer {
width: 100%;
padding: 1rem;
background-color: #fff;
border: 1px solid #4d4d4d;
cursor: pointer;
}
main .quiz #answers .answer:hover {
}
div#ui {
text-align: center;
width: 100%;
padding: .75rem;
}
div#ui button {
font-size: 1.75rem;
padding: .75rem;
background-color: #4d4d4d;
border: 1px solid #4d4d4d;
color: #fff;
cursor: pointer;
}
<main>
<div class='quiz'>
<div id='quiz-question'>
</div>
<div id='answers'>
</div>
</div>
<div id='results'>
</div>
</main>
<div id='ui'>
<button id='next'>Next</button>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Basically, a question and its answers are displayed, when an answer is clicked it stops running the game, so that no other answers can be clicked (or an answer can't be clicked more than once to boost score). When the question is answered, a button appears at the bottom to go to the next question. If there are no more questions, it shows you the results display.
This works exactly how I wish - for one question. When I add any further questions, it displays the question exactly as it should, but the on click effects are no longer applied. I assume this is to do with the elements not existing when the $(document).ready() function is called. Could anyone shed any light on how I could solve this problem?
Edited to include code snippet. Uncomment the second quest

On line 37, change:
$('.answer').on('click', function(){
to
$('body').on('click', '.answer', function(){
The thing is, when you write:
$(document).ready(function(){
$next.hide();
$results.hide();
$('.answer').on('click', function(){
You target all elements (at current moment) that have the class .answer. Since this is only the first question (in the beginning) it won't work at the questions after the first one.
If you instead write:
$(document).ready(function(){
$next.hide();
$results.hide();
$('body').on('click', '.answer', function(){
You tell jQuery to add the click-event to any current and new elements that will be added with the class .answer (within the body-element). It better to keep this specific, for example with an id for the quiz.
Se the whole example:
var progress = 0;
var score = 0;
var running = true;
var questions = [
{question: 'Which character is played by Robert Downey Junior?', answers: ['Thor', 'Iron Man', 'Captain America', 'Star Lord'], correct: 'Iron Man'},
{question: 'What colour is the star on Captain Americas shield?', answers: ['Red', 'Silver/Grey', 'Blue', 'Yellow/Gold'], correct: 'Silver/Grey'}
];
var $quiz = $('.quiz');
var $question = $('#quiz-question');
var $answers = $('#answers');
var $next = $('#next');
var $results = $('#results');
var showQuestion = q => {
if (progress < questions.length) {
$question.html(q.question);
$answers.html(' ');
q.answers.forEach(function(ans) {
$answers.append("<div class='answer'>" + ans + "</div>");
})
} else {
$results.html("<h2>Your Results:</h2><p>You scored " + score + "/" + questions.length + "</p>");
$quiz.hide();
$results.show();
}
};
showQuestion(questions[progress]);
$(document).ready(function(){
$next.hide();
$results.hide();
$('body').on('click', '.answer', function(){
if($(this).html() === questions[progress].correct && running) {
progress++;
running = false;
score++;
$(this).css('color', 'green');
$(this).css('border', '3px solid green');
$(this).css('font-weight', 'bold');
$next.show();
} else if ($(this).html() !== questions[progress] && running) {
$(this).css('color', 'red');
$(this).css('border', '3px solid red');
$(this).css('font-weight', 'bold');
progress++;
running = false;
$next.show();
}
})
$next.on('click', function() {
running = true;
showQuestion(questions[progress]);
})
})
<body>
<main>
<div class='quiz'>
<div id='quiz-question'>
</div>
<div id='answers'>
</div>
</div>
<div id='results'>
</div>
</main>
<div id='ui'>
<button id='next'>Next</button>
</div>
<script src='https://code.jquery.com/jquery-3.2.1.min.js' integrity='sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=' crossorigin='anonymous'></script>
<script src='includes/js/main.js'></script>
</body>

Here is a minimal edit to get your code working:
var progress = 0;
var score = 0;
var running = true;
var questions = [
{question: 'Which character is played by Robert Downey Junior?', answers: ['Thor', 'Iron Man', 'Captain America', 'Star Lord'], correct: 'Iron Man'},
{question: 'What colour is the star on Captain Americas shield?', answers: ['Red', 'Silver/Grey', 'Blue', 'Yellow/Gold'], correct: 'Silver/Grey'}
];
var $quiz = $('.quiz');
var $question = $('#quiz-question');
var $answers = $('#answers');
var $next = $('#next');
var $results = $('#results');
var showQuestion = q => {
if (progress < questions.length) {
$question.html(q.question);
$answers.html(' ');
q.answers.forEach(function(ans) {
$answers.append("<div class='answer'>" + ans + "</div>");
})
$('.answer').on('click', function(){
if($(this).html() === questions[progress].correct && running) {
progress++;
running = false;
score++;
$(this).css('color', 'green');
$(this).css('border', '3px solid green');
$(this).css('font-weight', 'bold');
$next.show();
} else if ($(this).html() !== questions[progress] && running) {
$(this).css('color', 'red');
$(this).css('border', '3px solid red');
$(this).css('font-weight', 'bold');
progress++;
running = false;
$next.show();
}
})
} else {
$results.html("<h2>Your Results:</h2><p>You scored " + score + "/" + questions.length + "</p>");
$quiz.hide();
$results.show();
}
};
showQuestion(questions[progress]);
$(document).ready(function(){
$next.hide();
$results.hide();
$next.on('click', function() {
running = true;
showQuestion(questions[progress]);
})
})
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
body {
background-color: #c7ecee;
font-family: 'Karla', sans-serif;
}
main {
min-height: 500px;
width: 100%;
display: flex;
align-items: flex-end;
}
main .quiz {
width: 40%;
margin: 0 auto;
text-align: center;
}
main .quiz #quiz-question {
font-size: 2rem;
width: 100%;
border: 2px solid #4d4d4d;
color: #fff;
background-color: #4d4d4d;
padding: 1rem;
}
main .quiz #answers {
font-size: 1.5rem;
border: 1px solid #4d4d4d;
}
main .quiz #answers .answer {
width: 100%;
padding: 1rem;
background-color: #fff;
border: 1px solid #4d4d4d;
cursor: pointer;
}
main .quiz #answers .answer:hover {
}
div#ui {
text-align: center;
width: 100%;
padding: .75rem;
}
div#ui button {
font-size: 1.75rem;
padding: .75rem;
background-color: #4d4d4d;
border: 1px solid #4d4d4d;
color: #fff;
cursor: pointer;
}
<main>
<div class='quiz'>
<div id='quiz-question'>
</div>
<div id='answers'>
</div>
</div>
<div id='results'>
</div>
</main>
<div id='ui'>
<button id='next'>Next</button>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Basically, you were attaching an event listener to .answer elements once, then replacing those elements, which means when a user clicks the new ones, nothing happens. Here, we add the listeners every time a question is created.
Keep in mind, there are ways you can refactor this code. I would look into event delegation if you want to avoid creating listeners for every .answer element.

Related

how to play audio file on each question on javascript

var questions = [];
var images = {}
So, the inside of "questions" array have another array that can call "images" array the problem here is how to call the "audio array" i have made an array for the audio but it seems not working
var sounds ={}
I have also tried another method which is putting html element inside of the array of variables but still, it's not working
HTML css
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>Picture Quiz</title>
<style>
body {
background-color: #eeeeee;
}
.grid {
width: 68%;
height: 520px;
margin: 0 auto;
background-color: #fff;
padding: 10px 50px 50px 50px;
border-radius: 50px;
border: 2px solid #cbcbcb;
box-shadow: 10px 15px 5px #cbcbcb;
}
.buttons img
{
width:200px;
}
.grid h1 {
font-family: "sans-serif";
background-color: #ffc107;
font-size: 35px;
text-align: center;
color: #ffffff;
padding: 2px 0px;
border-radius: 50px;
}
hr
{
margin-top: 50px;
color: red;
background-color: #ffc107;
height: 2px;
border: none;
}
#score {
color: #ffc107;
text-align: center;
font-size: 30px;
}
.grid #question {
font-family: "monospace";
font-size: 30px;
color: #ffc107;
}
.buttons {
margin-top: 30px;
}
#btn0,
#btn1,
#btn2,
#btn3 {
padding: 0px;
font-size: 20px;
color: #fff;
border: none;
margin: 10px 20px 10px 0px;
}
#btn0:hover,
#btn1:hover,
#btn2:hover,
#btn3:hover {
cursor: pointer;
background-color: #ffc107;
}
#btn0:focus,
#btn1:focus,
#btn2:focus,
#btn3:focus {
outline: 0;
}
#progress {
color: #2b2b2b;
font-size: 18px;
}
</style>
</head>
<body>
<div class="grid">
<div id="quiz">
<h1>Picture Quiz</h1>
<hr style="margin-bottom: 20px">
<p id="question"></p>
<p id="audio"></p>
<div class="buttons">
<button id="btn0"><span id="choice0"></span></button>
<button id="btn1"><span id="choice1"></span></button>
<button id="btn2"><span id="choice2"></span></button>
<button id="btn3"><span id="choice3"></span></button>
</div>
<hr style="margin-top: 50px">
<footer>
<p id="progress">Question x of y</p>
</footer>
</div>
</div>
</body>
</html>
Javascript
var images = {
"dog": "dog.jpg",
"cow": "cow.jpg",
"cat": "cat.jpg",
"goat": "goat.jpg",
"deer": "deer.jpg",
"hen": "hen.jpg",
"lion": "lion.jpg",
"parrot": "parrot.jpg",
"tiger": "tiger.jpg"
}
var sounds = {
"audio1" : "grizz.mp3",
"audio2" : "immortal.mp3",
"audio3" : "genshoshi.mp3",
"audio4" : "genshoshi.mp3",
"audio5" : "immortal.mp3"
}
function populate() {
if (quiz.isEnded()) {
showScores();
} else {
// show question
var element = document.getElementById("question");
element.innerHTML = quiz.getQuestionIndex().text;
// show audio
var audio = document.getElementById("audio");
audio.innerHTML = quiz.getQuestionIndex().audio;
// show options
var choices = quiz.getQuestionIndex().choices;
for (var i = 0; i < choices.length; i++) {
var element = document.getElementById("choice" + i);
element.innerHTML = images[choices[i]]? '<img src="'+images[choices[i]]+'"/>':choices[i];
guess("btn" + i, choices[i]);
}
showProgress();
}
};
function guess(id, guess) {
var button = document.getElementById(id);
button.onclick = function() {
quiz.guess(guess);
populate();
}
};
function showProgress() {
var currentQuestionNumber = quiz.questionIndex + 1;
var element = document.getElementById("progress");
element.innerHTML = "Question " + currentQuestionNumber + " of " + quiz.questions.length;
};
function showScores() {
var gameOverHTML = "<h1>Result</h1>";
gameOverHTML += "<h2 id='score'> Your scores: " + quiz.score + "</h2>";
var element = document.getElementById("quiz");
element.innerHTML = gameOverHTML;
};
// create questions
var questions = [
new Question(["Which one is dog?"],"audio1",["cow", "goat", "cat", "dog"], "dog"),
new Question(["select tiger below"],"audio2",["parrot", "deer", "tiger", "lion"], "tiger"),
new Question(["choose parrot pls?"],"audio3",["hen", "parrot", "goat", "dog"], "parrot"),
new Question(["Find cat below?"],"audio4",["parrot", "goat", "cat", "tiger"], "cat"),
new Question(["choose lion pls?"],"audio5",["lion", "goat", "tiger", "dog"], "lion")
];
questions.sort(function(){
return 0.5 - Math.random();
});
function Question(text, audio , choices, answer) {
this.text = text;
this.audio = audio;
this.choices = choices;
this.answer = answer;
}
Question.prototype.isCorrectAnswer = function(choice) {
return this.answer === choice;
}
function Quiz(questions) {
this.score = 0;
this.questions = questions;
this.questionIndex = 0;
}
Quiz.prototype.getQuestionIndex = function() {
return this.questions[this.questionIndex];
}
Quiz.prototype.guess = function(answer) {
if (this.getQuestionIndex().isCorrectAnswer(answer)) {
this.score++;
}
this.questionIndex++;
}
Quiz.prototype.isEnded = function() {
return this.questionIndex === this.questions.length;
}
// create quiz
var quiz = new Quiz(questions);
// display quiz
populate();
I'm trying to make text sound1 into an audio button that can be played as my quiz later
For audio, you have to make an html element and grab that element by using its id and audio will only play when the user triggers it like when clicked it will not be automatically played.
You can refer this site for more information.
And please don't copy paste whole code while asking question, paste whatever is required.

How to color the right choice and the wrong choice in java script quiz?

I want to color the button with green when user choice the correct answer, and with red when it is wrong but in a same time with color the correct answer with green i try this but it is not work.
this text is to let me to publish the post
/*
I would like to be able to show the user what the correct answer to the question is if the one that they selected was incorrect. I would like to keep it simple, but here is what I am thinking. Once the user submits their answer and if it is incorrect, before moving onto the next question I would like for the incorrect answer to be highlighted in red, and the correct answer to be highlighted in green.
I already have coded whether or not the answer is correct or incorrect, but I haven't been able to figure out how to be able to show the correct answer if an incorrect one is chosen.
*/
function wait(ms){
var start = new Date().getTime();
var end = start;
while(end < start + ms) {
end = new Date().getTime();
}
}
function Quiz(questions) {
this.score = 0;
this.questions = questions;
this.questionIndex = 0;
}
Quiz.prototype.getQuestionIndex = function() {
return this.questions[this.questionIndex];
}
Quiz.prototype.guess = function(answer) {
if(this.getQuestionIndex().isCorrectAnswer(answer)) {
console.log(answer);
this.score++;
}
populateV2();
wait(2000);
this.questionIndex++;
}
Quiz.prototype.isEnded = function() {
return this.questionIndex === this.questions.length;
}
function Question(text, textAnswer, choices, answer) {
this.text = text;
this.textAnswer = textAnswer;
this.choices = choices;
this.answer = answer;
}
Question.prototype.isCorrectAnswer = function(choice) {
document.getElementById("btn0").style.backgroundColor='green';
return this.answer === choice;
}
function populate() {
if(quiz.isEnded()) {
showScores();
}
else {
// show question
var element = document.getElementById("question");
element.innerHTML = quiz.getQuestionIndex().text;
// show textAnswer
var textAnswer = quiz.getQuestionIndex().textAnswer;
for(var i = 0; i < textAnswer.length; i++) {
var element = document.getElementById("textAnswer" + i);
element.innerHTML = textAnswer[i];
}
// show options
var choices = quiz.getQuestionIndex().choices;
for(var i = 0; i < choices.length; i++) {
var element = document.getElementById("choice" + i);
element.innerHTML = choices[i];
guess("btn" + i, choices[i]);
}
showProgress();
}
};
function populateV2() {
console.log("Test");
// show question
var element = document.getElementById("question");
element.innerHTML = quiz.getQuestionIndex().text;
// show textAnswer
var textAnswer = quiz.getQuestionIndex().textAnswer;
for(var i = 0; i < textAnswer.length; i++) {
var element = document.getElementById("textAnswer" + i);
element.innerHTML = textAnswer[i];
}
// show options
var choices = quiz.getQuestionIndex().choices;
for(var i = 0; i < choices.length; i++) {
var element = document.getElementById("choice" + i);
element.innerHTML = choices[i];
}
showProgress();
};
function guess(id, guess) {
var button = document.getElementById(id);
button.onclick = function() {
quiz.guess(guess);
populate();
}
};
function showProgress() {
var currentQuestionNumber = quiz.questionIndex + 1;
var element = document.getElementById("progress");
element.innerHTML = "Question " + currentQuestionNumber + " of " + quiz.questions.length;
};
function showScores() {
var gameOverHTML = "<h1>Result</h1>";
gameOverHTML += "<h2 id='score'> Your scores: " + quiz.score + "</h2>";
var element = document.getElementById("quiz");
element.innerHTML = gameOverHTML;
};
// create questions here
var questions = [
new Question("1.At what age was Harry Potter when he received his Hogwarts letter?",
["A: 9",
"B: 6",
"C: 7"],
["A", "B","C"],
"C"),
new Question("2.Which is not a Hogwarts house?",
["A: Dunder Mifflin",
"B: Ravenclaw",
"C: Slytherin"],
["A", "B","C"],
"A"),
new Question("3.Who teaches Transfiguration at Hogwarts?",
["A: Rubeus Hagrid",
"B: Minerva McGonnagle",
"C: Albus Dumbledore"],
["A", "B","C"],
"B")
];
// create quiz
var quiz = new Quiz(questions);
// display quiz
populate();
body {
background-color: #eeeeee;
}
.grid {
width: 600px;
height: 600px;
margin: 0 auto;
background-color: #fff;
padding: 10px 50px 50px 50px;
border-radius: 50px;
border: 2px solid #cbcbcb;
box-shadow: 10px 15px 5px #cbcbcb;
}
.grid h1 {
font-family: "sans-serif";
background-color: #57636e;
font-size: 60px;
text-align: center;
color: #ffffff;
padding: 2px 0px;
border-radius: 50px;
}
#score {
color: #5A6772;
text-align: center;
font-size: 30px;
}
.grid #question {
font-family: "monospace";
font-size: 20px;
color: #5A6772;
}
.grid1 #textAnswer {
font-family: "monospace";
font-size: 15px;
color: #5A6772;
}
.image {
width: 20%;
}
.buttons {
margin-top: 30px;
}
#btn0, #btn1 {
background-color: #778897;
width: 250px;
font-size: 20px;
color: #fff;
border: 1px solid #1D3C6A;
border-radius: 50px;
margin: 10px 40px 10px 0px;
padding: 10px 10px;
}
#btn2 {
background-color: #778897;
width: 500px;
font-size: 20px;
color: #fff;
border: 1px solid #1D3C6A;
border-radius: 50px;
margin: 10px 40px 10px 20px;
padding: 10px 10px;
}
#btn0:hover, #btn1:hover, #btn2:hover {
cursor: pointer;
background-color: #57636e;
}
#btn0:focus, #btn1:focus, #btn2:focus {
outline: 0;
}
#progress {
color: #2b2b2b;
font-size: 18px;
}
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>Quiz</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div class="grid">
<div id="quiz">
<h1>Quiz</h1>
<hr style="margin-bottom: 20px">
<p id="question"></p>
<ul class="grid1">
<li id="textAnswer0"></li>
<li id="textAnswer1"></li>
<li id="textAnswer2"></li>
</ul>
<div class="buttons">
<button id="btn0"><span id="choice0"></span></button>
<button id="btn1"><span id="choice1"></span></button>
<button id="btn2"><span id="choice2"></span></button>
</div>
<span id="wrong_answer"></span>
<hr style="margin-top: 50px">
<footer>
<p id="progress">Question x of y</p>
</footer>
</div>
</div>
<script src="app.js"></script>
</body>
</html>
In order to color the right choice with green and the wrong choices with red just select all buttons, compare the content of their <span> element with the right answer and color them accordingly:
function wait(ms) {
var start = new Date().getTime();
var end = start;
while (end < start + ms) {
end = new Date().getTime();
}
}
function Quiz(questions) {
this.score = 0;
this.questions = questions;
this.questionIndex = 0;
}
Quiz.prototype.getQuestionIndex = function() {
return this.questions[this.questionIndex];
}
Quiz.prototype.guess = function(answer) {
if (this.getQuestionIndex().isCorrectAnswer(answer)) {
console.log(answer);
this.score++;
}
populateV2();
wait(2000);
this.questionIndex++;
}
Quiz.prototype.isEnded = function() {
return this.questionIndex === this.questions.length;
}
function Question(text, textAnswer, choices, answer) {
this.text = text;
this.textAnswer = textAnswer;
this.choices = choices;
this.answer = answer;
}
Question.prototype.isCorrectAnswer = function(choice) {
var answer = this.answer;
const buttons = document.querySelectorAll('button');
for (let i = 0; i < buttons.length; i++) {
var letter = buttons[i].getElementsByTagName("span")[0].textContent;
if (letter == answer) {
buttons[i].style.backgroundColor = 'green';
} else {
buttons[i].style.backgroundColor = 'red';
}
}
return this.answer === choice;
}
function populate() {
if (quiz.isEnded()) {
showScores();
} else {
// show question
var element = document.getElementById("question");
element.innerHTML = quiz.getQuestionIndex().text;
// show textAnswer
var textAnswer = quiz.getQuestionIndex().textAnswer;
for (var i = 0; i < textAnswer.length; i++) {
var element = document.getElementById("textAnswer" + i);
element.innerHTML = textAnswer[i];
}
// show options
var choices = quiz.getQuestionIndex().choices;
for (var i = 0; i < choices.length; i++) {
var element = document.getElementById("choice" + i);
element.innerHTML = choices[i];
guess("btn" + i, choices[i]);
}
showProgress();
}
};
function populateV2() {
console.log("Test");
// show question
var element = document.getElementById("question");
element.innerHTML = quiz.getQuestionIndex().text;
// show textAnswer
var textAnswer = quiz.getQuestionIndex().textAnswer;
for (var i = 0; i < textAnswer.length; i++) {
var element = document.getElementById("textAnswer" + i);
element.innerHTML = textAnswer[i];
}
// show options
var choices = quiz.getQuestionIndex().choices;
for (var i = 0; i < choices.length; i++) {
var element = document.getElementById("choice" + i);
element.innerHTML = choices[i];
}
showProgress();
};
function guess(id, guess) {
var button = document.getElementById(id);
button.onclick = function() {
quiz.guess(guess);
populate();
}
};
function showProgress() {
var currentQuestionNumber = quiz.questionIndex + 1;
var element = document.getElementById("progress");
element.innerHTML = "Question " + currentQuestionNumber + " of " + quiz.questions.length;
};
function showScores() {
var gameOverHTML = "<h1>Result</h1>";
gameOverHTML += "<h2 id='score'> Your scores: " + quiz.score + "</h2>";
var element = document.getElementById("quiz");
element.innerHTML = gameOverHTML;
};
// create questions here
var questions = [
new Question("1.At what age was Harry Potter when he received his Hogwarts letter?",
["A: 9",
"B: 6",
"C: 7"
],
["A", "B", "C"],
"C"),
new Question("2.Which is not a Hogwarts house?",
["A: Dunder Mifflin",
"B: Ravenclaw",
"C: Slytherin"
],
["A", "B", "C"],
"A"),
new Question("3.Who teaches Transfiguration at Hogwarts?",
["A: Rubeus Hagrid",
"B: Minerva McGonnagle",
"C: Albus Dumbledore"
],
["A", "B", "C"],
"B")
];
// create quiz
var quiz = new Quiz(questions);
// display quiz
populate();
body {
background-color: #eeeeee;
}
.grid {
width: 600px;
height: 600px;
margin: 0 auto;
background-color: #fff;
padding: 10px 50px 50px 50px;
border-radius: 50px;
border: 2px solid #cbcbcb;
box-shadow: 10px 15px 5px #cbcbcb;
}
.grid h1 {
font-family: "sans-serif";
background-color: #57636e;
font-size: 60px;
text-align: center;
color: #ffffff;
padding: 2px 0px;
border-radius: 50px;
}
#score {
color: #5A6772;
text-align: center;
font-size: 30px;
}
.grid #question {
font-family: "monospace";
font-size: 20px;
color: #5A6772;
}
.grid1 #textAnswer {
font-family: "monospace";
font-size: 15px;
color: #5A6772;
}
.image {
width: 20%;
}
.buttons {
margin-top: 30px;
}
#btn0, #btn1 {
background-color: #778897;
width: 250px;
font-size: 20px;
color: #fff;
border: 1px solid #1D3C6A;
border-radius: 50px;
margin: 10px 40px 10px 0px;
padding: 10px 10px;
}
#btn2 {
background-color: #778897;
width: 500px;
font-size: 20px;
color: #fff;
border: 1px solid #1D3C6A;
border-radius: 50px;
margin: 10px 40px 10px 20px;
padding: 10px 10px;
}
#btn0:hover, #btn1:hover, #btn2:hover {
cursor: pointer;
background-color: #57636e;
}
#btn0:focus, #btn1:focus, #btn2:focus {
outline: 0;
}
#progress {
color: #2b2b2b;
font-size: 18px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="grid">
<div id="quiz">
<h1>Quiz</h1>
<hr style="margin-bottom: 20px">
<p id="question"></p>
<ul class="grid1">
<li id="textAnswer0"></li>
<li id="textAnswer1"></li>
<li id="textAnswer2"></li>
</ul>
<div class="buttons">
<button id="btn0"><span id="choice0"></span></button>
<button id="btn1"><span id="choice1"></span></button>
<button id="btn2"><span id="choice2"></span></button>
</div>
<span id="wrong_answer"></span>
<hr style="margin-top: 50px">
<footer>
<p id="progress">Question x of y</p>
</footer>
</div>
</div>
Note that you have to adjust/restructure your code so that there's a short waiting time before the new question is generated as I think you might want to show the buttons again with the grey background color upon a new question.

JS: a addClass function in jquery for some reason does nothing

The function showColorStart() for some reason does nothing. When the function is executed the background of the squares needs to change to the color of the string in the array colorspicked[lindex], and it does not do nothing. I looked at the code multiple times and i cant find the problem.
How can I fix it?
The codepen is here.
// Setting Variables
var gameStatus = false;
var strict = false;
var playerTurn = true+;
var colors = ['green', 'red', 'yellow', 'blue'];
var colorsPicked = ['green', 'red', 'yellow', 'blue'];
var colorsClicked = [];
var level = 1;
var lIndex = 0;
// Game Status Function
$('#start').click(function(){
if(gameStatus == false){
gameStatus = true;
gameStart();
}
});
// Game Start Function
function gameStart(){
}
// Chaning color buttons
$('.cubes').click(function(e){
if(playerTurn == true){
$(e.target).addClass(e.target.id);
setTimeout(function(){
$(e.target).removeClass(e.target.id);
}, 500);
} else {
return;
}
});
// Random Color Picking Function
function randomColor(){
var random = Math.floor(Math.random() * 4);
colorsPicked.push(colors[random]);
}
// Colors Showing at Start of a level
function showColorStart(){
lIndex = 0;
setInterval(function(){
if(colorsPicked[lIndex] == 'green'){
$('#green').addClass('green');
} else if(colorsPicked[lIndex] == 'red'){
$('#red').addClass('red');
} else if(colorsPicked[lIndex] == 'yellow'){
$('#yellow').addClass('yellow');
} else if(colorsPicked[lIndex] == 'blue'){
$('#blue').addClass('blue');
} else {
return;
}
setTimeout(function(){
$('#green', '#red', '#yellow', '#blue').removeClass('green, red, yellow, blue');
}, 500);
if(lIndex == colorsPicked.length){
stopInterval();
}
}, 500);
lIndex++;
}
showColorStart();
#import url('https://fonts.googleapis.com/css?family=Orbitron');
body {
background-color: #000;
margin: 0;
padding: 0;
}
.container {
margin: 0 auto;
text-align: center;
padding: 20px;
}
.menu {
margin-bottom: 20px;
}
.display {
width: 130px;
height: 40px;
background-color: #282828;
margin: 0 auto;
text-align: center;
font-family: Orbitron, sans-serif;
}
table {
margin: 0 auto;
}
.cubes {
width: 150px;
height: 150px;
}
#green {
border: 2px solid green;
border-right: 2px solid red;
}
#red {
border: 2px solid red;
border-bottom: 2px solid blue;
}
#yellow {
border: 2px solid yellow;
}
#blue {
border: 2px solid blue;
}
.green {
background-color: green;
}
.red {
background-color: red;
}
.yellow {
background-color: yellow;
}
.blue {
background-color: blue;
}
#disp {
font-size: 12px;
color: #000;
padding: 8px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<div class="container">
<div class="menu">
<input type='button' value='Start/Restart' id='start' class='btn'>
<input type='button' value='Strict' id='strict' class='btn'>
</div>
<div class='board'>
<div class='display'><p id='disp'></p></div>
<br>
<table>
<tbody>
<tr>
<td class='cubes' id='green'></td>
<td class='cubes' id='red'></td>
</tr>
<tr>
<td class='cubes' id='yellow'></td>
<td class='cubes' id='blue'></td>
</tr>
</tbody>
</table>
</div>
</div>
You've put a plus sign on this line where is doesn't belong causing an error
var playerTurn = true+;
change to
var playerTurn = true;
Yupp,
Remove the + sign from your code, Error on line No 4,
var playerTurn = true+;
replace it by var playerTurn = true;
Here is your mistake man,
after removing this ,will work fine.

JS/jQuery - If statements without "return"

*this question has been updated.
I have a set of boxes which, when clicked open a div called #expander. In my code, after #expander is opened, and if another box is clicked, I check if the new box clicked is the same as the last box clicked. If it is the same, I close #expander, else I briefly close it and then open it again.
This is demonstrated with the this jsfiddle
Here is the same code, in stackoverflow:
$(document).on('click', '.box', function(e) {
if (!$('#expander').hasClass('active')) {
$('#expander').addClass('active');
$('.basic-info').css('border-left', '1px solid black');
activeBox = $(this).attr('id');
$('#main').text(activeBox);
console.log('activeBox = ' + activeBox);
return;
}
if ($('#expander').hasClass('active')) {
$('#expander').removeClass('active');
$('.basic-info').css('border-left', '0px solid black');
if ($(this).attr('id') !== activeBox) {
setTimeout(function() {
$('#expander').addClass('active');
}, 256);
}
activeBox = $(this).attr('id');
$('#main').text(activeBox);
console.log('activeBox = ' + activeBox);
return;
}
});
#expander{
height: 100%;
width: 0%;
float: left;
visibility: hidden;
overflow: hidden;
background-color: grey;
transition: .75s ease-out;
}
#expander.active{
height: 100%;
width: 50%;
z-index: 1;
visibility: visible;
}
#closer{
padding: 4px;
margin: 0px;
background-color: #707070;
color: white;
font-size: 1.5em;
text-align: center;
cursor: pointer;
}
#closer:hover{
background-color: #606060;
font-size: 2em;
padding: 0px;
}
.box{
width: 32px;
height: 32px;
padding: 5px 0px;
margin: 0px 4px;
display: inline-block;
background-color: grey;
overflow: hidden;
font-size: 1em;
font-weight: bold;
text-align: center;
border: 1px solid transparent;
border-radius: 2px;
cursor: pointer;
}
.basic-info{
padding: 8px 16px;
color: white;
background-color: #47a;
border-top: 1px solid black;
border-right: 1px solid black;
border-bottom: 1px solid black;
transition: .5s ease-out;
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="expander">
<div id="closer" title="Close"><span>&times</span></div>
<div id="main"></div>
</div>
<div class="basic-info">
<div id="box1" class="box">1</div>
<div id="box2" class="box">2</div>
<div id="box3" class="box">3</div>
</div>
The above code works (although it does not look exactly how it looks in my final layout) BUT what it does not do run this: $('.basic-info').css('border-left', '1px solid black'); after the first time a box is clicked (when it opens the #expander
I realize the reason this is not working is that the JS code first adds the classes and styles, but then the next if statement removes the classes and styles. Also, I have to paste the following code two times:
$('#main').text(activeBox);
console.log('activeBox = ' + activeBox);
return;
Does anyone know a better way to layout my if statements so that code does not conflict? Also, is there a way to not need to use return;s?
P.S. does anyone have a link to a good if statement tricks tutorial so that I can learn these things for the future?
Thank you.
UPDATE:
I have updated the code based on the current answers and have changed the JS to this:
$(document).on('click', '.box', function(e) {
if ($('#expander').hasClass('active')) {
$('#expander').removeClass('active');
if ($(this).attr('id') !== activeBox) {
setTimeout(function() {
$('#expander').addClass('active');
}, 256);
activeBox = $(this).attr('id');
console.log('activeBox = ' + activeBox);
return;
}
$('.basic-info').css('border-left', '0px solid white');
return;
}
$('#expander').addClass('active');
$('.basic-info').css('border-left', '1px solid white');
activeBox = $(this).attr('id');
console.log('activeBox = ' + activeBox);
}
(it does the same thing, just laid out differently). All I am trying to figure out now is just how I can write this without any of the return;s and also so I do not have to write activeBox = $(this).attr('id'); console.log('activeBox = ' + activeBox); twice (unless these things are impossible/unavoidable)
thank you.
for the clean up part and get rid of repeated data, you can convert your js code to this
Updated
jsFiddle
// target the #expander
var Expander = $('#expander'),
activeBox = '';
$(document).on('click', '.box', function(e) {
//toggleClass means if #expander hasClass, remove it, if it
//doesn't have the class, add it.
Expander.toggleClass('active');
// same for .basic info, we use toggle class, instead of
// CSS hardcoded, thus we can toggle
$('.basic-info').toggleClass('black-border-left');
if ($(this).attr('id') !== activeBox) {
Expander.removeClass('active');
// to get rid of the delay for when one .box div is clicked for the first time
// when activeBox = ''.
if(activeBox !== ''){
setTimeout(function() {
Expander.addClass('active');
}, 500);
}else{
Expander.addClass('active');
}
activeBox = $(this).attr('id');
}
$('#main').text(activeBox);
console.log('activeBox = ' + activeBox);
});
$(document).on('click', '.box', function(e) {
if (!$('#expander').hasClass('active')) {
$('#expander').addClass('active');
$('.basic-info').css('border-left', '1px solid black');
activeBox = $(this).attr('id');
$('#main').text(activeBox);
console.log('activeBox = ' + activeBox);
} else if ($('#expander').hasClass('active')) {
$('#expander').removeClass('active');
$('.basic-info').css('border-left', '0px solid black');
if ($(this).attr('id') !== activeBox) {
setTimeout(function() {
$('#expander').addClass('active');
}, 256);
}
activeBox = $(this).attr('id');
$('#main').text(activeBox);
console.log('activeBox = ' + activeBox);
}
});

jQuery filters sometimes showing all elements

When I toggle between jQuery filters that show elements with a certain class, sometimes the selected filter shows all elements and not just the ones with the respective class.
You can see this in the below fiddle. Switch between the select options and sometimes they'll show all results.
Fiddle.
function activateButtons(_data){
$('.jobs-teams select').on("change", function(e) {
e.preventDefault();
for(i = 0; i < _data.length; i++) {
var teamRaw = _data[i].title;
var team = cleanString(teamRaw);
var jobs = $(".jobs-list");
if ($(this).find(":selected").hasClass(team)) {
if ($(this).hasClass("active")) {
$(this).removeClass("active");
jobs.find(".job").fadeIn("fast");
}
else {
$(".jobs-teams").find("a").removeClass("active");
$(this).addClass("active");
jobs.find("."+team).fadeIn("fast");
jobs.find(".job").not("."+team).fadeOut("fast");
}
}
}
})
}
Issues with the code that just need to be updated are the following.
//$(this) return the select tag. you should target options
if ($(this).hasClass("active")) {
$(this).removeClass("active");
jobs.find(".job").fadeIn("fast");
}
else {
//$(".jobs-teams").find("a") returns undefined remember that you changed the anchors to select options
$(".jobs-teams").find("a").removeClass("active");
$(this).addClass("active");
jobs.find("."+team).fadeIn("fast");
jobs.find(".job").not("."+team).fadeOut("fast");
}
CODE SNIPPET:
// Replace "leverdemo" with your own company name
url = 'https://api.lever.co/v0/postings/leverdemo?group=team&mode=json'
//Functions for checking if the variable is unspecified
function cleanString(string) {
if (string) {
var cleanString = string.replace(/\s+/ig, "");
return cleanString;
}
else {
return "Uncategorized";
}
}
function nullCheck(string) {
if (!string) {
var result = 'Uncategorized'
return result;
}
else {
return string;
}
}
function createJobs(_data) {
for(i = 0; i < _data.length; i++) {
var team = nullCheck(_data[i].title)
var teamCleanString = cleanString(team);
$('#jobs-container .jobs-teams select').append(
'<option value="" class=' + teamCleanString + '>' + team + '</option>'
);
}
for(i = 0; i < _data.length; i++) {
for (j = 0; j < _data[i].postings.length; j ++) {
var posting = _data[i].postings[j]
var title = posting.text
var description = posting.description
//Making each job description shorter than 250 characters
var shortDescription = $.trim(description).substring(0, 250)
.replace('\n', ' ') + "...";
var location = nullCheck(posting.categories.location);
var locationCleanString = cleanString(location);
var commitment = nullCheck(posting.categories.commitment);
var commitmentCleanString = cleanString(commitment);
var team = nullCheck(posting.categories.team);
var teamCleanString = cleanString(team);
var link = posting.hostedUrl;
$('#jobs-container .jobs-list').append(
'<div class="job '+teamCleanString+' '+locationCleanString+' '+commitmentCleanString+'">' +
'<a class="job-title" href="'+link+'"">'+title+'</a>' +
'<p class="tags"><span>'+team+'</span><span>'+location+'</span><span>'+commitment+'</span></p>' +
'<p class="description">'+shortDescription+'</p>' +
'<a class="btn" href="'+link+'">Learn more</a>' +
'</div>'
);
}
}
}
function activateButtons(_data){
$('.jobs-teams select').on("change", function(e) {
e.preventDefault();
for(i = 0; i < _data.length; i++) {
var teamRaw = _data[i].title;
var team = cleanString(teamRaw);
var jobs = $(".jobs-list");
var $this = $(this).find(":selected");
if ($this.hasClass(team)) {
if ($this.hasClass("active")) {
$this.removeClass("active");
jobs.find(".job").fadeIn("fast");
}
else {
$(".jobs-teams select").find("option").removeClass("active");
$this.addClass("active");
jobs.find("."+team).fadeIn("fast");
jobs.find(".job").not("."+team).fadeOut("fast");
}
}
}
}).change();
}
//Fetching job postings from Lever's postings API
$.ajax({
dataType: "json",
url: url,
success: function(data){
createJobs(data);
activateButtons(data);
}
});
body {
font-family: 'Lato', sans-serif;
overflow-y: scroll;
}
p {
margin: 0 0 1em 0;
line-height: 1.4em;
}
* {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
section {
position: relative;
padding: 30px;
}
.container {
max-width: 960px;
margin: 0 auto;
}
.job {
display: inline-block;
vertical-align: top;
width: 50%;
padding: 40px 30px;
}
h1 {
font-size: 48px;
color: #454545;
padding: 0 30px;
}
.job-title {
font-size: 24px;
text-decoration: none;
color: #454545;
}
.job-title:hover {
color: #00A0DF;
}
.tags span {
color: #999;
font-size: 12px;
color: grayMediumDark;
}
.tags span:after {
content: ', ';
}
.tags span:last-of-type:after {
content: '';
}
.description {
color: #999;
}
.btn {
display: inline-block;
padding: 7px 15px;
text-decoration: none;
font-weight: normal;
color: #999;
border: 2px solid #ebebeb;
-webkit-border-radius: 4px;
border-radius: 4px;
background: #f9f9f9;
}
.btn:hover {
background: #ebebeb;
color: #555;
}
.btn.active {
background: #454545;
border-color: #454545;
color: #fff;
}
.jobs-teams {
margin-bottom: 40px;
padding: 0 30px
}
.jobs-teams .btn {
margin: 0 8px 8px 0;
}
.jobs-teams .btn:first-of-type {
margin-left: 0;
}
.jobs-teams .btn:last-of-type {
margin-right: 0;
}
<section>
<div class="container" id="jobs-container">
<h1>Open jobs</h1>
<div class="jobs-teams">
<select>
</select>
</div>
<div class="jobs-list">
</div>
</div>
</section>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
Consider doing it with fewer lines:
function activateButtons(_data) {
$('.jobs-teams select').on("change", function(e) {
e.preventDefault();
var selected_class = $('.jobs-teams select').find(':selected').attr('class');
$('.jobs-list').find('div.job')
.not('.' + selected_class).fadeOut('fast').end() //remove the ones that do not match
.filter('.' + selected_class).not(':visible').fadeIn('fast'); // bring in the ones that do match (and are not already visible)
})
.change(); //have the form pre-load with the default selected value
}
Oh--I also added a line to have the jobs honor the default selection (.change(); //have the form pre-load with the default selected value).
Working fiddle.

Categories

Resources