Updating global variable via function - javascript

I've seen this question asked quite a bit, and I've followed all the recommendations but I can't seem to get it to work. My code is pretty simple at the moment, all it's doing is getting an input value from the input field, and updating the global variable. Any help would be great!
const createButton = document.getElementById('create-todo');
const errorOutput = document.getElementById('error-messages');
let taskValue = '';
const getInputValue = () => {
const inputValue = document.getElementById('task-input').value;
if(inputValue === ''){
errorOutput.innerHTML += `<p>Please Enter A Task</p>`;
}else{
taskValue = inputValue;
};
};
createButton.addEventListener('click', getInputValue);
console.log(taskValue);
<div id="root">
<header class="header">
<h1>To Do List</h1>
<input type="checkbox" class="toggle">
</header>
<main class="main">
<section class="todo-form">
<input type="text"
placeholder="Type your task..."
value = ""
id="task-input">
<button id="create-todo">Add To List</button>
</section>
<section id="error-messages"></section>
<section class="todo-list">
<ul>
<li id="todo-list-item">test item</li>
</ul>
<div class="list-buttons">
<button id="mark-completed">Mark As Completed</button>
<button id="remove-item">Remove Item</button>
</div>
</section>
<section class="completed-list">
<h2>Completed Tasks</h2>
</section>
</main>
<footer class="footer">
<button class="reset-button" id="reset">Clear List</button>
</footer>
</div>

That's because that line is executing immediately (before the click event has taken place). Move it into the getInputValue function so it runs at the right time.
Code in JavaScript does not necessarily execute linearly. Functions that are registered as event handlers (callbacks) only run when and if that event occurs, so that code is skipped over until needed. Your console.log() exists outside of that, so it is executed right away.
Yeah I tried that, and it doesn't update the variable after clicking
the button
Then you have another problem because as you can see below, it works as I describe if you simply move the code you want to run after the button is clicked into the button click handler.
document.getElementById('create-todo').addEventListener('click', () => {
if(task.value === ''){
errorOutput.innerHTML += `<p>Please Enter A Task</p>`;
}else{
taskValue = task.value;
}
console.log(taskValue); // <-- Works now!
}
);
const errorOutput = document.getElementById('error-messages');
const task = document.getElementById('task-input');
let taskValue = '';
<div id="root">
<header class="header">
<h1>To Do List</h1>
<input type="checkbox" class="toggle">
</header>
<main class="main">
<section class="todo-form">
<input type="text"
placeholder="Type your task..."
value = ""
id="task-input">
<button id="create-todo">Add To List</button>
</section>
<section id="error-messages"></section>
<section class="todo-list">
<ul>
<li id="todo-list-item">test item</li>
</ul>
<div class="list-buttons">
<button id="mark-completed">Mark As Completed</button>
<button id="remove-item">Remove Item</button>
</div>
</section>
<section class="completed-list">
<h2>Completed Tasks</h2>
</section>
</main>
<footer class="footer">
<button class="reset-button" id="reset">Clear List</button>
</footer>
</div>

Related

adding statement to increment value by 1 js

