Having trouble reducing the total in this small todo app - javascript

I am having a hard time trying to figure out how to get the the value from every new Li and reduce it (add) to then output to my h2. Can't figure out what I am doing wrong. Any help would be greatly appreciated! Codepen: https://codepen.io/Chasehud26/pen/Poagjwy
I tried to console.log different variables to see if there were any hints of what is going wrong.
const form = document.querySelector("form")
const nameInput = document.querySelector("#name-input")
const priceInput = document.querySelector("#price-input")
const button = document.querySelector("button")
const nameUl = document.querySelector("#item-name")
const priceUl = document.querySelector("#item-price")
const h2 = document.querySelector("h2")
const nameLi = document.createElement("li")
const priceLi = document.createElement("li")
form.addEventListener("submit", function (e) {
e.preventDefault()
let nameVal = nameInput.value
let priceVal = priceInput.value
const nameLi = document.createElement("li")
const priceLi = document.createElement("li")
nameUl.appendChild(nameLi)
nameLi.innerHTML = nameInput.value
priceUl.appendChild(priceLi)
priceLi.textContent = `${priceInput.value}`
showTotals()
})
//TRYING TO ADD TOGETHER ALL THE PRICE VALUES AND THEN PUT IT TO MY H2//
function showTotals() {
const priceList = document.querySelectorAll("li")
for (let priceLists of priceList) {
const total = []
total.push(parseFloat(priceLists.textContent));
const totalMoney = total.reduce(function (total, item) {
total += item;
return total;
}, 0);
const finalMoney = totalMoney.toFixed(2);
h2.textContent = finalMoney;
}
}

