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;
}
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 days ago.
Improve this question
I am coding a simple Javascript chatbot and need help on how to make the choices cookBtn and englishBtn to work as well as how I finish from Bound Book, Pocket Book and Chaged My Mind to "Thank you for your order (name), we will ship out right away.
Please find my js code below.
// All the DOM selectors stored as short variables
const chat = document.getElementById("chat");
const formWrapper = document.getElementById('formWrapper');
const messageSound = new Audio ("assets/pop.mp3");
const timeGreetings = [`Good morning my friend! What's your name?`, `Hello my friend! What's your name?`, `Good evening my friend! What's your name?`, `I am sorry my friend, but we are closed!`];
// Variable for date & time.
const date = new Date();
console.log(date);
const time = date.getHours();
console.log(time);
const greetUser = (timeGreetings, time) => {
if (time >= 5 && time <= 10) {
showMessage(timeGreetings[0], "bot"); //Morning (5 to 10)
} else if (time > 10 && time <= 18) {
showMessage(timeGreetings[1], "bot"); //Hello (11 to 18)
} else if (time > 18 && time <= 22) {
showMessage(timeGreetings[2], "bot"); //Evening (19 to 22)
} else {
showMessage(timeGreetings[3], "bot"); //Late (23 to 4)
showMessage("Anyways, since you're up. What's your name?", "bot");
}
};
//1 second delay for greeting
setTimeout(greetUser, 1000, timeGreetings, time);
//--This is the general way of adding a chat bubble from both the user and the bot. Create more detailed ones for what we want to do later.
const showMessage = (msg, sender) => {
if (sender === 'user') {
chat.innerHTML += `<section class="user-msg">
<div class="bubble user-bubble">
<p>${msg}</p>
</div>
<img src="./user.png" alt="chat bot" />
</section>`;
}
else if (sender === 'bot') {
chat.innerHTML += `<section class="bot-msg">
<img src="./bot.png" alt="user bot" />
<div class="bubble bot-bubble">
<p>${msg}</p>
</div>
</section>`;
}
//Makes sound when sending a message
messageSound.currentTime = 0
messageSound.play()
// This little thing makes the chat scroll to the last message when there are too many to be shown in the chat box
chat.scrollTop = chat.scrollHeight;
};
//Eventlistener: Starts the function when user clicks submit.
form.addEventListener('submit', (event) => {
event.preventDefault() //Stops it from autosaving.
const firstName = document.getElementById('firstName').value;
console.log(firstName)
// Calling the function "showMessage".
showMessage(firstName, 'user');
//This code slows it with 1 sec.
setTimeout(() => recognize(firstName), 1000)
})
//Question 2
const recognize = (firstName) => {
console.log(firstName);
chat.innerHTML += `<section class="bot-msg">
<img src="./bot.png" alt="user bot" />
<div class="bubble bot-bubble">
<p>Which book would you like ${firstName}?</p>
</div>
</section>`;
console.log(formWrapper);
formWrapper.innerHTML = `<button id="yogaBtn">How to Yoga book</button>
<button id="cookBtn">How to cook book</button>
<button id="englishBtn">Learn English book</button>`;
let yogaBtn = document.getElementById('yogaBtn');
yogaBtn.addEventListener('click', () => choiceBook())
let cookBtn = document.getElementById('cookBtn');
cookBtn.addEventListenerById('click',() => choiceBook())
let englishBtn = document.getElementById('englishBtn');
englishBtn.addEventListenerById('click',() => choiceBook())
}
/*
setTimeout(() => choiceBook(firstName), 1000)
*/
// Question number 3
const choiceBook = (firstName) => {
chat.innerHTML += `<section class="bot-msg">
<img src="./bot.png" alt="user bot" />
<div class="bubble bot-bubble">
<p>Which book would you like ${firstName}?</p>
</div>
</section>`;
showMessage(`Would you like bound or pocket book, ${firstName}?`, 'bot');
formWrapper.innerHTML =
`<button id="boundBtn" type="submit" value="Bound book">Bound Book</button>
<button id="pocketBtn" type="submit" value="Pocket book">Pocket Book</button>
<button id="neverMindBtn" type="submit" value="Changed my mind">Changed my mind</button>`
let boundBtn = document.getElementById('boundBtn');
boundBtn.addEventListener('click',() => choiceBook())
let pocketBtn = document.getElementById('pocketBtn');
pocketBtn.addEventListener('click',() => choiceBook())
let neverMindBtn = document.getElementById('neverMindBtn');
neverMindBtn.addEventListener('click',() => choiceBook())
}
I think I need to do else, else if and if to access the other replies, but I can't seem to get them working.
This question already has answers here:
Why does jQuery or a DOM method such as getElementById not find the element?
(6 answers)
Closed 1 year ago.
My Issue:
Please help me run this code as it should. I am getting a null form error when typing a City name in the place holder and I'm not sure why I am practicing this code from here: https://webdesign.tutsplus.com/tutorials/build-a-simple-weather-app-with-vanilla-javascript--cms-33893
/*SEARCH BY USING A CITY NAME (e.g. athens) OR A COMMA-SEPARATED CITY NAME ALONG WITH THE COUNTRY CODE (e.g. athens,gr)*/
const form = document.querySelector(".top-banner form");
const input = document.querySelector(".top-banner input");
const msg = document.querySelector(".top-banner .msg");
const list = document.querySelector(".ajax-section .cities");
/*SUBSCRIBE HERE FOR API KEY: https://home.openweathermap.org/users/sign_up*/
const apiKey = "f077e7d6167270fa866a36699ab528fe"; /*REPLACE THIS WITH YOUR API KEY FROM OPENWEATHERMAP.ORG*/
form.addEventListener("submit", e => {
e.preventDefault();
let inputVal = input.value;
//check if there's already a city
const listItems = list.querySelectorAll(".ajax-section .city");
const listItemsArray = Array.from(listItems);
if (listItemsArray.length > 0) {
const filteredArray = listItemsArray.filter(el => {
let content = "";
//athens,gr
if (inputVal.includes(",")) {
//athens,grrrrrr->invalid country code, so we keep only the first part of inputVal
if (inputVal.split(",")[1].length > 2) {
inputVal = inputVal.split(",")[0];
content = el
.querySelector(".city-name span")
.textContent.toLowerCase();
} else {
content = el.querySelector(".city-name").dataset.name.toLowerCase();
}
} else {
//athens
content = el.querySelector(".city-name span").textContent.toLowerCase();
}
return content == inputVal.toLowerCase();
});
if (filteredArray.length > 0) {
msg.textContent = `You already know the weather for ${
filteredArray[0].querySelector(".city-name span").textContent
} ...otherwise be more specific by providing the country code as well 😉`;
form.reset();
input.focus();
return;
}
}
//ajax here
const url = `https://api.openweathermap.org/data/2.5/weather?q=${inputVal}&appid=${apiKey}&units=metric`;
fetch(url)
.then(response => response.json())
.then(data => {
const {
main,
name,
sys,
weather
} = data;
const icon = `https://s3-us-west-2.amazonaws.com/s.cdpn.io/162656/${
weather[0]["icon"]
}.svg`;
const li = document.createElement("li");
li.classList.add("city");
const markup = `
<h2 class="city-name" data-name="${name},${sys.country}">
<span>${name}</span>
<sup>${sys.country}</sup>
</h2>
<div class="city-temp">${Math.round(main.temp)}<sup>°C</sup></div>
<figure>
<img class="city-icon" src="${icon}" alt="${
weather[0]["description"]
}">
<figcaption>${weather[0]["description"]}</figcaption>
</figure>
`;
li.innerHTML = markup;
list.appendChild(li);
})
.catch(() => {
msg.textContent = "Please search for a valid city 😩";
});
msg.textContent = "";
form.reset();
input.focus();
});
<!DOCTYPE html>
<html>
<head>
<script src="main.js"></script>
</head>
<body>
<div class="api">
<div class="container">🌞 This demo needs an OpenWeather API key to work. <a target="_blank" href="https://home.openweathermap.org/users/sign_up">Get yours here for free!</a>
</div>
</div>
<section class="top-banner">
<div class="container">
<h1 class="heading">Simple Weather App</h1>
<form>
<input type="text" placeholder="Search for a city" autofocus>
<button type="submit">SUBMIT</button>
<span class="msg"></span>
</form>
</div>
</section>
<section class="ajax-section">
<div class="container">
<ul class="cities"></ul>
</div>
</section>
<footer class="page-footer">
<div class="container">
</div>
<small>Made with <span>❤</span> by George Martsoukos
</small>
<li class="city">
<h2 class="city-name" data-name="...">
<span>...</span>
<sup>...</sup>
</h2>
<span class="city-temp">...<sup>°C</sup></span>
<figure>
<img class="city-icon" src="..." alt="...">
<figcaption>...</figcaption>
</figure>
</li>
</footer>
</body>
</html>
It's because your javascript code is executed before DOM is fully loaded.
So you have two choices, either move
<script src="main.js"></script> as the last item inside body (before </body>)
or place all your javascript code inside:
document.addEventListener("DOMContentLoaded", e =>
{
// your code here
});
I'm trying to make a Ping Pong scoreKeeper. Everything is done except the part where the scores are compared and a winner is declared. I'm trying to use the if statement to compare the innerText of two variables and whether their scores match or not. But it's not working.
Here's the Javascript and HTML code I've written.
const p1Score = document.querySelector("#p1Score")
const p2Score = document.querySelector("#p2Score")
const increaseP1Score = document.querySelector("#increaseP1Score")
const increaseP2Score = document.querySelector("#increaseP2Score")
const resetScore = document.querySelector("#resetScore")
const scoreKeeper = document.querySelector("#scoreKeeper")
increaseP1Score.addEventListener('click', function(event) {
p1Score.innerText++
// if (p1Score.innerText == 5 && p1Score.innerText > p2Score.innerText) {
// console.log("Here it works!")
})
increaseP2Score.addEventListener('click', function() {
p2Score.innerText++
})
resetScore.addEventListener('click', function() {
p1Score.innerText = 0;
p2Score.innerText = 0;
})
if (p1Score.innerText == 5 && p1Score.innerText > p2Score.innerText) {
console.log("Working!")
}
<div id="container">
<header id="header">
<h1 id="scoreKeeper">Current Score: <span id="p1Score">0</span> to <span id="p2Score">1</span></h1>
</header>
<footer id="footer">
<button id="increaseP1Score">+1 Player One</button>
<button id="increaseP2Score">+1 Player Two</button>
<button id="resetScore">Reset</button>
</footer>
</div>
You'll see a comment in my JS code. When I try to compare the values there, it somehow works. But I don't know why it doesn't work outside the event listener.
const p1Score = document.querySelector("#p1Score")
const p2Score = document.querySelector("#p2Score")
const increaseP1Score = document.querySelector("#increaseP1Score")
const increaseP2Score = document.querySelector("#increaseP2Score")
const resetScore = document.querySelector("#resetScore")
const scoreKeeper = document.querySelector("#scoreKeeper")
increaseP1Score.addEventListener('click', function(event) {
p1Score.innerText++
checkScore();
// if (p1Score.innerText == 5 && p1Score.innerText > p2Score.innerText) {
// console.log("Here it works!")
})
increaseP2Score.addEventListener('click', function() {
p2Score.innerText++
checkScore();
})
resetScore.addEventListener('click', function() {
p1Score.innerText = 0;
p2Score.innerText = 0;
})
function checkScore(){
if (p1Score.innerText == 5 && p1Score.innerText > p2Score.innerText) {
//console.log("Working!")
alert("working!");
}
}
<div id="container">
<header id="header">
<h1 id="scoreKeeper">Current Score: <span id="p1Score">0</span> to <span id="p2Score">1</span></h1>
</header>
<footer id="footer">
<button id="increaseP1Score">+1 Player One</button>
<button id="increaseP2Score">+1 Player Two</button>
<button id="resetScore">Reset</button>
</footer>
</div>
Your if statement is just running once when the page loads. You could put the functionality... in a function like checkScore() above and call it when you increment the scores. This is more re-usable and a better solution to hard-coding it in each incrementer.
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('');
};
I have an application that tests people on their times tables. The sum is presented to the user and then they have to enter their answer into the input field.
The majority of this works but the value of the input field shows as undefined rather than the value that the user enters.
let timesTableNumber = 2;
let listOfTables = [2,3,4,5,6,7,8,9,10,11,12];
let spellingItems = listOfTables.length;
let spellingItemShown = 0;
let checks = 0;
let answers = {
rightAnswers: 0,
wrongAnswers: [],
numberOfSpellings:spellingItems,
spellingGroup: "{{spelling.group}}",
spellingId: "{{spelling._id}}",
spellingcreatedBy: "{{spelling.createdBy}}",
user: "{{user._id}}"
};
var checkSpellings = setInterval(function() {
if (spellingItemShown > checks) {
checkAnswer();
}
if (spellingItemShown < spellingItems){
document.getElementById('spellings').innerHTML = timesTableNumber + 'x' + listOfTables[spellingItemShown];
document.getElementById('answer').innerHTML = timesTableNumber * listOfTables[spellingItemShown];
//hide the spelling to be tested for x seconds
var hideSpellings = setInterval(function() {
document.getElementById('spellings').style.visibility = 'hidden';
document.getElementById('form').style.removeProperty( 'visibility' );
document.getElementById('spelling').focus();
clearInterval(hideSpellings);
}, 3000);
document.getElementById('spellings').style.removeProperty( 'visibility' );
document.getElementById('form').style.visibility = 'hidden';
spellingItemShown ++;
} else{
//We're done!
console.log('there were '+ answers.rightAnswers + ' right answers and the wrong answers were '+ answers.wrongAnswers);
//post to server desired info....
// axios.post('/spellings', answers);
//showResults();
console.log(answers);
clearInterval(checkSpellings);
}
}, 7000);
function checkAnswer(){
console.log('checkAnswer:');
var correctAns = timesTableNumber * listOfTables[spellingItemShown];
var userAns = document.getElementById('spelling').value;
console.log('correctAns', correctAns);
console.log('userAns', userAns);
// debugger;
if (userAns == correctAns){
console.log('FOOOOOO');
answers.rightAnswers ++;
} else {
console.log('yo');
answers.wrongAnswers.push(document.getElementById('spellings').innerHTML);
}
document.getElementById("spelling").value = "";
checks++
}
<div class="row">
<div class="col-xs-12 col-sm-8 col-md-6 col-sm-offset-2 col-md-offset-3">
<div id="spellingTest">
<h2 id="spellings"></h2>
<p id="answer" class="answer" style="visibility:hidden"></p>
<div id="form" class="spellings" style="visibility:hidden">
<label for="spelling"> attempt</label>
<input type="number" class="form-control" id="spelling" name="spelling">
</div>
<h3 id="spellingResults">Your results will show below at the end of the test.</h3>
</div>
</div>
</div>
Can anyone help me understand why this is happening and how to resolve it?
Edit - I have resolved the undefined issue by changing the value of userAns to var userAns = document.getElementById('spelling').value; However there is now the issue that the correct answer is always one ahead of the actual correct answer e.g. correct answer for 2x2 shows as 6 rather than 4 and 3x2 shows as 8 rather than 6