Hi im really new to javascript and stuck on a textbook exercise where I increase the increment of variable i by 1 to be able to continuing listing the inputs. Here is my code so far, can anyone guid me on what I am doing incorrect thank you
<body>
<header>
<h1>
Project 2 Test 1
</h1>
</header>
<article>
<div id="results">
<ul>
<li id="item1"></li>
<li id="item2"></li>
<li id="item3"></li>
<li id="item4"></li>
<li id="item5"></li>
</ul>
<p id="resultsExp"></p>
</div>
<form>
<fieldset>
<label for="wishList" id="placeLabel">
Type the name of a wish list item, then click Submit:
</label>
<input type="text" id="wishList" />
</fieldset>
<fieldset>
<button type="button" id="button">Submit</button>
</fieldset>
</form>
</article>
<script>
i = 1;
listitem = "";
function processitems() {
if (i<= 5) {
listitem ="item" +i;
document.getElementById(listitem).innerHTML = document.getElementById("wishList").value;
document.getElementById("wishlist").value ="";
if (i===5) {
document.getElementById("resultsExp").innerHTML = "Your wish list has been submitted";
}
//inside the processitems() function of the main if statement, after the nested if statement, add a statement to increment the value of i by 1.
i =+1;
}
}
var btn = document.getElementById("button");
if (btn.addEventListener) {
btn.addEventListener("click", processitems, false);
} else if (btn.attachEvent) {
btn.attachEvent("onclick", processitems);
}
</script>
i =+1; is assigning 1 to i. You should be doing i += 1 instead:
<body>
<header>
<h1>
Project 2 Test 1
</h1>
</header>
<article>
<div id="results">
<ul>
<li id="item1"></li>
<li id="item2"></li>
<li id="item3"></li>
<li id="item4"></li>
<li id="item5"></li>
</ul>
<p id="resultsExp"></p>
</div>
<form>
<fieldset>
<label for="wishList" id="placeLabel">
Type the name of a wish list item, then click Submit:
</label>
<input type="text" id="wishList" />
</fieldset>
<fieldset>
<button type="button" id="button">Submit</button>
</fieldset>
</form>
</article>
<script>
i = 1;
listitem = "";
function processitems() {
if (i <= 5) {
listitem = "item" + i;
document.getElementById(listitem).innerHTML = document.getElementById("wishList").value;
document.getElementById("wishList").value = "";
if (i === 5) {
document.getElementById("resultsExp").innerHTML = "Your wish list has been submitted";
}
//inside the processitems() function of the main if statement, after the nested if statement, add a statement to increment the value of i by 1.
i += 1;
}
}
var btn = document.getElementById("button");
if (btn.addEventListener) {
btn.addEventListener("click", processitems, false);
} else if (btn.attachEvent) {
btn.attachEvent("onclick", processitems);
}
</script>

Prevent buttons with same class from being clicked simultaneously