You need to have your const total [] array initialized outside of the for loop. also, when you setup your <li> decorators, you need to differentiate between the number and non-number fields, since the way you had it, it was trying to add the text 'li' fields also:
/// truncated for clarity
const nameLi = document.createElement("li")
const priceLi = document.createElement("li")
priceLi.classList.add('num') // <== this line added
//// =================
function showTotals() {
const priceList = document.querySelectorAll("li.num") // added class
const total = [] // <== move this to here
for (let priceLists of priceList) {
total.push(parseFloat(priceLists.textContent));
const totalMoney = total.reduce(function (total, item) {
total += item;
return total;
}, 0);
const finalMoney = totalMoney.toFixed(2);
h2.textContent = finalMoney;
}

Related

Conditional statement limiting the number of displayed elements

I'm having trouble implementing the logic that will limit me from adding the same items to my shopping list. When the item is the same, I just want to display the quantity with the existing item.
<div class="pizzas">
</div>
<div class="shoppingCart">
<p class="totalPrice">Hungry? order our pizzas</p>
</div>
// js
fetch("https://raw.githubusercontent.com/alexsimkovich/patronage/main/api/data.json")
.then(data => data.json())
.then(data => {
let valueCurrency = 0;
data.forEach(element => {
const shoppingCart = document.querySelector(".shoppingCart");
const pizzas = document.querySelector(".pizzas");
const box = document.createElement("div");
const img = document.createElement("img");
const title = document.createElement("h3");
const ingredients = document.createElement("p");
const price = document.createElement("h4");
const btn = document.createElement("button");
const totalPrice = document.querySelector(".totalPrice");
box.className = "box";
ingredients.className = "ingredients"
btn.className = "btn";
img.src = element.image;
img.className = "img";
title.innerHTML = element.title;
ingredients.innerHTML = element.ingredients;
price.innerHTML = element.price.toFixed(2) + " zł";
btn.innerHTML = "Dodaj do koszyka";
box.appendChild(img);
box.appendChild(title);
box.appendChild(ingredients);
box.appendChild(price);
box.appendChild(btn);
pizzas.appendChild(box);
btn.addEventListener("click", (e) => {
valueCurrency = valueCurrency + element.price;
const pizza = document.createElement("div");
pizza.className = "pizzaList";
const pizzasList = document.createElement("li");
const pizzaPrice = document.createElement("p");
const btnRemove = document.createElement("button");
btnRemove.innerText = "X";
pizzasList.innerText = title.textContent;
pizzaPrice.innerText = price.textContent;
pizza.appendChild(pizzasList);
pizza.appendChild(pizzaPrice);
pizza.appendChild(btnRemove);
totalPrice.innerText = "Całkowita cena: " + valueCurrency.toFixed(2);
if(pizzasList.innerText === pizzasList.innerText)
{
// don't add another item to the list
// just add +1 to existing element
}
else
{
// add an item to the list
shoppingCart.prepend(pizza);
}
btnRemove.addEventListener("click", (e) => {
pizza.remove();
valueCurrency = valueCurrency - element.price;
totalPrice.innerText = "Całkowita cena: " + valueCurrency.toFixed(2);
})
})
});
})
.catch(err => console.log(err));
My problem is exactly in the conditional statement, I don't know exactly how to implement the counting of the same pizzas option.
Thank you in advance for your help.
Since you are using html elements for this, what you can do is to use a data-attribute in your pizza element and increment it each time you need.
Something like:
if(pizzasList === pizzasList)
{
pizza.dataset.total = Number(pizza.dataset.total) + 1;
}
else
{
pizza.dataset.total = 1;
shoppingCart.prepend(pizza);
}
Then just use pizza.dataset.total to retieve the total number of repetitions.

How to automatically add and update the price total when adding an item with price

I have been learning javascript, i'm on my second project called "expense tracker" i have been able to use DOM and functions but could not execute right on the operators.
I have 2 input text the first is "item name" and the second is "price".
I have 2 buttons first is "add" and 2nd is "deduct".
The problem is Im so confused to create functions on the operators that able to get the total price and auto update the total whenever I add items.
I want to achieve:
When ever I add Item the current total price will be updated automatically.
When ever I deduct item the current total price will be updated automatically.
This the Javascript. I can able add and append items and price but dont know how to add and deduct with automatic price total.
const itemname = document.querySelector('#itemname');
const price = document.querySelector('#price');
//set requirements and limitations
const isRequired = value => value === '' ? false : true;
//set error trapping and message
const showError = (input, message) => {
const formgroup = input.parentElement;
formgroup.classList.remove('success');
formgroup.classList.add('error');
const error = formgroup.querySelector('small');
error.textContent = message;
}
const showSuccess = (input, message) => {
const formgroup = input.parentElement;
formgroup.classList.remove('error');
formgroup.classList.add('success');
const error = formgroup.querySelector('small');
error.textContent = message;
}
// Verifying fields if correct
const checkItemname = () =>{
let valid = false;
const itemnameTrim = itemname.value.trim();
const priceTrim = price.value.trim();
if(!isRequired(itemnameTrim)){
showError(itemname, "Pls type item name!");
}
else if(!isRequired(priceTrim)){
showError(price, "Pls type price!");
}
else{
showSuccess(itemname);
showSuccess(price);
addItem();
valid = true;
}
return valid;
}
const addItem = () => {
const itemnameTrim = itemname.value.trim();
const tableRowItem = document.createElement("tr");
const tableDataItem = document.createElement("td");
const tableTxtnode = document.createTextNode(itemnameTrim);
tableRowItem.appendChild(tableDataItem);
tableDataItem.appendChild(tableTxtnode);
document.getElementById("td-item").appendChild(tableRowItem);
const priceTrim = price.value.trim();
const tableDataPrice = document.createElement("td");
const tableTxtnodePrice = document.createTextNode(priceTrim);
tableRowItem.appendChild(tableDataPrice);
tableDataPrice.appendChild(tableTxtnodePrice);
document.getElementById("itemname").value = "";
document.getElementById("price").value = "";
}
//Deduct button
const deductItem = () => {
const itemnameTrim = itemname.value.trim();
const tableRowItem = document.createElement("tr");
const tableDataItem = document.createElement("td");
const tableTxtnode = document.createTextNode(itemnameTrim);
tableRowItem.className = 'redtext';
console.log(tableRowItem);
tableRowItem.appendChild(tableDataItem);
tableDataItem.appendChild(tableTxtnode);
document.getElementById("td-item").appendChild(tableRowItem);
const priceTrim = price.value.trim();
const tableDataPrice = document.createElement("td");
const tableTxtnodePrice = document.createTextNode(priceTrim);
tableRowItem.appendChild(tableDataPrice);
tableDataPrice.appendChild(tableTxtnodePrice);
document.getElementById("itemname").value = "";
document.getElementById("price").value = "";
}
//Call the buttons and evoke functions
const deductBtn = document.querySelector('#deductBtn')
const addBtn = document.querySelector('#addBtn')
addBtn.addEventListener("click", function(){
checkItemname()});
deductBtn.addEventListener("click", function(){
deductItem()});
$(document).ready(function(){
//iterate through each textboxes and add keyup
//handler to trigger sum event
$(".txt").each(function() {
$(this).keyup(function(){
calculateSum();
});
});
});
function calculateSum() {
var sum = 0;
//iterate through each textboxes and add the values
$(".txt").each(function() {
//add only if the value is number
if(!isNaN(this.value) && this.value.length!=0) {
sum += parseFloat(this.value);
}
});
//.toFixed() method will roundoff the final sum to 2 decimal places
$("#sum").html(sum.toFixed(2));
}

Whenever the page gets reloaded, an item in a list gets duplicated in javascript

I’m a newbie started js like 2 weeks ago.
I have been making a to-do list.
There are key toDos & finished in localStorage.
I want the value in toDos to go to finished, getting class name “done” if I click the finBtn. Also it should move to the bottom.
At first it works. However, every time the page gets refreshed, the stuff in finished gets duplicated.
This problem’s been bothering me for a week.
Thank you for reading.
const toDoForm = document.querySelector(".js-toDoForm"),
toDoInput = toDoForm.querySelector("input"),
toDoList = document.querySelector(".js-toDoList");
const TODOS_LS = "toDos";
const FINISHED_LS = "finished";
const NOTSTART_CN = "notStart";
const DONE_CN = "done";
let toDos = [];
let toDosDone = [];
function saveToDos(){
localStorage.setItem(TODOS_LS, JSON.stringify(toDos));
}
function updateToDos(){
localStorage.setItem(FINISHED_LS, JSON.stringify(toDosDone));
}
function deleteToDo(event){
const btn = event.target;
const li = btn.parentNode;
toDoList.removeChild(li);
const cleanToDos = toDos.filter(function(toDo){
return toDo.id !== parseInt(li.id);
});
toDos = cleanToDos;
saveToDos();
}
function finish(event){
const btn = event.target;
const li = btn.parentNode;
const oldToDos = localStorage.getItem(TODOS_LS);
const parsedOldToDos = JSON.parse(oldToDos);
const btnNum = parseInt(li.id) - 1;
const finishedStuff = parsedOldToDos.splice(btnNum, 1);
finishedStuff[0].class = DONE_CN;
li.classList.add(DONE_CN);
toDos = parsedOldToDos;
toDosDone = finishedStuff;
saveToDos();
updateToDos();
}
function makeToDos(text){
const li = document.createElement("li");
const span = document.createElement("span");
const delBtn = document.createElement("button");
const finBtn = document.createElement("button");
const newId = toDos.length + 1;
delBtn.innerText="❌";
delBtn.classList.add("delBtn");
delBtn.addEventListener("click", deleteToDo);
finBtn.classList.add("finBtn");
finBtn.innerText = "✔";
finBtn.addEventListener("click", finish);
span.innerText = text;
li.id = newId;
li.appendChild(span);
li.appendChild(delBtn);
li.appendChild(finBtn);
toDoList.appendChild(li);
const toDoObj = {
text: text,
id: newId,
class:""
};
toDos.push(toDoObj);
saveToDos();
}
function handleSubmit(event){
event.preventDefault();
const currentValue = toDoInput.value;
makeToDos(currentValue);
toDoInput.value = "";
}
function loadToDos(){
const loadedToDos = localStorage.getItem(TODOS_LS);
const loadedFinToDos = localStorage.getItem(FINISHED_LS);
if(loadedToDos !== null || loadedFinToDos !== null){
const parsedToDos = JSON.parse(loadedToDos);
const parsedFinToDos = JSON.parse(loadedFinToDos);
parsedToDos.forEach(function(toDo){
makeToDos(toDo.text);
});
parsedFinToDos.forEach(function(done){
makeToDos(done.text);
});
} //else
} //ends of loadToDos
function init(){
loadToDos();
toDoForm.addEventListener("submit", handleSubmit);
}
init();
Your localStorage is not cleaning up on page refresh, you should do localStorage.clear(); Each time page load using

Javascript - can't iterate over object in incremental search

I'm very new to javascript/dev so I hope there is a an obvious solution that I've not thought of. My code returns search items from TVMaze.com API. The feature giving me trouble is the incremental search (as a user types in input box, the code returns and displays images by creating a new div and appending images, removing and replacing the an div).
My problem is that on deleting all characters from input box, I receive the error: "Uncaught (in promise) TypeError: shows is not iterable" which I suppose means that there is no object to iterate over? Thanks in advance for any help.
const input = document.querySelector("#query");
input.addEventListener("input", async function (e) {
e.preventDefault();
const searchTerm = e.target.value;
const config = { params: { q: searchTerm } };
const res = await axios.get(`http://api.tvmaze.com/search/shows?`, config);
makeImages(res.data);
clearList();
});
const makeImages = (shows) => {
const div = document.createElement("div");
for (let result of shows) {
if (result.show.image) {
const img = document.createElement("IMG");
img.className += "resultImage";
img.src = result.show.image.medium;
const title = document.createElement("h3");
title.className += "resultTitle";
title.innerText = result.show.name;
const year = document.createElement("h4");
year.className += "score";
year.innerText = result.show.premiered;
var sub = year.innerText.substring(0, 4);
var yearNum = parseInt(sub);
div.append(year);
div.append(img);
div.append(title);
document.body.appendChild(div);
}
if (yearNum <= 2000) {
var retro = document.createElement("h5");
retro.className = "retro";
retro.innerText = "retro";
div.append(retro);
}
}
};
let clearList = () => {
var allImg = document.querySelectorAll("IMG");
if (allImg.length === 0) {
document.createElement("div");
return makeImages();
}
var oldDiv = document.querySelector("div");
oldDiv.remove();
console.log(oldDiv);
};

needing help fixing unordered list not displaying through Dom

The logic seems sound but my ul is not displaying what I am asking it to. I have used console.logs and I am for sure getting poem in the function displayPoem(poem) but it isn't showing up when I button click. Any help would be greatly appreciated!
const inputsList = document.querySelector('ol');
const poemsList = document.getElementById('savedThoughts');
const form = document.getElementById('')
const submitButton = document.getElementById('submitThoughts');
const startButton = document.querySelector('#startButton')
startButton.onclick = () => {
const ranNum = generateRanNum();
generateInputs(ranNum)
changeToRestartText()
}
submitButton.onclick = () => {
const poem = savePoem();
console.log(poem)
displayPoem(poem);
clearForm()
}
const generateRanNum = () => {
let randomNumber = Math.floor(Math.random() * 20);
return randomNumber
}
const changeToRestartText = () => {
startButton.textContent = 'Restart Game'
}
const generateInputs = (ranNum) => {
const listItem = document.createElement('li');
for(let i = 1; i <= ranNum; i++){
const input = document.createElement('input');
listItem.appendChild(input).setAttribute('type', 'text');
console.log(ranNum)
}
inputsList.appendChild(listItem);
}
const savePoem = () => {
let poemArr = [];
const input = document.querySelectorAll('input');
input.forEach(element => {
poemArr.push(element.value);
})
// console.log(poemArr)
return poemArr;
}
const displayPoem = (poem) => {
const savedPoem = document.createElement('li')
const savedText = document.createElement('span')
const deletePoem = document.createElement('button')
console.log(poem)
savedPoem.appendChild(savedText);
savedText.textContent = poem.toString();
savedPoem.appendChild(deletePoem);
deletePoem.textContent = 'Delete';
poemsList.appendChild(savedPoem)
deletePoem.onclick = e => {
poemsList.removeChild(savedPoem);
}
}
const clearForm = () => {
const inputLi = document.querySelectorAll('li');
inputLi.forEach(element => {
element.remove()
})
}
small html segment
<div >
<ul id="savedThoughts">
</ul>
</div>
Your saved list items aren't showing up because your submit onclick calls displayPoem which creates list items and then calls clearForm which removes all list items on the page. Try inputLi = document.querySelectorAll('ol > li').

Categories