Conditional statement limiting the number of displayed elements - javascript

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.

Related

Having trouble reducing the total in this small todo app

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;
}

How to achieve individual card functionality with JS?

Repo: https://github.com/bigolboyyo/weatherdbapp
Hello! I am working on a small project working with an API for the first time. I'm making a simple weather app that allows you to type in a location and append a "card" of data.
This card has a "front" and "back". Front being the weather data and the back being a simple textarea notepad.
As far as functionality goes I am just about there. My only issue is now when I have more than one card I only get an event listener on the first card button and the first card's button affects all the other cards created after! How would I apply the event listener for each card's buttons made and have those buttons only affect the relevant card?
Current code I'm working with
let notesBtn = document.getElementById("notes-btn");
notesBtn.addEventListener("click", handleFrontClick);
console.log(notesBtn);
function handleFrontClick(e) {
e.target.parentNode.remove();
card.appendChild(back);
let frontBtn = document.getElementById("front-btn");
frontBtn.addEventListener("click", (e) => {
e.target.parentNode.remove();
card.appendChild(front);
});
ALL JS (git repo above)
const body = document.getElementsByTagName("body");
const unsplashRandom =
"https://source.unsplash.com/random/1920x1080/?landscapes";
document.body.style.backgroundImage = `url(${unsplashRandom})`;
const header = document.createElement("div");
header.className = "header";
header.id = "header";
document.body.append(header);
const container = document.createElement("div");
container.className = "container";
document.body.append(container);
const h1 = document.createElement("h1");
h1.id = "h1";
h1.textContent = "WeatherDB Search";
h1.style.textAlign = "center";
header.append(h1);
let p1 = document.createElement("p");
p1.id = "p1";
p1.textContent = "Enter location for today's weather!";
p1.style.textAlign = "center";
header.append(p1);
const cityInput = document.createElement("input");
cityInput.className = "search-inputs";
cityInput.id = "city-input";
cityInput.placeholder = " ex: New York, Toronto, London";
header.append(cityInput);
const searchButton = document.createElement("button");
searchButton.className = "buttons";
searchButton.id = "search-btn";
searchButton.textContent = "🔍";
let br = document.createElement("br");
header.append(br);
header.append(searchButton);
function fetchWeather(e) {
let userInput = cityInput.value;
let config = {
Headers: {
"Content-type": "application/json",
},
};
return fetch(
`https://weatherdbi.herokuapp.com/data/weather/${userInput}`,
config
)
.then((res) => res.json())
.then((json) => weatherSearch(json, userInput))
.catch((err) => {
window.alert(
`${err} \n https://weatherdbi.herokuapp.com/data/weather/${userInput}`
);
console.log(err);
});
}
function weatherSearch(e, userInput) {
cityInput.value = "";
let weatherKeys = Object.keys(e.currentConditions);
let weatherValues = Object.values(e.currentConditions);
let temps = Object.values(weatherValues[1]);
let speeds = Object.values(weatherValues[4]);
const card = document.createElement("div");
card.id = `${userInput}-card`;
card.className = "cards";
container.append(card);
const front = document.createElement("div");
front.id = `${userInput}-front`;
front.className = "front";
front.innerHTML = `
<h1>${userInput.toUpperCase()}</h1>
<p>Time: ${weatherValues[0]}</p>
<li id="comment">Comment: ${weatherValues[6]}</li>
<li id="precipitation">Precipitation: ${weatherValues[2]}
<li id="temp">Temp: ${temps[0]}c | ${temps[1]}f</li>
<li id="humidity">Humidity: ${weatherValues[3]}</li>
<li id="wind">Wind Speed: ${speeds[0]}km | ${speeds[1]}mile</li>
</br>
<button id="notes-btn" class="buttons">Notes</button>
`;
card.append(front);
const back = document.createElement("div");
back.id = `${userInput}-back`;
back.className = "back";
back.innerHTML = `
<textarea id="back-text" name="backtext"
rows="25" placeholder="NotePad">
</textarea>
</br>
<button id="front-btn">Flip</button>
`;
let notesBtn = document.getElementById("notes-btn");
notesBtn.addEventListener("click", handleFrontClick);
console.log(notesBtn);
function handleFrontClick(e) {
e.target.parentNode.remove();
card.appendChild(back);
let frontBtn = document.getElementById("front-btn");
frontBtn.addEventListener("click", (e) => {
e.target.parentNode.remove();
card.appendChild(front);
});
}
}
document.addEventListener("DOMContentLoaded", (e) => {
searchButton.addEventListener("click", (e) => {
fetchWeather();
});
document.addEventListener("keydown", function (e) {
if (e.key === "Enter" && cityInput.value.length > 0) {
fetchWeather();
}
});
});

How should I call my function inside map method?

I want to use function instead of codes that I wrote in map method and I want to call this function (createItemCart) inside map method but I don't know how to do it.
This is createItemCart function:
const product = event.target.parentElement;
const id = product.id;
const imgProduct = product.querySelector("img").src;
const titleProduct = product.querySelector(".title").innerText;
const priceProduct = Number(product.querySelector(".price").innerText);
const qtyCheck = document.getElementById("item" + id);
let totalPrice = Number(document.querySelector(".total-price").innerText);
document.querySelector(".total-price").innerText = totalPrice + priceProduct;
function createItemCart(imgProduct, titleProduct, priceProduct, totalPrice, id) {
const itemsCart = document.getElementById("items-cart");
document.querySelector(".total-price").innerText = totalPrice + priceProduct;
const item = document.createElement("div");
item.setAttribute("class", "item-cart");
const imgItem = document.createElement("img");
imgItem.src = imgProduct;
const detailItem = document.createElement("div");
const titleItem = document.createElement("div");
titleItem.setAttribute("class", "title-item");
titleItem.innerText = titleProduct;
const divPrice = document.createElement("div");
const priceItem = document.createElement("span");
priceItem.setAttribute("class", "price-item");
priceItem.innerText = priceProduct;
const spanToman = document.createElement("span");
spanToman.innerText = "تومان";
const qtyItem = document.createElement("div");
qtyItem.className = "qty-item";
qtyItem.innerText = "1";
qtyItem.id = "item" + id;
const deleteItem = document.createElement("i");
deleteItem.className = "delete-item";
deleteItem.innerText = "x";
deleteItemCart(deleteItem, totalPrice, priceProduct);
detailItem.appendChild(titleItem);
detailItem.appendChild(divPrice);
detailItem.appendChild(qtyItem);
divPrice.appendChild(priceItem);
divPrice.appendChild(spanToman);
item.appendChild(imgItem);
item.appendChild(detailItem);
item.appendChild(deleteItem);
itemsCart.appendChild(item);
}
This is map method:
items.map((itemCart) => {
const item = document.createElement("div");
item.setAttribute("class", "item-cart");
const imgItem = document.createElement("img");
imgItem.src = itemCart.img;
const detailItem = document.createElement("div");
const titleItem = document.createElement("div");
titleItem.setAttribute("class", "title-item");
titleItem.innerText = itemCart.title;
const divPrice = document.createElement("div");
const priceItem = document.createElement("span");
priceItem.setAttribute("class", "price-item");
priceItem.innerText = itemCart.price;
const spanToman = document.createElement("span");
spanToman.innerText = "تومان";
const qtyItem = document.createElement("div");
qtyItem.className = "qty-item";
qtyItem.innerText = itemCart.qty;
qtyItem.id = "item" + itemCart.id;
totalPrice += itemCart.price * itemCart.qty;
document.querySelector(".total-price").innerText = totalPrice;
sumQty += itemCart.qty;
document.getElementById("number").innerText = sumQty;
const deleteItem = document.createElement("i");
deleteItem.className = "delete-item";
deleteItem.innerText = "x";
deleteItemCart(deleteItem, totalPrice, itemCart.price);
detailItem.appendChild(titleItem);
detailItem.appendChild(divPrice);
detailItem.appendChild(qtyItem);
divPrice.appendChild(priceItem);
divPrice.appendChild(spanToman);
item.appendChild(imgItem);
item.appendChild(detailItem);
item.appendChild(deleteItem);
itemsCart.appendChild(item);
});
For example I don't know how to use itemCart.img in createItemCart Function. Anyone can help?
You don't use itemCart.img in the function, you use it as the argument to the function.
items.forEach(itemCart =>
createItemCart(itemCart.img, itemCart.title, itemCart.price, itemCart.price * itemCart.qty, itemCart.id));
And you should use forEach() rather than map(). map() is used when you want to create an array of the results of the function, but your function doesn't return anything.

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

Keep Todo Results after browser refreshing

I created a todo app to add and remove tasks on the page.
however i would like to keep todo results when browser refreshed .
Is that possible to make this like storing data on db or any storage to save these results?
any idea to make this to save data ??
Now I posted the complete code hereee! because i cant posted code here before
let menu = document.querySelector(".bs");
let btn1 = document.querySelector(".btn");
let btn2 = document.querySelector(".btn3");
let irp = document.querySelector(".date");
let inp = document.querySelector(".input");
let bsd = document.querySelector(".sss");
let brs = document.querySelector(".marker");
let addBr = () => {
btn1.addEventListener("click", addBr);
let br = document.createElement("DIV");
let dd = document.createElement("H1");
dd.innerHTML = (inp.value);
br.className = "red";
var bn = document.createElement("H1");
bn.innerHTML = (irp.value);
menu.appendChild(br);
br.appendChild(dd);
br.appendChild(bn);
if( inp.value == "") {
br.remove();
}
else {
menu.appendChild(br);
}
if( irp.value == "") {
dd.innerHTML = "Albenis";
}
else {
menu.appendChild(br);
}
let ttt = document.createElement("BUTTON");
ttt.className = "marker";
ttt.innerHTML = "Remove";
br.appendChild(ttt);
// This is the important change. Part of creating the .ttt element
// is setting up its event listeners!
ttt.addEventListener('click', () => br.remove());
};
btn1.addEventListener("click", addBr);
// Call `addBr` once to add the initial element
addBr();
<html>
<body>
<div class="bs">
<input type="text" class="input">
<input type="date" class="date">
<button class="btn">
Add
</button>
</div>
</body>
</html>
TL;DR: use localStorage to read the items at page load and write the items when they change, like in the final version
To keep your todo entries, you need to store it in a Database. This can be either a local database in the website like localStorage. Or you need to build a backend which is connected to a Database and send and load the Data from there.
localStorage example:
const items = [{ name: "My Todo" }, { name: "My Todo 2" }];
const setItems = () => {
localStorage.setItem("items", JSON.stringify(items));
};
const getItems = () => {
return JSON.parse(localStorage.getItem("items"));
};
Including your code:
const getItems = () => {
return JSON.parse(localStorage.getItem("items"));
};
const items = getItems() || [];
const setItems = () => {
localStorage.setItem("items", JSON.stringify(items));
};
let addBr = (item) => {
let br = document.createElement("DIV");
let dd = document.createElement("H1");
dd.innerHTML = (item ? item.name : inp.value);
br.className = "red";
var bn = document.createElement("H1");
bn.innerHTML = (item ? item.name : irp.value);
if (!item) {
items.push({ name: inp.value });
setItems();
}
menu.appendChild(br);
br.appendChild(dd);
br.appendChild(bn);
if( inp.value == "") {
br.remove();
}
else {
menu.appendChild(br);
}
if( irp.value == "") {
dd.innerHTML = "Albenis";
}
else {
menu.appendChild(br);
}
let ttt = document.createElement("BUTTON");
ttt.className = "marker";
ttt.innerHTML = "Remove";
br.appendChild(ttt);
// This is the important change. Part of creating the .ttt element
// is setting up its event listeners!
ttt.addEventListener('click', () => br.remove());
};
for (const item of items) {
addBr(item);
}
btn1.addEventListener("click", () => addBr());

Categories