I have two buttons that have the same class name and have same functionality but different inputs must be added, so I used document.querySelectorAll() and the forEach() method to get them, but now when I click one, the other gets clicked too. Is there a way I can prevent this without having two addEventListener for both buttons? Enable it to click only one button at a time.
My code:
let inputElements = document.querySelectorAll('.inputElement');
const submitBtn = document.querySelectorAll('.submitBtn');
const backersElement = document.querySelector('.number-of-backers');
let donationsMade = [];
function calculateBamboo() {
inputElements.forEach(inputElement => {
const inputValue = parseFloat(inputElement.value);
if (inputValue < 25 || inputValue === '') return alert('Pledge must be at least $25.');
donationsMade.push(inputValue);
const donationsTotal = donationsMade.reduce((a, b) => a += b);
pledgedAmount.textContent = `$${donationsTotal}`;
backersElement.textContent = donationsMade.length;
return donationsTotal;
})
}
submitBtn.forEach(button => {
button.addEventListener('click', calculateBamboo);
})
It's not actually "clicking" both buttons. What's happening is the following:
Your calculateBamboo() functions loops through all the inputElements: inputElements.forEach(); and you're executing your logic for all the inputs. So, no matter which button you press, calculateBamboo() is processing each input.
Passing target input using data-attributes will help you to identify which input belongs to clicked button
Also, #JerryBen is right, you don't need to add event listener to each button but instead, we can wrap all the buttons in one element, add event listener to it and identify which element was clicked.
const wrapper = document.getElementById('wrapper');
const pledgedAmount = document.querySelector('.backed-users');
const backersElement = document.querySelector('.number-of-backers');
wrapper.addEventListener('click', calculateBamboo);
let donationsMade = [];
function calculateBamboo(event) {
/* Here you can access to the event argument,
which contains target: the clicked element*/
const el = event.target;
if (el.nodeName !== 'BUTTON' || !el.classList.contains('submitBtn')) {
return;
}
// Get target input from button's data-attr
const targetInput = el.dataset.input;
const inputElement = document.querySelector(`input[data-input="${targetInput}"]`);
// Continue with the code you had...
const inputValue = parseFloat(inputElement.value) || 0;
if (inputValue < 25 || inputValue === '') return alert('Pledge must be at least $25.');
donationsMade.push(inputValue);
const donationsTotal = donationsMade.reduce((a, b) => a += b);
pledgedAmount.textContent = `$${donationsTotal}`;
backersElement.textContent = donationsMade.length;
return donationsTotal;
}
<div class="backed">
<h1 class="backed-users">0</h1>
</div>
<div class="backers">
<h1 class="number-of-backers">0</h1>
</div>
<hr>
<div id="wrapper">
<div class=".pledge-edition">
<div class="pledge">
<section class="pledgeTwo"></section>
<div>
<h2>Bamboo Stand</h2>
Pledge $25 or more
<div>
<h2>101</h2>
<div>left</div>
</div>
</div>
</div>
<p>
You get an ergonomic stand made of natural bamboo. You've helped us launch our promotional campaign, and you’ll be added to a special Backer member list.
</p>
<div class="pledge-amount">
<p>Enter your pledge</p>
<div>
<input class="inputElement bambooInputElement" data-input="1" placeholder="$25" min="25" type="number">
<button class="submitBtn bambooBtn" data-input="1">Continue</button>
</div>
</div>
</div>
<div class=".pledge-edition">
<div class="pledge">
<section class="pledgeThree"></section>
<div>
<h2>Black Edition Stand</h2>
Pledge $75 or more
<div>
<h2>64</h2>
<div>left</div>
</div>
</div>
</div>
<p>
You get a Black Special Edition computer stand and a personal thank you. You’ll be added to our Backer member list. Shipping is included.
</p>
<div class="pledge-amount">
<p>Enter your pledge</p>
<div>
<input class="inputElement bambooInputElement" data-input="2" placeholder="$75" min="75" type="number">
<button class="submitBtn blackEditionBtn" data-input="2" placeholder="$75" min="75">Continue</button>
</div>
</div>
</div>
</div>
Adding event listeners to each button is considered a bad practice. Instead, use a single event listener to rule them all:
Wrap the buttons in a div element
Add click event only to the div wrapper
Pass an event object as an argument to the handler function
The event handler function will use the event.target to identify which specific button was clicked:
function calculateBamboo(evt){ const inputValue = parseFloat(evt.target.value) }
I hope this helps 🙄
My current JS
function calculateBamboo(target) {
let inputElement = document.querySelector(`input[data-input="${target}"]`);
donationsMade.push(inputElement);
const donationsTotal = donationsMade.reduce((a, b) => a += b);
backersElement.textContent = donationsMade.length;
pledgedAmount.textContent = `$${donationsTotal}`;
successElement.style.display = 'block';
return donationsTotal;
}
submitBtn.forEach(button => {
const target = button.dataset.input;
button.addEventListener('click', calculateBamboo.bind(target));
})
HTML buttons and input
<!-- this is how my buttons are placed -->
<div id="wrapper">
<div class=".pledge-edition">
<div class="pledge">
<section class="pledgeTwo"></section>
<div>
<h2>Bamboo Stand</h2>
Pledge $25 or more
<div>
<h2>101</h2>
<div>left</div>
</div>
</div>
</div>
<p>
You get an ergonomic stand made of natural bamboo. You've helped us launch our promotional campaign, and
you’ll be added to a special Backer member list.
</p>
<div class="pledge-amount">
<p>Enter your pledge</p>
<div>
<input class="inputElement bambooInputElement" data-input="1" placeholder="$25" min="25" type="number">
<button class="submitBtn bambooBtn" data-input="1">Continue</button>
</div>
</div>
</div>
<div class=".pledge-edition">
<div class="pledge">
<section class="pledgeThree"></section>
<div>
<h2>Black Edition Stand</h2>
Pledge $75 or more
<div>
<h2>64</h2>
<div>left</div>
</div>
</div>
</div>
<p>
You get a Black Special Edition computer stand and a personal thank you. You’ll be added to our Backer
member list. Shipping is included.
</p>
<div class="pledge-amount">
<p>Enter your pledge</p>
<div>
<input class="inputElement bambooInputElement" data-input="2" placeholder="$75" min="75" type="number">
<button class="submitBtn blackEditionBtn" data-input="2" placeholder="$75" min="75">Continue</button>
</div>
</div>
</div>
HTML for when the values are entered
<div class="backed">
<h1 class="backed-users">0</h1>
</div>
<div class="backers">
<h1 class="number-of-backers">0</h1>
</div>

Printing each expense name and amount from a JS object that is saved from user input

