I'm learning JS and created an app game in which a user guesses random day and random month. When the user gets both of them right, I want to replace the question mark with a heart icon from JS icons. Somehow it doesn't work.
I tried this code:
if (guessDay === secretDay && guessMonth === secretMonth) {
document.getElementById("victory").innerHTML = "💖";
}
I also tried replacing the heart icon with a word: "Victory" but it didn't work either.
Full code below:
let secretMonth = Math.trunc(Math.random() * 12) + 1;
let secretDay = Math.trunc(Math.random() * 31) + 1;
console.log(secretMonth, secretDay);
document.querySelector(".btn-month").addEventListener("click", function () {
const guessMonth = Number(document.querySelector(".guess-month").value);
if (guessMonth === secretMonth) {
document.querySelector(
".hint-month"
).textContent = `You got the month right.`;
document.querySelector(".left").style.backgroundColor = "blue";
} else if (guessMonth >= secretMonth) {
document.querySelector(".hint-month").textContent = `Go lower.`;
document.querySelector(".left").style.backgroundColor = "#d9480f";
} else {
document.querySelector(".hint-month").textContent = `Go higher.`;
document.querySelector(".left").style.backgroundColor = "#d9480f";
}
});
document.querySelector(".btn-day").addEventListener("click", function () {
const guessDay = Number(document.querySelector(".guess-day").value);
if (guessDay === secretDay) {
document.querySelector(".hint-day").textContent = `You got the day right.`;
document.querySelector(".right").style.backgroundColor = "blue";
} else if (guessDay >= secretDay) {
document.querySelector(".hint-day").textContent = `Go lower.`;
document.querySelector(".right").style.backgroundColor = "#d9480f";
} else {
document.querySelector(".hint-day").textContent = `Go higher.`;
document.querySelector(".right").style.backgroundColor = "#d9480f";
}
});
document.querySelector(".btn-reset").addEventListener("click", function () {
document.querySelector(".hint-day").textContent = "";
document.querySelector(".hint-month").textContent = "";
document.querySelector(".right").style.backgroundColor = "#d9480f";
document.querySelector(".left").style.backgroundColor = "#d9480f";
document.querySelector(".guess-month").value = "";
document.querySelector(".guess-day").value = "";
});
if (guessDay === secretDay && guessMonth === secretMonth) {
document.getElementById("victory").innerHTML = "victory";
}
<div class="wrapper">
<header>
<h1>Guess my birthday</h1>
<div class="divider"><span id="victory">?</span></div>
</header>
<main>
<section class="left">
<div class="label-container">
<p class="range">Between 1-12</p>
<p class="label">month</p>
</div>
<input class="guess guess-month" type="number" min="0" max="12" />
<button class="btn btn-month">Check</button>
<p class="hint hint-month"></p>
</section>
<section class="right">
<div class="label-container">
<p class="range">Between 1-31</p>
<p class="label">day</p>
</div>
<input class="guess guess-day" type="number" min="0" max="31" />
<button class="btn btn-day">Check</button>
<p class="hint hint-day"></p>
</section>
<button class="btn btn-reset">Reset</button>
</main>
</div>
The logic is correct but the code is not running at the right moment in the right scope. The conditional check happens at the same time as registering event handlers.
// register month click
// register day click
// register reset click
// too early to check the guess, no guesses have been made yet
if (guessDay === secretDay && guessMonth === secretMonth) {
document.getElementById("victory").innerHTML = "victory";
}
In order to fix the problem, there are two steps.
Put the victory check in a helper function to call on both the day and month submit if the guess is right.
Keep track of the day and month guess in the parent scope to allow checking for victory after guessing either value.
let secretMonth = Math.trunc(Math.random() * 12) + 1;
let secretDay = Math.trunc(Math.random() * 31) + 1;
// keep track of last day and month guess in parent scope
let guessMonth;
let guessDay;
// in click event handler set outer scope variable (no const)
guessMonth = Number(document.querySelector(".guess-month").value);
In terms of checking for victory it could be a helper function.
function checkVictory() {
if (guessDay === secretDay && guessMonth === secretMonth) {
document.getElementById("victory").innerHTML = "victory";
}
}
// in click event handler
if (guessDay === secretDay) {
// update styles
checkVictory();
}
I had to change the conditions for the month. Because after I checked the victory for the day and styles were applied, the same style was supposed to be applied to the month div but only the victory for both was applied. Therefore the game must be done in the predifined order. Guess the day first, then guess the month and the month styling must be applied together with the victory styling. (I removed the victory for the month and applied victory for the game instead.
Related
I'm working on a restaurant ordering app, and when I add items, it adds and removes them from the total display, but when I remove the FINAL item in the cart, the order total still shows the value of the last item that was removed. Here is a link to my code as well as the function itself that contain the order total:
https://codepen.io/vanessalearnsjavascript/pen/qBKGvQP?editors=0011
function handleOrderSection(){
let totalPriceArray = [];
let invoiceHtml = ``;
let totalPrice = 0;
orderList.forEach(function(chosenItem, index){
invoiceHtml += `
<div class="item-invoice">
<div class="remove-wpr">
<h3 class="item-invoice name">${chosenItem.name}</h3>
<button class="remove-btn" data-remove="${index}">Remove</button>
</div>
<h3 class="item-invoice-price">$${chosenItem.price}</h3>
</div>
`
//console.log(chosenItem)
totalPriceArray.push(chosenItem.price)
//console.log(totalPriceArray)
if(totalPriceArray.length >= 1){
let orderValue = totalPriceArray.reduce(function(total, num){
return total + num
})
console.log(orderValue)
let customOrder = ``
customOrder += `
<div id="order-total" class="total-display">
Order Total:$ ${totalPriceArray.reduce(function(total, num){
return total + num
})}
</div> `
document.getElementById("chosen-items").style.display = "block"
document.getElementById("chosen-items").innerHTML = customOrder
}
})
document.getElementById('ordered-items').innerHTML = invoiceHtml
if(orderList.length >= 1){
modal.style.display = "inline"
completeBtn.style.display = "inline"
} else {
modal.style.display = "none"
completeBtn.style.display = "none"
}
}
Any help is appreciated. Thanks in advance.
I've tried different things like adding the return statement to different parts of the function and even changing the event listeners, and it just continues to confuse me. I don't have too much to add to this part, just that it's been a real head scratcher for me.
I have a basic word scramble game (not styled yet), that works fine on an HTML page.
When I bring that exact code over to a blogger post it stops working.
I can enter text into the text field but on pressing the "Check Word" button it throws back a "Please enter the word to check" even though I have entered a word to check.
Everything else seems to work correctly on blogger (Refresh button, counter, hint, etc.)
The code is as follows...
let words = [
{
word: "addition",
hint: "The process of adding numbers"
},
{
word: "meeting",
hint: "Event in which people come together"
},
{
word: "number",
hint: "Math symbol used for counting"
},
{
word: "exchange",
hint: "The act of trading"
},
]
const wordText = document.querySelector(".word"),
hintText = document.querySelector(".hint span"),
timeText = document.querySelector(".time b"),
inputField = document.querySelector("input"),
refreshBtn = document.querySelector(".refresh-word"),
checkBtn = document.querySelector(".check-word");
let correctWord, timer;
const initTimer = maxTime => {
clearInterval(timer);
timer = setInterval(() => {
if(maxTime > 0) {
maxTime--;
return timeText.innerText = maxTime;
}
alert(`Time off! ${correctWord.toUpperCase()} was the correct word`);
initGame();
}, 1000);
}
const initGame = () => {
initTimer(20);
let randomObj = words[Math.floor(Math.random() * words.length)];
let wordArray = randomObj.word.split("");
for (let i = wordArray.length - 1; i > 0; i--) {
let j = Math.floor(Math.random() * (i + 1));
[wordArray[i], wordArray[j]] = [wordArray[j], wordArray[i]];
}
wordText.innerText = wordArray.join("");
hintText.innerText = randomObj.hint;
correctWord = randomObj.word.toLowerCase();;
inputField.value = "";
inputField.setAttribute("maxlength", correctWord.length);
}
initGame();
const checkWord = () => {
let userWord = inputField.value.toLowerCase();
if(!userWord) return alert("Please enter the word to check!");
if(userWord !== correctWord) return alert(`Oops! ${userWord} is not a correct word`);
alert(`Congrats! ${correctWord.toUpperCase()} is the correct word`);
initGame();
}
refreshBtn.addEventListener("click", initGame);
checkBtn.addEventListener("click", checkWord);
<div class="Gamecontainer">
<h2>Word Scramble</h2>
<div class="content">
<p class="word"></p>
<div class="details">
<p class="hint">Hint: <span></span></p>
<p class="time">Time Left: <span><b>20</b>s</span></p>
</div>
<input spellcheck="false" type="text" />
<div class="buttons">
<button class="refresh-word">Refresh Word</button>
<button class="check-word">Check Word</button>
</div>
</div>
</div>
Any suggestions?
This is because you use querySelector("input") which selects first found input element on the page. Blogger post has multiple input elements therefore your code selects a wrong element. Use IDs or classes to better identify your html elements.
For example you can narrow the query to your html part by using:
inputField = document.querySelector(".Gamecontainer input")
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.
I am in the process of learning Javascript and at the moment I'm only using vanilla js to code stuff.
I'm trying to make 2 button (+ and -) to add and subtract a number.
Here's what I have so far:
let value = document.querySelector("#number");
let add = document.querySelector("#add").addEventListener("click", function(value){
add = value++;
document.querySelector("#number").textContent = add;
});
With the above code, when I click my button my p tag changes to NaN. It is 0 form the start.
Goal it to make it 1.
In case you need the HTML code then this is what I have:
<div class="content">
<button id="add">+</button>
<p id="number">0</p>
<button id="sub">-</button>
</div>
You need to set a global var and add and subtract value on that.
You also need to check value is more then zero using ternary operator (if condition) so that the value is always displayed above zero when subtracting
Live Demo
let value = document.querySelector("#number");
//Store value
let valueNumber = 0
//Add value
document.querySelector("#add").addEventListener("click", function(value) {
valueNumber++;
document.querySelector("#number").textContent = valueNumber;
});
//Subtract value
document.querySelector("#sub").addEventListener("click", function(value) {
valueNumber--;
document.querySelector("#number").textContent = valueNumber > 0 ? valueNumber : 0;
});
<div class="content">
<button id="add">+</button>
<p id="number">0</p>
<button id="sub">-</button>
</div>
Even though the answer has been given, I'd like to share mine.
document.querySelector("#add").onclick = function(){
let num = number.innerText;
number.innerText = num/1 + 1;
}
document.querySelector("#sub").onclick = function(){
let num = number.innerText;
if(num > 0){
number.innerText = num/1 - 1;
}
}
<div class="content">
<button id="add">+</button>
<p id="number">0</p>
<button id="sub">-</button>
</div>
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