stuck on get the answers for each question, quiz - javascript

Please help me with this exercise!
I got an API link https://opentdb.com/api.php?amount=10 and I have to get the data from that API to make a simple quiz with javascript (yes SIMPLE but I can’t figure out how to do it, difficult for me). The problem is I did get the questions appear on the page but 10 questions have the same answers. I mean it should be 10 questions with 10 different arrays with different answers inside. I'm stuck here and don't know how to do it.:(
$.getJSON(url, function (data) {
var myQuestions = data.results;
for (question of myQuestions) {
var correctAnswer = question.correct_answer;
var totAnswers = question.incorrect_answers;
totAnswers.push(correctAnswer);
// console.log(totAnswers);
}
function buildQuiz() {
const output = [];
myQuestions.forEach((currentQuestion, questionNumber) => {
const answers = [];
for (value of totAnswers) {
console.log(value);
answers.push(
`<label>
<input type="radio" name="question${questionNumber}" value="${value}">
${value}
</label>`
);
}
output.push(
`<div class="slide">
<div class="question"> ${currentQuestion.question} </div>
<div class="answers"> ${answers.join("")} </div>
</div>`
);
});
quizContainer.innerHTML = output.join('');
}
Here is how it looks like now:
I think that the problem is where I use the loop for the totAnswers variable. But I don’t understand why.
Can anyone give me some tips please?

I can't understand why are you forming totAnswers
What you want to achieve can be done like this:
function buildQuiz() {
const output = myQuestions.map((currentQuestion, questionNumber) => (
`<div class="slide">
<div class="question">
${currentQuestion.question}
</div>
<div class="answers">
${currentQuestion.incorrect_answers.concat(currentQuestion.correct_answer).join('')}
</div>
</div>`))
quizContainer.innerHTML = output.join('');
};

Related

Buttons are not working properly with addEventListener [duplicate]

This question already has answers here:
What do querySelectorAll and getElementsBy* methods return?
(12 answers)
Closed 3 months ago.
I have tried the answers given on the similar questions but I really can't do this one and I actually have no idea what I am supposed to do which is why I made this new question. The respective counter is supposed increase by one each time the respective countUp button is clicked. But now, I got NaN in both counter when I click on the first countUp button. Could you please help? Thank you.
const countUp = document.querySelectorAll('.countUp')
const countDown = document.querySelector('.countDown')
const counter = document.querySelectorAll('.num')
let count = counter.textContent
countUp.forEach((countUp) => {
countUp.addEventListener('click', () => {
counter.forEach((countUp) => {
count++
countUp.innerHTML = count
})
})
});
<div class="rating">
<button class="countUp">+</button>
<span class="num">0</span>
<button class="countDown">-</button>
</div>
<div class="rating">
<button class="countUp">+</button>
<span class="num">0</span>
<button class="countDown">-</button>
</div>
You cannot access the relative span using querySelectorAll. It returns a collection
If you delegate and navigate relatively among siblings, you can save a lot of code and headaches
const container = document.getElementById("container");
container.addEventListener('click', (e) => {
const tgt = e.target.closest("button");
if (!tgt) return; // or use e.target and test tgt.matches("button")
const numSpan = tgt.closest(".rating").querySelector(".num");
if (numSpan.matches(".clicked")) return; // already clicked
numSpan.classList.add("clicked");
let num = +numSpan.textContent;
num += tgt.classList.contains("countUp") ? 1 : -1;
numSpan.textContent = num;
});
<div id="container">
<div class="rating">
<button class="countUp">+</button>
<span class="num">1</span>
<button class="countDown">-</button>
</div>
<div class="rating">
<button class="countUp">+</button>
<span class="num">0</span>
<button class="countDown">-</button>
</div>
</div>

Cant get js values to link to HTML elements

Im currently working on a timed quiz application and got a majority of the functionality working. But, when I went to test it I noticed the question element I set up in the HTML wasn't changing with the question objects I defined in the js file. The two files are linked together correctly, but I can't figure out where I went wrong. Tbh after looking at this for hours a fresh set of eyes would really come in handy.
HTML:
<body>
<div class="container">
<div id="game" class="justify-center">
<div id="hud">
<div class="hud-item">
<!-- container desc -->
<p id="container-text" class="hud-prefix">
Question:
</p>
<!-- timer function -->
<div id="timer">
</div>
<!-- end of timer -->
</div>
<div class="hud-item">
<p class="hud-prefix">
Score:
</p>
<h1 class="hud-main-text" id="score">
0
</h1>
</div>
</div>
<h1 id="question">What is the answer?</h1>
<!-- making possible answers to given question -->
<div class="choice-container">
<p class="choice-prefix">A</p>
<p class="choice-text" data-number="1">Choice 1</p>
</div>
<!-- making possible answers to given question -->
<div class="choice-container">
<p class="choice-prefix">B</p>
<p class="choice-text" data-number="2">Choice 2</p>
</div>
<!-- making possible answers to given question -->
<div class="choice-container">
<p class="choice-prefix">C</p>
<p class="choice-text" data-number="3">Choice 3</p>
</div>
<!-- making possible answers to given question -->
<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="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="./assets/script.js"></script>
Here is my JavaScript file:
const question = $('#question');
const choices = Array.from($('.choice-text'));
const scoreText = $('#score');
//defining let var which values will change throughout the game
let currentQuestion = {};
let acceptingAnswers = true;
let score = 0;
let questionCounter = 0;
let availableQustions = [];
//defining list of potential questions to be called apon by currentQuestions
let questions = [
{
question: 'What types of variables can you define?',
choice1: 'var',
choice2: 'let',
choice3: 'const',
choice4: 'all of the above',
answer: 'all of the above'
},
// question 1 ^^^^
{
question: 'How would you store an item to local storage?',
choice1: 'localStorage.getItem()',
choice2: 'localStorage.setItem()',
choice3: 'localStorage.store()',
choice4: 'localStorage.setLocal()',
answer: 'localStorage.setItem()'
},
// question 2 ^^^^
]
console.log(questions)
//start game functionality and needed var
const SCORE_POINTS = 100;
const MAX_QUESTIONS = 10;
startGame = () => {
questionCounter = 0;
score = 0;
availableQustions = [...questions];
getNewQuestion();
}
//get new question function supplies new q when previous gets answered
getNewQuestion = () => {
if(availableQustions.length === 0 || questionCounter > MAX_QUESTIONS) {
localStorage.setItem('mostRecentScore', score)
return window.location.assign('/end.html')
}
questionCounter++
//making random question appear
const questionIndex = Math.floor(Math.random() * availableQustions.length)
currentQuestion = availableQustions[questionIndex]
question.innerHTML = currentQuestion.question
//was originally choices.array.forEach
choices.forEach((choice)=> {
const number = choice.dataset['number'];
choice.innerText = currentQuestion['choice' + number];
});
availableQustions.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']
let classToApply = selectedAnswer == currentQuestion.answer ? 'correct' : 'incorrect'
//if answer is correct add 100 to score
if (classToApply === 'correct') {
incrementScore(SCORE_POINTS)
}
selectedChoice.parentElement.classList.add(classToApply)
setTimeout(() => {
selectedChoice.parentElement.classList.remove(classToApply)
getNewQuestion();
}, 1000)
})
});
//increment score funt and calling start game
incrementScore = num => {
score += num
scoreText.innerText = score
}
startGame();
I originally had ten questions but I deleted the other 8 because of stacks code to normal text ratio.
The problem that is happening is the questions aren't toggling red and green for correct and wrong answers. and the questions aren't displaying on the #question HTML element.
Heres the CSS for the correct and wrong bits
.correct {
background-color: green;
border: green 4px solid;
}
/* will change wrong answer color to red */
.wrong {
background-color: red;
border: red 4px solid;
}