Good morning!
I am halfway through my first JS app and have run into a problem. I am having a hard time printing multiple user inputs that I am putting into a JS object and printing both the obj.name and obj.amount to their respective places. I am able to print single items to their areas, but it puts the new one in each time instead of adding the new input onto the old. I have tried different things like putting the input directly into an array obj and then using a for loop and putting both the inputs into a separate var and pushing that into the previously created array. I have even tried console.log to see what it is taking from the input and it logs only the first letter of the string. I would appreciate any help with getting this to work. Thanks.
Here is what I have so far.
let expenseNames = [];
function incomingExpenses() {
expenseNames.name = document.querySelector("[name=expense_Name]").value,
expenseNames.amount= document.querySelector("[name=expense_Value]").value
for (var i = 0; i <expenseNames['amount'].length; i++){
document.querySelector('#title_Expenses').innerHTML = expenseNames.name;
document.querySelector('#value_Expenses').innerHTML = expenseNames.amount;
console.log(expenseNames['name'][i]);
i++;
}
};
let outgoingCalcButton = document.getElementById('expenseButton');
expenseButton.addEventListener("click", incomingExpenses);
<body>
<h1>Budget Application</h1>
<div id="inputSections" class="inputSections">
<section id="incomingMoney">
<h3>Please Enter Your Budget</h3>
<input type="number" id="incomingCashInput" class="inputs" name="incoming_Cash_Input"><br>
<button id="incomingCalcButton">Calculate</button>
</section>
<section id="enterExpenses">
<h3>Please Enter Your Expense</h3>
<input type="text" id="expenseName" class="inputs" name="expense_Name">
<h3>Please Enter Expense Amount</h3>
<input type="number" id="expenseAmount" class="inputs" name="expense_Value"><br>
<button id="expenseButton">Add Expense</button>
</section>
</div>
<section id="calculations" class="calcs">
<div class="budget calcs">
<h3>Budget</h3><br>
<img src="money_icon.png" class="moneyIcon calcIcon"><br>
<section id="budgetIncoming">
</section>
</div>
<div class="expenses calcs">
<h3>Expenses</h3><br>
<img src="expense_icon.png" class="expenseIcon calcIcon"><br>
<section id="expenseIncoming">
</section>
</div>
<div class="balance calcs">
<h3>Balance</h3><br><br>
<img src="budget_icon.png" class="budgetIcon calcIcon"><br>
<section class="balanceIncoming">
</section>
</div>
</section>
<section id="expenses expContainer" >
<div class="expContainer">
<h4>Expense Title</h4>
<section class="titleExpenses expContainer" id="title_Expenses">
</section>
</div>
<div class="expContainer">
<h4>Expense Value</h4><br><br>
<section class="valueExpenses" id="value_Expenses">
</section>
</div>
<div class="expContainer">
<h4>Edit</h4>
<section class="deleteExpenses" >
</section>
</div>
</section>
</body>
I'm not sure if I understood well what you want to achieve.
But maybe this example can help you move your project forward:
a link on jsfiddle

List Items are showing up inside my submit button in to-do app

My List items are showing up inside of my submit button when I submit a new task.
EXPECTATION: when the submit button is clicked a new task should show up in a task list inside the .
ACTUAL: submit button is clicked, a new task is made inside of the submit button.
<body>
<div class="container">
<h1>TO DO LIST</h1>
<form id="taskForm">
<input id="taskInput"></input>
<button type="button" id="taskButton" onclick="taskList()">
Click Here</buton>
</form>
</div>
<div>
<ul id="taskLister"></ul>
</div>
<script src=script.js></script>
</body>
function taskList() {
let item = document.getElementById("taskInput").value;
let text = document.createTextNode(item);
let newTask = document.createElement("li");
let deleteTask = document.createElement("button");
deleteTask.style.cssText = 'height: 30px; width: 60px;';
deleteTask.innerText = 'Delete';
newTask.appendChild(text);
deleteTask.appendChild(newTask);
document.getElementById("taskLister").appendChild(newTask);
}
Firstable the <input> HTML element has no closing tag and you have misspelled the closing tag name </button>
function taskList() {
let item = document.getElementById("taskInput").value;
let text = document.createTextNode(item);
let newTask = document.createElement("li");
let deleteTask = document.createElement("button");
deleteTask.style.cssText = 'height: 30px; width: 60px;';
deleteTask.innerText = 'Delete';
newTask.appendChild(text);
deleteTask.appendChild(newTask);
document.getElementById("taskLister").appendChild(newTask);
}
<div class="container">
<h1>TO DO LIST</h1>
<form id="taskForm">
<input id="taskInput">
<button type="button" id="taskButton" onclick="taskList()">Click Here</button>
</form>
</div>
<div>
<ul id="taskLister"></ul>
</div>
I thought you want to add a remove button to each list item so here is an example
function taskList() {
// using inner HTML is much clear and gives a cleaner code
document.getElementById("taskLister").innerHTML += `
<li>${document.querySelector("#taskInput").value}<button onclick="this.parentElement.remove()">×</button></li>
`;
}
<div class="container">
<h1>TO DO LIST</h1>
<form id="taskForm">
<input id="taskInput">
<button type="button" id="taskButton" onclick="taskList()">Click Here</button>
</form>
</div>
<div>
<ul id="taskLister"></ul>
</div>

