I'm making a personal quiz in javascript to see what clothing you want. Most of it works fine, except that the value that I give when I press an answer isn't right.
Html:
<div className="container">
<div id="question"></div>
<div id="answer"></div>
<button onClick="NextQuestion()" id="nextbtn">Next</button>
<button onClick="PrevQuestion()" id="prevbtn" style="display: none;">Previous</button>
<div id="finalLink"></div>
</div>
JS:
document.getElementById("finalLink").innerHTML =
"<a id='FLink' href='https://www.voetbalshop.nl/voetbalschoenen.html#' onClick='location.href=this.href getLink(url);return false;'>Result</a>";
class QuizPart {
constructor(questionDescription, chosenAnswer, prefix) {
this.questionDescription = questionDescription;
this.chosenAnswer = chosenAnswer;
this.prefix = prefix;
}
}
class ChosenAnswer {
constructor(id, name) {
this.id = id;
this.name = name;
}
}
let Quiz = [
new QuizPart('Whats your size?', [
new ChosenAnswer('6595', '41'),
new ChosenAnswer('6598', '42'),
new ChosenAnswer('6601', '43'),
], 'bd_shoe_size_ids='),
new QuizPart('What color would you like?', [
new ChosenAnswer('6053', 'Red'),
new ChosenAnswer('6044', 'Blue'),
new ChosenAnswer('6056', 'Yellow'),
new ChosenAnswer('6048', 'Green'),
], 'color_ids='),
new QuizPart('What brand would you like?', [
new ChosenAnswer('5805', 'Adidas'),
new ChosenAnswer('5866', 'Nike'),
new ChosenAnswer('5875', 'Puma'),
], 'manufacturer_ids='),
]
// console.log(Quiz);
let url = [];
let questionNumber = -1;
let button = document.getElementById('answer');
let questionName = document.getElementById('question');
let nextbtn = document.getElementById('nextbtn');
let prevbtn = document.getElementById('prevbtn')
let resultbtn = document.getElementById('FLink');
function NextQuestion() {
// adds 1 to question to see a different question
questionNumber ;
let oldAnswerButton = document.querySelectorAll('.filter_anwser');
// Deletes old question when the next question is clicked
for (let answerButton of oldAnswerButton) {
answerButton.style.display = 'none';
}
let question = Quiz[questionNumber];
// Displays answers of the questions
for (let y = 0; y < question.chosenAnswer.length; y ) {
let item = question.chosenAnswer[y];
// Display answer buttons
let btn = document.createElement('button');
btn.value = item.id;
btn.className = "filter_anwser";
btn.textContent = item.name;
button.appendChild(btn);
}
// Check if your at the last question so the next button will stop being displayed.
if (questionNumber > 0) {
prevbtn.style.display = 'block';
} else {
prevbtn.style.display = 'none';
}
if (Quiz.length - 1 <= questionNumber) {
nextbtn.style.display = 'none';
resultbtn.style.display = 'grid';
} else {
nextbtn.style.display = 'block';
resultbtn.style.display = 'none';
}
// Displays Question
questionName.textContent = question.questionDescription;
questionName.id = "questionID";
}
function PrevQuestion() {
questionNumber--;
let oldAnswerButton = document.querySelectorAll('.filter_anwser');
// Deletes old question when the next question is clicked
for (let answerButton of oldAnswerButton) {
answerButton.style.display = 'none';
}
let question = Quiz[questionNumber];
// Displays answers of the questions
for (let y = 0; y < question.chosenAnswer.length; y ) {
let item = question.chosenAnswer[y];
// Display answer buttons
let btn = document.querySelector('button[value="' item.id '"]');
btn.style.display = 'block';
}
//Check if your at the last question so the next button will stop being displayed.
if (questionNumber < Quiz.length - 1) {
nextbtn.style.display = 'block';
}
if (questionNumber <= 0) {
prevbtn.style.display = 'none';
} else {
prevbtn.style.display = 'block';
}
if (Quiz.length - 1 <= questionNumber) {
resultbtn.style.display = 'grid';
} else {
resultbtn.style.display = 'none';
}
// Displays Question
questionName.textContent = question.questionDescription;
questionName.id = "questionID";
}
/**
* Returns the paremeters for the URL.
*
* @param {Array} url The parameters .... .
*/
function getLink(url) {
let tmp = [];
for (let i = 0; i < url.length; i ) {
// Check if question is from the same quiz part and adds a , between chosen answers and add the right prefix at the beginning
if (url[i].length > 0) {
tmp.push("" Quiz[i].prefix url[i].join(","))
}
}
/// If answers are from different quiz parts add a & between answers.
console.log(url, questionNumber);
return "" tmp.join("&");
};
button.addEventListener("click", function (e) {
const tgt = e.target;
// clear the url array if there's nothing clicked
if (url.length < questionNumber) {
url.push([]);
}
let quizUrl = url[questionNumber - 1];
// Check if a button is clicked. Changes color and adds value to the url array.
if (quizUrl.indexOf(tgt.value) === -1) {
quizUrl.push(tgt.value);
e.target.style.backgroundColor = "orange";
// Check if a button is clicked again. If clicked again changes color back and deletes value in the url array.
} else {
quizUrl.splice(quizUrl.indexOf(tgt.value), 1);
e.target.style.backgroundColor = "white";
}
console.log(getLink(url));
})
When I open my site it shows the beginning and when I start the quiz I see my first question with all the answers beneath, but when I click on an answer of the first question I get an error and with the second question, it shows the right value, but in the prefix of the first question etc. It basically always sets the value to the previous question.
Too make it a little clearer all the answers that you give are collected in one variable (url). At the end it look something like this:
bd_shoe_size_ids=6732,4765&color_ids=3846,4635&manufacturer_ids=4563,3456
The text in the variable are the questions and the id's the answers that you clicked. When I click on an answer that belongs to manufacturer_ids it sets the answer goes to color_ids abd when click an answer that blongs to color it goed to shoe size.
Can anybody help me with this?
The error that the first question gives is as following:
(index):188 Uncaught TypeError: Cannot read properties of undefined (reading 'indexOf') at HTMLDivElement. ((index):188)
CodePudding user response:
To clear an array, set it to [] or call splice.
Not Correct
if (url.length < questionNumber) {
url.push([]);
}
Correct
url = []
// or
url.splice(0, url.length)
Then there is this
let quizUrl = url[questionNumber - 1];
If you clear it and not return, that will throw an error.
Put a log statement before this line.
console.log(url)
let quizUrl = url[questionNumber - 1];
As this line might be the culprit.
quizUrl.indexOf(quizUrl)
In fact, I do not even see where you add anything to your url
array besides pushing an empty array.
CodePudding user response:
I'm surprised nobody found out the obvious problem. You have:
let questionNumber = -1;
//...
function NextQuestion() {
questionNumber ;
//...
}
function PreviousQuestion() {
questionNumber--;
//...
}
So your questionNumber is 0-indexed (first question is 0, second 1, etc.)
The way you fetch the current quizUrl
is wrong:
let quizUrl = url[questionNumber - 1];
For the first question (questionNumber=0
) you get url[-1]
which is undefined, thus your error.
You should use:
let quizUrl = url[questionNumber];
You can easily debug these kind of errors with a debugger. (see for instance https://developer.chrome.com/docs/devtools/javascript/ if you use Chrome)