How to modify/delete an object from localStorage?

I am currently in apprenticeship and I am having a problem.
I must be able to modify the quantity of the product or remove it from my basket. (therefore modify the localStorage)
But I cannot do it, I am aware that this question must have been asked several times.
But I can't find an answer to my problem among the many documentations, I must go about it wrong.
let basket = JSON.parse(localStorage.getItem("Sofas")) || [];
const cartItems = document.getElementById("cart__items");
contentBaskets = [];
function onQuantityChange(id) {
}
for (let i = 0; i < basket.length; i++) {
fetch("http://localhost:3000/api/products/" + basket[i].id)
.then((response) => response.json())
.then((data) => {
contentBaskets =
contentBaskets +
`<article class="cart__item" data-id=${basket[i].id}>
<div class="cart__item__img">
<img src=${data.imageUrl}>
</div>
<div class="cart__item__content">
<div class="cart__item__content__titlePrice">
<h2>${data.name}</h2>
<p>${data.price}€</p>
</div>
<div class="cart__item__content__settings">
<p>Couleur : ${basket[i].color}</p>
<div class="cart__item__content__settings__quantity">
<p>Qté : </p>
<input type="number" class="itemQuantity" name="itemQuantity" min="1" max="100" value=${basket[i].quantity} onchange=onQuantityChange('${basket[i].id}')>
</div>
<div class="cart__item__content__settings__delete">
<p class="deleteItem">Supprimer</p>
</div>
</div>
</div>
</article>`;
if (basket.length) {
cartItems.innerHTML = contentBaskets;
}
});
}
I'm not sure what's your question, but here's how to edit an object in localStorage.
// Get the string that's stored in localStorage
const stored = localStorage.getItem("sofas")
// Parse
const array = JSON.parse(stored) || []
// Push a new sofa to the array
array.push("IKEA Friheten")
// Set to localStorage the stringified version
// of the array, so you can get it later
localStorage.setItem("sofas", JSON.stringify(array))