Quiz game: how to target the correct answer on the DOM and hide it

I am working through a quiz game that imitates family feud. I have an input that a user types into and if one of the three answers displayed on the page matches that user's input the player gets the points and the answer is removed from the array and the same answer should fade away.
While it works functionally in javascript, I need to add styling to remove whichever correct answer was guessed.
In short, I'm currently able to match the correct answer object on the page according to what the user entered. How do I now access this same object on the DOM and hide its content?
Thank you!
no back end
answers stored in an array of objects in a js file
using JQuery
edit: since I was getting crucified asking for how one would implement this through jquery I decided to use a function instead.
correctAnswer is an object being passed in.
revealCorrectAnswer(correctAnswer) {
$(".answer").each(function() {
if ($(this).text() === correctAnswer.answer) {
$(this).addClass("hidden");
$(this)
.parent()
.next()
.children()
.addClass("hidden");
}
});
}
<section class="question-section">
<h2 id="current-question">Question Goes Here</h2>
</section>
<section class="answers-section">
<article class="answer-section" id="section-1">
<div>
<h1 class="answer answer-1">answer1</h1>
</div>
<div class="pts-section">
<p class="answer-1-pts">50</p>
</div>
</article>
<article class="answer answer-section" id="section-2">
<div>
<h1 class="answer-2">answer2</h1>
</div>
<div class="pts-section">
<p class="answer-2-pts">75</p>
</div>
</article>
<article class="answer answer-section" id="section-3">
<div>
<h1 class="answer-3">answer3</h1>
</div>
<div class="pts-section">
<p class="answer answer-3-pts">100</p>
</div>
</article>
</section>
<section class="whose-turn">
<form class="whose-turn-form">
<p class="current-turn"></p>
<label for="player-guess">
<input type="input" class="player-guess" id="player-guess" name="player-guess" placeholder="Make a guess!">
</label>
<button type="submit" class="btn submit-answer" id="submit-guess" name="submit-guess">Guess</button>
</form>
</section>
$("#submit-guess").on("click", event => {
event.preventDefault();
if (game.currentRound < 3) {
game.whoseTurn();
//let player 1 guess first
if (game.currentPlayerTurn === "player1") {
rotatePlayer(player2);
checkInputOf(player1);
updateTheScoreOf(player1, 1);
} else if (game.currentPlayerTurn === "player2") {
rotatePlayer(player1);
checkInputOf(player2);
updateTheScoreOf(player2, 2);
}
} else if (game.currentRound < 5) {
if (game.currentPlayerTurn === "player2") {
checkInputOf(player1);
updateTheScoreOf(player1, 1);
} else if (game.currentPlayerTurn === "player1") {
checkInputOf(player2);
updateTheScoreOf(player2, 2);
}
} else {
console.log("|| Exceeds Rounds ||");
}
function rotatePlayer(player) {
$(".current-turn").html(`${player.name}'s turn!`);
}
function checkInputOf(player) {
let userInput = $("#player-guess").val();
player.score += game.checkUserGuess(userInput, game.currentAnswers);
}
function updateTheScoreOf(player, domElementId) {
$(`.player-${domElementId}-score`).html(`Score: ${player.score}`);
}
});

Categories

Resources