I'm doing the "Learn JavaScript Properly" track on http://javascriptissexy.com/how-to-learn-javascript-properly/.
It took me forever, but I finally figured out how to get to the next question, but the choices don't change.
However, when I hard code the "questionIndex" the question and choices work fine.
Anyway here's my code (I know it's a bit messy, I'm a beginner):
http://jsfiddle.net/utfwae8d/1/
HTML:
<div id="container">
<div id="quiz"></div>
<div id="choices"></div>
<input type="button" value="Next">
</div>
JavaScript:
var allQuestions = [{
question: "Who is the best in the world?",
choices: ["CM Punk", "John Cena", "Daniel Bryan", "Roman Reigns"],
correctAnswer: 0
},
{
question: "Who is the current WWE World Champion?",
choices: ["John Cena", "Brock Lesnar", "Triple H"],
correctAnswer: 1
},
{
question: "Where is Toronto located?",
choices: ["Ontario", "California", "Georgia", "Texas"],
correctAnswer: 0
},
{
question: "What is the largest California city?",
choices: ["Los Angeles", "San Fransico", "San Deigo", "Anahiem"],
correctAnswer: 0
}];
var quiz = document.getElementById('quiz');
var choicesContainer = document.getElementById('choices');
var nextButton = document.querySelector('[type=button]');
var correctAnswers = 0;
var questionIndex = 0;
function showQuiz() {
var currentQuestion = allQuestions[questionIndex].question;
quiz.textContent = currentQuestion;
var choicesNum = allQuestions[questionIndex].choices.length;
var correctAnswer = allQuestions[questionIndex].correctAnswer;
var choices;
for (var i = 0; i < choicesNum; i++) {
choices = allQuestions[questionIndex].choices[i];
choicesHTML = "<input type='radio' name='choice'>" + choices + "</br>";
choicesContainer.innerHTML += choicesHTML;
}
nextButton.addEventListener('click', function () {
questionIndex++;
quiz.textContent = allQuestions[questionIndex].question;
});
}
showQuiz();
The button's click handler is not updating the answers, it's only updating the question.
I've separated the code into two functions: one that shows the quiz, and one that shows the answers.
var quiz = document.getElementById('quiz');
var choicesContainer = document.getElementById('choices');
var nextButton = document.querySelector('[type=button]');
var questionIndex = 0;
function showAnswers() {
choicesContainer.innerHTML = "";
var choicesNum = allQuestions[questionIndex].choices.length;
for (var i = 0; i < choicesNum; i++) {
var choice = allQuestions[questionIndex].choices[i];
choicesHTML = "<input type='radio' name='choice'>" + choice + "</br>";
choicesContainer.innerHTML += choicesHTML;
}
}
function showQuiz() {
var currentQuestion = allQuestions[questionIndex].question;
quiz.textContent = currentQuestion;
}
showQuiz();
showAnswers();
nextButton.addEventListener('click', function () {
questionIndex++;
showQuiz();
showAnswers();
});
Your issue is in the eventlistener method. I have modified your code as below and it works.
nextButton.addEventListener('click', function () {
var newChoicesHTML="";
var newChoices;
questionIndex++;
choicesNum = allQuestions[questionIndex].choices.length;
quiz.textContent = allQuestions[questionIndex].question;
for (var i = 0; i < choicesNum; i++) {
newChoices = allQuestions[questionIndex].choices[i];
newChoicesHTML+= "<input type='radio' name='choice'>" + newChoices + "</input></br>";
}
choicesContainer.innerHTML = newChoicesHTML;
});
Basically the issue is on event change you are updating your question but not the answers.
Your showQuiz function is doing 3 things:
setting the question text
setting the answer list
adding an event listener to the button
When the button is clicked, your code updates the question text but doesn't update the answer list. So I pulled adding the event listener out (it only needs to be executed once) and then made the button click call showQuiz again. Also I added a line to blank out the previous choices.
function showQuiz() {
var currentQuestion = allQuestions[questionIndex].question;
quiz.textContent = currentQuestion;
var choicesNum = allQuestions[questionIndex].choices.length;
var correctAnswer = allQuestions[questionIndex].correctAnswer;
var choices;
choicesContainer.innerHTML = '';
for (var i = 0; i < choicesNum; i++) {
choices = allQuestions[questionIndex].choices[i];
choicesHTML = "<input type='radio' name='choice'>" + choices + "</br>";
choicesContainer.innerHTML += choicesHTML;
}
}
nextButton.addEventListener('click', function () {
questionIndex++;
showQuiz();
});
Related
I'm creating a Trivia game using an array of objects. I created a function that loops through and displays all the questions and then loops through all the choices and turns them into radio buttons. I've been struggling comparing the answer to the selected value, so when the timer runs out I can print how many the user got right and wrong. Can someone point me to correct direction?
function countdown() {
var counter = 60;
var timeCountdown = setInterval(function(){
counter--
$('.timer-container .time').html(counter);
if (counter === 0) {
clearInterval(timeCountdown);
$('.timer-container .time').html("Times Up");
points();
}
}, 1000);
$('.timer-container').toggle();
}
let trivia = [
{
question: "How many wheels are on a skateboard?",
choices: ["2", "4", "6", "8"],
answer: "2",
},
{
question: "Who invented the kickflip?",
choices: ["Tony Hawk", "Bam Magera", "Rodney Mullen", "Chad Muska"],
answer: "Rodney Mullen"
},
{
question: "Who did the first 900?",
choices: ["Tony Hawk", "Tas Pappas", "Danny Way", "bob burnquist"],
answer: "Tony Hawk",
},
{
question: "What is another word for a 360 flip?",
choices: ["Impossible Flip", "3 1/2 flip", "Tre Bomb", "Tri Flip"],
answer: "Tre Bomb",
}
];
function triviaQuestions() {
for(var i = 0; i < trivia.length; i++) {
var questionHeader = $('<h2 class="question-' + i + '">');
var questionHeaderContent = questionHeader.text(trivia[i].question);
$('.question-container').append(questionHeaderContent).append("<form class='choices choices-container-" + i + " '>");
for (var j = 0; j < trivia.length; j++) {
console.log(trivia[i].choices[j]);
var questionChoices = $('<input type="radio"' + 'name="' + i + '"'+ 'value="' + trivia[i].choices[j] + '">' + '<label>' + trivia[i].choices[j] + '</label>');
var questionChoicesContent = questionChoices.text(trivia[i].choices[j]);
$('.choices-container-' + i).append(questionChoices).append(questionChoicesContent);
}
}
}
$( document ).ready(function() {
$('.start-button').on('click', function() {
$(this).toggle();
countdown();
triviaQuestions();
});
});
Thanks
Your points() function could look something like this:
function points() {
var correct = 0;
$(".choices").each(function(i){
var questionid = $(this).attr('id').split('-')[1];
var answer = $(this).find("input:checked").val();
if (answer == trivia[questionid].answer) correct += 1;
});
$(".points-container").toggle();
$(".points-container span").text(correct);
}
assuming you have an element somewhere on your page like this:
<div class="points-container" style="display:none">Total Points: <span></span></div>
and assuming you add the id="" attibute to your form elements:
$('.question-container').append(questionHeaderContent).append("<form class='choices choices-container-" + i + "' id='choices-" + i + "'>");
The function above loops through each form on your page, pulls the question's index in the trivia array from the form's id, and matches the answer given against the answer specified in that index. Perhaps not the most elegant solution, but it worked for me, with minimal edits to your code.
There's a bit going on here so I've given you a complete solution - this covers the timer, the printing of the question/answer sets and the testing functionality.
A complete codepen here: https://codepen.io/V3Dev/pen/vYBaEVL
Details below - enjoy :)
HTML
<input id="trigger" type="button" value="Start Timer" onclick="startTimer();"/>
<p id="timer">60 Seconds Remaining</p>
<br>
<input id="trigger" type="button" value="Test Answers Immediately" onclick="testAnswers();"/>
<br><br><br>
<div id="container"/>
Script
//starting JSON
let trivia = [*JSON*];
//iterate over your JSON
for (let i = 0; i < trivia.length; i++) {
//print the question
document.getElementById("container").appendChild(document.createTextNode(trivia[i].question));
document.getElementById("container").appendChild(document.createElement("br"));
//iterate over the choices and create answer objects
for (let i2 = 0; i2 < trivia[i].choices.length; i2++) {
//print the choices
var input = document.createElement("input");
input.type = "radio";
input.value = trivia[i].choices[i2];
input.name = trivia[i].question;
document.getElementById("container").appendChild(input);
document.getElementById("container").appendChild(document.createTextNode(trivia[i].choices[i2]));
document.getElementById("container").appendChild(document.createElement("br"));
};
//seperate questions
document.getElementById("container").appendChild(document.createElement("br"));
document.getElementById("container").appendChild(document.createElement("br"));
};
//test the submitted answer against the stored value
function testAnswers(){
let score = 0;
for (let i = 0; i < trivia.length; i++) {
let questionSelectedAnswer = getRadioValue(trivia[i].question);
if (questionSelectedAnswer == trivia[i].answer){
score++;
}
}
alert("You scored " + score + "/" + trivia.length);
}
//get the selected value for a collection of answers
function getRadioValue(theRadioGroup)
{
var elements = document.getElementsByName(theRadioGroup);
for (var i = 0, l = elements.length; i < l; i++)
{
if (elements[i].checked)
{
return elements[i].value;
}
}
}
//set the timer logic
var timer;
function startTimer() {
//clear any running timers
clearInterval(timer);
var secondsRemaining = 60;
timer = setInterval(function() {
secondsRemaining--;
// If the count down is over run the test
if (secondsRemaining < 1) {
clearInterval(timer);
testAnswers();
secondsRemaining = 0;
}
//print the time
document.getElementById("timer").innerHTML = secondsRemaining + " seconds remaining";
}, 1000);
}
The html variable in my JavaScript code , doesn't display to the screen after my questions loop through the page. I get this error message , TypeError: divOutput is null. After all of my questions loops through
Here is the HTML
<!DOCTYPE html>
<html>
<head>
<title>JavaScript ES2015 Practice</title>
<script type="text/javascript" src="js/output.js"></script>
</head>
<body>
<div id="text">
</div>
</body>
The Javascript code
var quizQuestions;
var quizAnswers;
var correctAnswers;
var wrongAnswers;
var html;
var response;
const questions = [
{
question:"What is the captial of Georgia [type quit to quit]",
answer:"atlanta"
},
{
question:"What is the captial of New York [type quit to quit]",
answer:"albany"
},
{
question:"What is the captial of Texas [type quit to quit]",
answer:"austin"
}
];
const print = (message) =>{
let divOutput = document.getElementById("text");
divOutput.innerHTML = message;
}
for(let i = 0; i < questions.length; i++){
quizQuestions = questions[i].question;
quizAnswers = questions[i].answer;
response = prompt(quizQuestions);
if(response === quizAnswers){
correctAnswers++;
}else{
wrongAnswers++;
}
html = `You got ${correctAnswers} questions right`; //this doesn't display to the screen
} // end of for loop
print(html);
move your script in the onload callback so the script will be executed after
all of the objects in the document are in the DOM, and all the images
and sub-frames have finished loading.
then you can get divOutput
window.onload=function(){
//your script code;
}
the script should be :
window.onload = function () {
var quizQuestions;
var quizAnswers;
var correctAnswers = 0;
var wrongAnswers = 0;
var html;
var response;
const questions = [
{
question: "What is the captial of Georgia [type quit to quit]",
answer: "atlanta"
},
{
question: "What is the captial of New York [type quit to quit]",
answer: "albany"
},
{
question: "What is the captial of Texas [type quit to quit]",
answer: "austin"
}
];
const print = (message) => {
let divOutput = document.getElementById("text");
divOutput.innerHTML = message;
}
for (let i = 0; i < questions.length; i++) {
quizQuestions = questions[i].question;
quizAnswers = questions[i].answer;
response = prompt(quizQuestions);
if (response === quizAnswers) {
correctAnswers++;
} else {
wrongAnswers++;
}
html = `You got ${correctAnswers} questions right`; //this doesn't display to the screen
} // end of for loop
print(html);
}
also,i modified this:
var correctAnswers = 0;
var wrongAnswers = 0;
to make it work more legitimately
how to display element one by one on click using only Javascript, in my example when I click all elements show at once, but i need only one click - one element. I appreciate if you show the simplest way to do if in order to i can understand how it works
$(function() {
var cars = ["audi", "bmw", "volvo"];
var x = "";
var i;
for (i = 0; i <cars.length; i++) {
x += cars[i] + "<br>";
}
document.getElementById("btn").onclick = function() {
document.getElementById("text").innerHTML = x;
}
});
You may update your code as follows. At the very beginnig, your are initializing x with empty string. Then for each click on button, append an element from array with new line tag.
var cars = ["audi", "bmw", "volvo"];
var x = "";
var i = 0;
document.getElementById("btn").onclick = function() {
if( i < cars.length) {
x += cars[i++] + "<br>";
}
document.getElementById("text").innerHTML = x;
}
<p id="text"></p>
<button id="btn">Result</button>
<html>
<script>
var cars = ["audi", "bmw", "volvo"];
var x = "";
var count = 0;
function appendArray(){
if(count<cars.length){
x += cars[count]+ "<br>";
document.getElementById("appendText").innerHTML = x;
count++;
}else{
count = 0;
document.getElementById("appendText").innerHTML = "";
}
}
</script>
<p id="appendText"></p>
<button onclick="appendArray()">Submit</button>
</html>
Here is one solution in vanilla javascript:
var button = document.getElementsByTagName('button')[0];
var i = 0;
function addCar(i) {
var cars = ['audi', 'bmw', 'volvo'];
var paragraph = document.getElementsByTagName('p')[0];
if (i < cars.length) {
var newLine = document.createElement('br');
var newCar = document.createTextNode(cars[i]);
paragraph.appendChild(newLine);
paragraph.appendChild(newCar);
}
}
button.addEventListener('click',function(){addCar(i); i++;},false);
<p></p>
<button>Click for a New Car</button>
The issue is the radio button didn't come up. And I am confused with the concept of create node, create node text, create node value, createElement, etc. those kind of concepts.
Here is my code, http://jsfiddle.net/vadjn2an/
Here is my function,
function displayQuestion() {
var question = document.getElementById("question");
question.textContent = questionPool[currentQuestion].question;
var numberOfChoices = questionPool[currentQuestion].choices.length;
for(var i=0; i < numberOfChoices; i++) {
var label = document.createElement('label');
var radio = document.createElement('input');
radio.setAttribute('type', 'radio');
radio.setAttribute('name', 'choice');
radio.setAttribute('value', 'questionPool[currentQuestion].choices[i]');
label.appendChild(radio);
question.appendChild(label);
label.innerHTML = questionPool[currentQuestion].choices[i] + "<br>";
}
Thanks for your help in advance,
Try below code.
createTextNode
var questionPool = [
{
question: " Which is the biggest city in China?",
choices: ["Beijing", "Shanghai", "Guangzhou"],
correctAnswer: 1,
}
];
var question = document.getElementById("question");
var questionPool = questionPool[0];
question.textContent = questionPool.question;
for(var i=0;i<questionPool.choices.length;i++){
var label = document.createElement('label');
var radio = document.createElement('input');
radio.setAttribute('type', 'radio');
radio.setAttribute('name', 'choice');
radio.setAttribute('value', questionPool.choices[i]);
label.appendChild(radio);
var txt = document.createTextNode(questionPool.choices[i]);
label.appendChild(txt);
question.appendChild(label);
}
Here is the complete answer to your question. The HTML part
<form>
<label id="question">Question:</label><br />
<div id="answersBox">
</div>
<input type="button" value="save" />
</form>
The Javascript part
var questionPool = [
{
question: " Which is the biggest city in China?",
choices: ["Beijing", "Shanghai", "Guangzhou"],
correctAnswer: "Beijing",
}
];
var currentQuestion = questionPool[0].question;
document.getElementById('question').innerHTML = currentQuestion;
choiceList();
function choiceList() {
var question=questionPool[0];
for (choice in question.choices) {
var choiceSelection = document.createElement('input');
var choiceLabel = document.createElement('label');
choiceSelection.setAttribute('type', 'radio');
choiceSelection.setAttribute('name', 'choice');
choiceLabel.innerHTML=question.choices[choice];
choiceLabel.setAttribute('for', question.choices[choice]);
document.getElementById('answersBox').appendChild(choiceSelection);
document.getElementById('answersBox').appendChild(choiceLabel);
}
}
choiceList();
The reason it won't show up is because you replace label's innerHTML into
questionPool[currentQuestion].choices[i] + <br>.
when you append radio into label,label's innerHTML become "<input>...</input>"
but then you just replace it into
questionPool[currentQuestion].choices[i] + "<br>".
simple move the
label.innerHTML= ...
up before
label.appendChild can solve your situation.
here's a slightly modify answer without using innerHTML and outerHTML.
function displayQuestion() {
var question = document.getElementById("question"),
currentQuestion = 0,
numberOfChoices = questionPool[currentQuestion].choices.length;
question.textContent = questionPool[currentQuestion].question;
question.appendChild(document.createElement('br'));
for(var i=0; i < numberOfChoices; i++) {
var label = document.createElement('label'),
radio = document.createElement('input'),
textNode= document.createTextNode(questionPool[currentQuestion].choices[ i]),
lineBreakNode = document.createElement("br");
radio.setAttribute('type', 'radio');
radio.setAttribute('name', 'choice');
radio.setAttribute('value', 'questionPool[currentQuestion].choices[i]');
label.appendChild(radio);
label.appendChild(textNode);
label.appendChild(lineBreakNode);
question.appendChild(label);
}
}
http://jsfiddle.net/vadjn2an/9/
to have radio show before label, I use label.outerHTML to inject it as label's innerHTML
function displayQuestion() {
var question = document.getElementById("question");
var currentQuestion = 0;
var numberOfChoices = questionPool[currentQuestion].choices.length;
question.textContent = questionPool[currentQuestion].question;
question.appendChild(document.createElement('br'));
for(var i=0; i < numberOfChoices; i++) {
var label = document.createElement('label');
var radio = document.createElement('input');
radio.setAttribute('type', 'radio');
radio.setAttribute('name', 'choice');
radio.setAttribute('value', 'questionPool[currentQuestion].choices[i]');
label.innerHTML = radio.outerHTML + questionPool[currentQuestion].choices[i] + "<br/>";
question.appendChild(label);
}
}
http://jsfiddle.net/vadjn2an/8/
You need to append the radio button to question, please change the code line
from
label.appendChild(radio);
to
question.appendChild(radio);
Hope this helps!
My function that lists the question and choices won't work. I keep getting the error code document.getElementById(...) is null or not an object. The syntax appears to be correct.
I want the questions and choices to appear in the same divs. I do not want to list all my questions at once. When the user completes a question, they then move on to the next question which will appear in exactly the same divs as the first question until all the questions have been seen.
<script>
var questions = new Array();
questions[0] = 'Is there a difference between a jungle and a rain forest?'
questions[1] = 'What is the world\'s most common religion?',
questions[2] = 'What is the second largest country (in size) in the world?';
var choices = new Array();
choices[0] = ['No difference', 'Some difference', 'Completely different'],
choices[1] = ['Christianity', 'Buddhism', 'Hinduism', 'Islam'],
choices[2] = ['USA', 'China', 'Canada', 'Russia'];
var answers = new Array();
answers[0] = ['Some difference'],
answers[1] = ['Christianity'],
answers[2] = ['Canada'];
var score = 0;
i= 0;
var listQuestion = function(){
if( i < questions.length ){
document.getElementById("myDiv1").innerHTML = '<p>'+questions[i]+'</p>';
for (k=0; k<choices[i].length; k++){
document.getElementById("myDiv2").innerHTML ='<p><input type = "radio" name = "questionchoice">'+choices[i][k]+'</p>';
}
document.getElementById("myDiv3").innerHTML = '<p><button onClick = "getRadioValue()">Check</button></p> <br>';
};
};
var getRadioValue = function(){
for ( var h = 0; h < document.getElementsByName('questionchoice').length; h++ ){
var value = '';
if (document.getElementsByName('questionchoice')[h].checked==true){
value = document.getElementsByName('questionchoice')[h].value;
score+=1
}
}
if (value== answers[i]){
document.getElementById("myDiv4").innerHTML ="That is correct. </br><button input type = 'submit' onClick = 'loadContent()'> Next Question</button>";
}
else {
document.getElementById("myDiv4").innerHTML ="That is incorrect. </br><button input type = 'submit' onClick = 'loadContent()'> Next Question</button>";
}
i++;
};
var whatIsScore = function(){
return score;
}
window.onload = listQuestion();
</script>
</head>
<body>
<div id="myDiv1"></div>
<div id="myDiv2"></div>
<div id="myDiv3"></div>
<div id="myDiv4"></div>
</body>
Here is the full code:
<!DOCTYPE html>
<html>
<head>
<script>
var questions = new Array();
questions[0] = 'Is there a difference between a jungle and a rain forest?';
questions[1] = 'What is the world\'s most common religion?',
questions[2] = 'What is the second largest country (in size) in the world?';
var choices = new Array();
choices[0] = ['No difference', 'Some difference', 'Completely different'],
choices[1] = ['Christianity', 'Buddhism', 'Hinduism', 'Islam'],
choices[2] = ['USA', 'China', 'Canada', 'Russia'];
var answers = new Array();
answers[0] = ['Some difference'],
answers[1] = ['Christianity'],
answers[2] = ['Canada'];
var score = 0;
i= 0;
var listQuestion = function(){
if(i<questions.length){
document.getElementById("myDiv1").innerHTML = '<p>'+questions[i]+'</p>';
var choicesOutput=[];//new Array()
for (var k=0; k<choices[i].length; k++){
choicesOutput.push(
'<p><input type = "radio" name ='
+' "questionchoice">'+choices[i][k]+'</p>');
}
document.getElementById("myDiv2").innerHTML =choicesOutput.join("");
document.getElementById("myDiv3").innerHTML =
'<p><button onClick = "getRadioValue()">Check</button></p> <br>';
}
};
var getRadioValue = function(){
var value = '';
for (var h = 0;
h < document.getElementsByName('questionchoice').length; h++){
if (document.getElementsByName('questionchoice')[h]
.checked==true){
value = document.getElementsByName('questionchoice')[h].value;
score++;
}
}
if (value== answers[i]){
document.getElementById("myDiv4").innerHTML =
"That is correct. </br><button input type = "
+"'submit' onClick = 'loadContent()'> Next Question</button>";
}
else {
document.getElementById("myDiv4").innerHTML ="That is incorrect. "
+"</br><button input type = 'submit' onClick = 'loadContent()'> N"
+"ext Question</button>";
}
i++;
};
var whatIsScore = function(){
return score;
};
function loadContent(){
document.getElementById("myDiv4").innerHTML="";
listQuestion();
}
window.onload = listQuestion;
</script>
</head>
<body>
<div id="myDiv1"></div>
<div id="myDiv2"></div>
<div id="myDiv3"></div>
<div id="myDiv4"></div>
</body>
</html>