How to get the value of a specific element in a div when clicked?

I'm making a search engine program. People can ask questions and it will be listed in a different div. People can then click a question listed to answer it, and the answer (and that particular question) will be listed in another div.
But my code only shows the last question entered in the answer list. So if there are 3 questions and a user answered the first one, the expected output is:
Question 1?
Ans: Answer 1
But the actual output is:
Question 3?
Ans: Answer 1
function separate()
{
var question = document.createElement("p");
question.innerHTML = document.getElementById("qInput").value;
document.getElementById("stackDisplay").appendChild(question);
question.addEventListener("click", answerBox);
}
function answerBox(ques)
{
document.getElementById("answerBox").style.display = "block";
}
var i =1;
function collectAns() {
if(event.key === 'Enter') {
var quest = document.getElementById("qInput").value;
var ans = document.getElementById("ansSpace").value;
document.getElementById("ansDisplay").innerHTML += i+") "+quest+"<br> Ans: "+ans+"<br><br>";
document.getElementById("answerBox").style.display = "none";
i+=1;
}
}
<div class="search">
<input type="text" placeholder="Search.." name="search" id="qInput">
<button type="submit" onclick="separate()">
<i class="fa fa-search"></i>
</button>
</div>
<div class="stack">
<span id="stackDisplay">
<center><b><u> LIST OF QUESTIONS</u></b></center>
<button id="close" onmouseover="clo()"> × </button>
</span>
<button onmouseover="list()"> ☰ </button>
</div>
<div class="ans">
<span id="ansDisplay">
<center><b><u> LIST OF ANSWERS</u></b></center>
<button id="closeans" onmouseover="closeans()"> × </button>
</span>
<button onmouseover="listans()">
<i class="fa fa-commenting-o"></i>
</button>
</div>
<div id="answerBox">
<center><b> Write your answer:</b></center>
<button id="closeans" onmouseover="closeansbox()"> × </button>
<textarea id="ansSpace" placeholder="Your answer here..." onkeydown="collectAns()"></textarea>
</div>
I know it's because of var quest = document.getElementById("qInput").value; so it only takes the last question, but I don't know what to write instead of this.
I tried adding question.addEventListener("click", function(){collectAns(ques)}); in the separate() but it prints undefined instead of the question.
I tried adding var q = document.getElementById("stackDisplay").children; in the collectAns() but I don't know which question they'll click so I can't give the index, so I wrote q[this] when printing, and it still gives undefined.
What should I do to make it show the question? (without jquery or php if possible, just html, css, javascript)
I removed unnecessary stuff to answer the question.
The idea is to call collectAns with the question as argument. To do that you can use the bind method.
As you are adding eventListners, you will need to remove old ones to prevent them to be executed too. The difficulty to remove old ones is that you don't know their name, they are anonymous because of the use of bind. You could store them in an array but it is simplier to clone the node, which do not clone the eventlistners attached to it.
function separate() {
var question = document.createElement("li");
question.innerHTML = document.getElementById("qInput").value;
document.getElementById("stackDisplay").appendChild(question);
question.addEventListener("click", answerBox);
}
function answerBox() {
const answerbox = document.getElementById("answerBox");
const question = this.innerText;
answerbox.querySelector('.ques').innerText = question;
// find textarea, clone it and remove it
// this is to remove any eventListener from it.
const textarea = answerbox.querySelector('textarea');
const new_textarea = textarea.cloneNode();
textarea.remove();
// add new eventListner with question as parameter
new_textarea.addEventListener('keydown', collectAns.bind(null, this.innerText));
answerbox.appendChild(new_textarea);
// display answer box
answerbox.style.display = "block";
}
var i = 1;
function collectAns(ques) {
if (event.key === 'Enter') {
var ans = document.getElementById("ansSpace").value;
document.getElementById("ansDisplay").innerHTML += i + ") " + ques + "<br> Ans: " + ans + "<br><br>";
document.getElementById("answerBox").style.display = "none";
i += 1;
}
}
<div class="search">
<input type="text" placeholder="Question.." name="search" id="qInput">
<button type="submit" onclick="separate()">
add
</button>
</div>
<h4>LIST OF QUESTIONS:</h4>
<ul id="stackDisplay"></ul>
<h4>LIST OF ANSWERS</h4>
<ul id="ansDisplay"></ul>
<div id="answerBox">
<div>Write your answer to question "<span class="ques"></span>":</div>
<textarea id="ansSpace" placeholder="Your answer here..."></textarea>
</div>

