I'm trying to develop logic for a quiz - Fiddle here. I've looked at similar projects such as here and here. However, their solutions did not work for my quiz; I'm using plain Javascript.
The question path develops a tree structure. For example, the first question asks what type of wine do you like? If you choose red it asks if you prefer sparkling or still. Ultimately the branches lead to a result that is displayed.
The problem here is I cannot even get to the second set of questions and choices.
Could there be something wrong with my questions array object variable?
I've managed to connect my buttons to the first two labels (white and red) inside the beginQuiz function, so the function can access the tree top. However, if I try to access any deeper into the array I get an undefined error.
for example (showQuestion function):
topBtn.innerHTML = questions[questionIndex].question.choices.label;
bottomBtn.innerHTML = questions[questionIndex].question.choices.label;
The question area shows undefined after I click either of the choice buttons.
I get this error:
Uncaught TypeError: Cannot read properties of undefined (reading 'question')
I'm able to get the first question and set of choices inside the beginQuiz function, but not able to progress to the next set. What am I doing wrong?
How do I get it to click through to the next set of questions and labels and display them?
Thanks in advance for any help.
const questions = [
{
question: {
text: 'What type of wine do you like?',
choices: [
{
label: 'white',
path: 1,
question: {
text: 'I prefer...',
choices: [
{
label: 'sparkling',
path: 11,
},
{
label: 'still',
path: 12,
},
],
},
},
{
label: 'red',
path: 2,
question: {
text: 'I prefer...',
choices: [
{
label: 'sparkling',
path: 21,
},
{
label: 'still',
path: 22,
},
],
},
},
],
},
},
];
topBtn.addEventListener('click', nextQuestion);
bottomBtn.addEventListener('click', nextQuestion);
restartBtn.addEventListener('click', restart);
let questionIndex = 0;
function beginQuiz() {
let questionIndex = 0;
questionText.innerHTML = questions[questionIndex].question.text;
topBtn.innerHTML = questions[questionIndex].question.choices[0].label;
topBtn.addEventListener('click', () => {
if (questionIndex < 2) {
nextQuestion();
}
});
bottomBtn.innerHTML = questions[questionIndex].question.choices[1].label;
bottomBtn.addEventListener('click', () => {
if (questionIndex < 2) {
nextQuestion();
}
});
}
beginQuiz();
function showQuestion() {
questionText.innerHTML = questions[questionIndex];
topBtn.innerHTML = questions[questionIndex].question.choices.label;
bottomBtn.innerHTML = questions[questionIndex].question.choices.label;
}
function nextQuestion() {
questionIndex ;
showQuestion();
}
CodePudding user response:
const restartBtn = document.getElementById('restart');
const topBtn = document.getElementById('top-btn');
const bottomBtn = document.getElementById('bottom-btn');
const questionText = document.querySelector('.question');
const choiceText = document.querySelector('.choices');
const resultText = document.querySelector('.result');
const questions = [
{
question: {
text: 'What type of wine do you like?',
choices: [
{
label: 'white',
path: 1,
question: {
text: 'I prefer...',
choices: [
{
label: 'sparkling',
path: 11,
},
{
label: 'still',
path: 12,
},
],
},
},
{
label: 'red',
path: 2,
question: {
text: 'I prefer...',
choices: [
{
label: 'sparkling',
path: 21,
},
{
label: 'still',
path: 22,
},
],
},
},
],
}, // index 0
},
{
question: {
text: 'Another more question?',
choices: [
{
label: 'this is my answer',
path: 1,
question: {
text: 'I prefer...',
choices: [
{
label: 'sparkling',
path: 11,
},
{
label: 'still',
path: 12,
},
],
},
},
{
label: 'another answer',
path: 2,
question: {
text: 'I prefer...',
choices: [
{
label: 'sparkling',
path: 21,
},
{
label: 'still',
path: 22,
},
],
},
},
],
}, // index 1
},
];
topBtn.addEventListener('click', nextQuestion);
bottomBtn.addEventListener('click', nextQuestion);
restartBtn.addEventListener('click', restart);
let questionIndex = 0;
function beginQuiz() {
let questionIndex = 0;
console.log(questionIndex, "index");
questionText.innerHTML = questions[questionIndex].question.text;
console.log(questions[questionIndex], "test");
topBtn.innerHTML = questions[questionIndex].question.choices[0].label;
topBtn.addEventListener('click', () => {
if (questionIndex < 3) {
nextQuestion();
}
});
bottomBtn.innerHTML = questions[questionIndex].question.choices[1].label;
bottomBtn.addEventListener('click', () => {
if (questionIndex < 3) {
nextQuestion();
}
});
}
beginQuiz();
function showQuestion() {
questionText.innerHTML = questions[questionIndex].question.text;
topBtn.innerHTML = questions[questionIndex].question.choices[0].label;
bottomBtn.innerHTML = questions[questionIndex].question.choices[1].label;
console.log( questions[questionIndex].question.choices[0].label, " questionText.innerHTML");
}
function nextQuestion() {
questionIndex ;
showQuestion();
}
function restart() {
questionIndex = 0;
currentQuestion = 0;
document.getElementById('question').style.display = 'block';
document.getElementById('choices').style.display = 'block';
document.getElementById('result').style.display = 'none';
topBtn.classList.remove('hide');
bottomBtn.classList.remove('hide');
beginQuiz();
}
function findProp(obj, prop) {
let result = [];
function recursivelyFindProp(o, keyToBeFound) {
Object.keys(o).forEach(function (key) {
if (typeof o[key] === 'object') {
recursivelyFindProp(o[key], keyToBeFound);
} else {
if (key === keyToBeFound) result.push(o[key]);
}
});
}
recursivelyFindProp(obj, prop);
return result;
}
console.log(findProp(questions, 'label'));
console.log(findProp(questions, 'text'));
console.log(findProp(questions, 'path'));
body {
background-color: darkkhaki;
font-family: serif;
}
h1 {
color: white;
text-align: center;
}
.container {
background-color: darkgoldenrod;
position: relative;
display: grid;
justify-content: center;
align-items: center;
text-align: center;
color: #fafafa;
padding: 20px;
border: 2px solid #fff;
border-radius: 20px;
}
.question {
font-size: 2em;
width: 90%;
height: auto;
margin: auto;
border-radius: 6px;
text-align: center;
}
.choices {
font-family: Courier, serif;
color: white;
margin-top: 2em;
}
.choice {
cursor: pointer;
font-size: 2em;
text-align: center;
}
.btn {
background-color: transparent;
color: #fff;
font-size: 12px;
text-transform: uppercase;
border: 3px solid #fff;
border-radius: 10px;
padding: 10px 20px;
margin: 10px;
cursor: pointer;
outline: none;
transition: all 0.5s ease;
}
.btn:hover {
background-color: #fff;
color: darkgoldenrod;
}
<body>
<header><h1>Wine chooser</h1></header>
<!--Quiz Box -->
<div >
<div id="question"></div>
<div id="choices"></div>
<button id="top-btn"></button>
<button id="bottom-btn"></button>
<div id="result"></div>
</div>
<div >
<button id="restart">Restart</button>
</div>
<script src="test3.js"></script>
</body>
CodePudding user response:
In your code when I hard code the index like this with [0]:
questionText.innerHTML = questions[0].question.text;
topBtn.innerHTML = questions[0].question.choices[0].label;
I indeed get the first question and choices/answers.
However, when I do this [1]:
questionText.innerHTML = questions[1].question.text;
topBtn.innerHTML = questions[1].question.choices[0].label;
I get undefined!
This tells me that it's a problem with how you set up your data structures and how you're iterating through them. There's nothing to be found at index 1. Because you have nothing there atm.
Also you forgot to to add index numbers for labels i.e answers at line 121 in jsfiddle.
questionText.innerHTML = questions[questionIndex].question.text;
topBtn.innerHTML =
questions[questionIndex].question.choices[0].label;
bottomBtn.innerHTML =
questions[questionIndex].question.choices[1].label;