HTML multiple choice quiz

I am working on an HTML quiz recently, which is a page shown before a company page we use in my department. If the user answers correctly, then he can get the link to the page he needs to work.
However, when he answers wrongly, he gets a message and he can answer again, but the "Wrong Answer" that he got previously is still shown. That is what i don't want to happen.
The code of the quiz.js file is shown below. Also i post the HTML code of the answer section.
$(document).ready(function()
{
$("#results").click(function() {
if (!$("input[#name=q1]:checked").val())
{
alert("You're not done yet!");
}
else
{
var cat1name = "1";
var cat11name = "None";
var cat1 = ($("input[#name=q1]:checked").val() != "b"); // correct answer
var cat11 = (!cat1); var categories = [];
if (cat1) { categories.push(cat1name) };
if (cat11) { categories.push(cat11name) };
var catStr = 'You answered the following questions incorrectly: ' + categories.join(', ') + '';
$("#categorylist").text(catStr);
$("#categorylist").show("slow");
if (cat1) { $("#category1").show("slow"); };
if (cat11) { $("#category11").show("slow"); };
{ $("#closing").show("slow"); };
}
});
});
<div id="results">
Answer
</div>
<div id="category1">
<p>
<strong>Wrong answer!</strong>
</p>
</div>
<div id="category11">
<p>You answered correctly!</p>
<p><a href="somelink</a></p>
</div>
</div>
</body>
</html>

Categories

Resources