The items in the DOM are added multiple times - javascript

I got a problem,each time I add the element,it multiplicates itself(for example if there is 1 element in the cart,on the next click it will add 2 more,and if there are 3 elements,it will add 3 more,if 6,it will add 4 more),that's a huge problem,please help!
My js code:
let pList = document.getElementById("productList");
const addDrip = () => {
let Drip, localObj, tObj;
Drip = {
name: "Traditional Drip",
type: "normal",
price: "2.00",
imgSrc: "images/c5.png"
};
localObj = localStorage.getItem("Drip");
if(!localObj) tObj = [];
else tObj = JSON.parse(localObj);
tObj.push(Drip)
localStorage.setItem("Drip", JSON.stringify(tObj));
for(let i = 0;i < tObj.length;i++){
let htmlDrip = `
<div class="productDiv">
<p>${tObj[i].name}</p>
<p>${tObj[i].type}</p>
<p>${tObj[i].price}$</p>
<img src="${tObj[i].imgSrc}">
</div>
`
document.getElementById("productList").innerHTML += htmlDrip;
}
}
My html part:
<div class="cList">
<img src="images/c5.png"class = "tDrip">
<h1 class="Type">Traditional Drip</h1>
<button id="tAdd"onclick="addDrip()">Add Traditional Drip</button>
</div>
<div id = productList></div>

This is because your array already has the drip update from the localstorage
Simply replace your JS code with this and it will work desired way you want.
let pList = document.getElementById("productList");
const addDrip = () => {
let Drip, localObj, tObj;
Drip = {
name: "Traditional Drip",
type: "normal",
price: "2.00",
imgSrc: "images/c5.png"
};
localObj = localStorage.getItem("Drip");
console.log(localObj,"Local object")
if(!localObj) {
tObj = [];
tObj.push(Drip)
}else {
tObj = JSON.parse(localObj);
console.log(tObj,"T object")
}
localStorage.setItem("Drip", JSON.stringify(tObj));
for(let i = 0;i < tObj.length;i++){
let htmlDrip = `
<div class="productDiv">
<p>${tObj[i].name}</p>
<p>${tObj[i].type}</p>
<p>${tObj[i].price}$</p>
<img src="${tObj[i].imgSrc}">
</div>
`
document.getElementById("productList").innerHTML += htmlDrip;
}
}
you just have to push when your array is empty. Give it a try it will work.
NOTE : you can check the demo too. Just clear the localstorage if you refresh.https://www.w3schools.com/code/tryit.asp?filename=GS7FA0970MF3

You don't actually need to loop thru the array while adding the new item.
You can first get the items from localStorage
HTML:
<div class="cList">
<img src="images/c5.png" class="tDrip">
<h1 class="Type">Traditional Drip</h1>
<button id="tAdd" onclick="addDrip()">Add Traditional Drip</button>
</div>
<div id="productList"></div>
Script:
const pList = document.getElementById("productList");
let localObj = JSON.parse(localStorage.getItem("Drip"));
const parseItems = () => {
if (!localObj) localObj = [];
for (let i = 0; i < localObj.length; i++) {
let htmlDrip = `
<div class="productDiv">
<p>${localObj[i].name}</p>
<p>${localObj[i].type}</p>
<p>${localObj[i].price}$</p>
<img src="${localObj[i].imgSrc}">
</div>
`;
pList.innerHTML += htmlDrip;
}
}
parseItems();
const addDrip = () => {
let Drip;
Drip = {
name: "Traditional Drip",
type: "normal",
price: "2.00",
imgSrc: "images/c5.png"
};
if (!localObj) localObj = [];
localObj.push(Drip);
localStorage.setItem("Drip", JSON.stringify(localObj));
let htmlDrip = `
<div class="productDiv">
<p>${Drip.name}</p>
<p>${Drip.type}</p>
<p>${Drip.price}$</p>
<img src="${Drip.imgSrc}">
</div>
`;
pList.innerHTML += htmlDrip;
}

Related

how to reuse a variable with everything and its value in another page of my project

im working on a e-commerce and im trying to do the page where you fill your info, but i cant use my variable cart, or my total.textContent i just need to show my cart, the total of the cart and my form but i cant use any of my variables or functions
enter code here
const container = document.getElementById("container");
const cartContainer = document.getElementById("cart-items");
let cart = [];
export let stock = [
{id: 1, item: "Playera blanca - Logo rojo", precio: 265, imagen: '<img class="cart-review-img" src="./images/Playera blanca - Logo rojo.png" alt="">'
}];
const upDateCart = () => {
cartContainer.innerHTML = ""
cart.forEach((prod) => {
const div = document.createElement("div")
div.className = ("cart-review-cotainer")
div.innerHTML = `
<div class="cart-image col-md-5">
${prod.imagen}
</div>
<div class="col-md-5 d-flex flex-column justify-content-between">
<div>
<p id="cart-item-name">${prod.item}</p>
<p id="cart-item-price">${prod.precio}</p>
</div>
</div>
<div class="col-md-2 delete-container">
<button onclick="deleteItem(${prod.id})" id="delete-item"><img class="delete-img" src="./images/trash-solid.svg" alt=""></button>
</div>
`
cartContainer.appendChild(div)
localStorage.setItem("newCart", JSON.stringify(cart))
})
total.innerText = cart.reduce((acc, prod) => acc + prod.precio, 0)
}
if(localStorage.getItem("newCart")) {
newCart = JSON.parse(localStorage.getItem("newCart"))
console.log(newCart)
upDateCart()
}
window.deleteItem = deleteItem;
window.cart = cart;
window.test = test;
window.newCart = newCart;
my files in vs code
I couldn't run your snippet, but I guess
if(localStorage.getItem("newCart")) {
newCart = JSON.parse(localStorage.getItem("newCart"))
console.log(newCart)
cart = newCart; // 👈 add this line maybe?
upDateCart()
}

Passing javaScript from one page to another in wordpress

This is javascript code of getting the REST API using strapi.
Im looping through myObject array and printing out products dynamically.
Im getting the element.id from the loop and saving it in a variable with a function called getInfo. The code is currently switching
let laptopsUrl = ''
function getInfo(props){
laptopsUrl = '/'+ props
console.log(laptopsUrl);
renderObjects(laptopsUrl);
}
async function renderObjects(props){
let apiUrl = "http://localhost:1337";
console.log(apiUrl);
console.log('test'+ props);
let urlLocalhost = apiUrl +`/api/Laptops${props}?populate=`;
console.log('Hello' + props)
let stringResponse = await fetch (urlLocalhost);
let myobject = await stringResponse.json();
let output = '';
let index = 0;
let title = '';
let details = '';
let price = '';
let qty = '';
//Kolla om data är en array
if(Array.isArray(myobject.data)){
myobject.data.forEach(element => {
let attr = element.attributes;
console.log(element);
output += `
<div class="grid-item" onclick="getInfo(${element.id})">
<div class="laptop-image">
<img src="${laptopsImages[index].image}"></img>
</div>
<div class="item-info">
<div class="item-title">${attr.Title}</div>
<div>Price: ${attr.Price}</div>
<div>Qty: ${attr.Qty}</div>
</div>
</div>
`;
index++;
});
}else{
let object = myobject.data.attributes;
title += `<div class="title"> Title: ${object.Title}</div>`;
details += `<div> Description: ${object.Description}</div>`;
price += `<div> Price: ${object.Price}</div>`;
qty+= `<div> In stock: ${object.Qty}</div>`;
}
document.getElementById('output').innerHTML = output;
document.getElementById("title").innerHTML = title;
document.getElementById("details").innerHTML = details ;
}
renderObjects(laptopsUrl);
This is HTML to print out products
<body>
<div id ="output">
</div>
<div id ="details">
</div>
<div id ="title">
</div>
<!-- </div> -->
</body>

How to delete an item from an array from localstorage onclick

I have the following code. It stores the info on localstorage each time the user clicks on an "add to cart" button:
let addCartItemButtons = document.getElementsByClassName('product-description-add')
for (let i = 0; i < addCartItemButtons.length; i++){
let button = addCartItemButtons[i]
button.addEventListener('click', addProduct)
}
function addProduct(event) {
let buttonClicked = event.target
let getTitle = buttonClicked.parentElement.parentElement.parentElement.querySelector('.product-title').innerText
let getImage = buttonClicked.parentElement.parentElement.parentElement.querySelector('.product-header img').src
let getColor = buttonClicked.parentElement.parentElement.querySelector('.product-description-text li span').innerText
let getSize = buttonClicked.parentElement.parentElement.querySelector('.product-description-text li select').value
let getPrice = buttonClicked.parentElement.parentElement.querySelector('.product-description-price').innerText
let getSpan = buttonClicked.parentElement.parentElement.querySelector('li span').getAttribute('id')
let oldItems = JSON.parse(localStorage.getItem('newProduct')) || [];
let newItem = {
'title': getTitle,
'image': getImage,
'color': getColor,
'size': getSize,
'price': getPrice,
'spanid': getSpan,
};
oldItems.push(newItem);
localStorage.setItem('newProduct', JSON.stringify(oldItems));
}
Then, i have a code that allows me to display the data the user have locally stored by creating divs and displaying the info:
let cartProducts = JSON.parse(localStorage.getItem("newProduct"))
for(let i = 0; i < cartProducts.length; i++){
let newCartProduct = document.createElement('div')
newCartProduct.classList.add('product')
newCartProduct.classList.add('cart')
const image = cartProducts[i].image
const title = cartProducts[i].title
const spanid = cartProducts[i].spanid
const color = cartProducts[i].color
const size = cartProducts[i].size
const price = cartProducts[i].price
let newCartProductContent = `
<div class="product-header cart"><img src="${image}" alt="" /></div>
<div class="product-content">
<h3 class="product-title" id="product-title">
${title}
</h3>
<div class="product-description">
<ul class="product-description-text cart">
<li>Color: <span id="${spanid}">${color} </span></li>
<li>Size: ${size} </li>
<li>Quantity: <input type="number" class="product-description-quantity" min="1" placeholder="2" value="2"></li>
</ul>
<p class="product-description-price" id="price1">
${price}
</p>
**Remove<i class="fas fa-trash"></i>**
</div>
</div>`
newCartProduct.innerHTML = newCartProductContent
let cartItems = document.getElementsByClassName('products_container_first-row')[0]
cartItems.append(newCartProduct)
}
So what i need to do now is to create a function that allows me to delete the data that it's the same which is on localstorage, each time that the user clicks on a "remove" button (in the above code is the line which has the ** ** at beginning and ending), but i cant figure out how to do this. Any ideas? Thanks!
UPDATE: i've come to this code but i get -1 as index for each element:
let addCartItemButtons = document.getElementsByClassName('product-description-add')
for (let i = 0; i < addCartItemButtons.length; i++){
let button = addCartItemButtons[i]
button.addEventListener('click', function(event){
let buttonClicked = event.target
let getTitle = buttonClicked.parentElement.parentElement.parentElement.querySelector('.product-title').innerText
let getImage = buttonClicked.parentElement.parentElement.parentElement.querySelector('.product-header img').src
console.log(getImage)
let getColor = buttonClicked.parentElement.parentElement.querySelector('.product-description-text li span').innerText
let getSize = buttonClicked.parentElement.parentElement.querySelector('.product-description-text li select').value
let getPrice = buttonClicked.parentElement.parentElement.querySelector('.product-description-price').innerText
let getSpan = buttonClicked.parentElement.parentElement.querySelector('li span').getAttribute('id')
console.log(getSpan)
let oldItems = JSON.parse(localStorage.getItem('newProduct')) || [];
let newItem = {
'id': i+1,
'title': getTitle,
'image': getImage,
'color': getColor,
'size': getSize,
'price': getPrice,
'spanid': getSpan,
};
oldItems.push(newItem);
localStorage.setItem('newProduct', JSON.stringify(oldItems));
})
}
let cartProducts = JSON.parse(localStorage.getItem("newProduct"));
for(let i = 0; i < cartProducts.length; i++){
let newCartProduct = document.createElement('div')
newCartProduct.classList.add('product')
newCartProduct.classList.add('cart')
console.log(newCartProduct)
const id = cartProducts[i].id
const image = cartProducts[i].image
const title = cartProducts[i].title
const spanid = cartProducts[i].spanid
const color = cartProducts[i].color
const size = cartProducts[i].size
const price = cartProducts[i].price
let newCartProductContent = `
<div class="product-header cart" id="${id}"><img src="${image}" alt="" /></div>
<div class="product-content">
<h3 class="product-title" id="product-title">
${title}
</h3>
<div class="product-description">
<ul class="product-description-text cart">
<li>Color: <span id="${spanid}">${color} </span></li>
<li>Size: ${size} </li>
<li>Quantity: <input type="number" class="product-description-quantity" min="1" placeholder="2" value="2"></li>
</ul>
<p class="product-description-price">
${price}
</p>
Remove<i class="fas fa-trash"></i>
</div>
</div>`
newCartProduct.innerHTML = newCartProductContent
let cartItems = document.getElementsByClassName('products_container_first-row')[0]
cartItems.append(newCartProduct)
}
function lsdel(storage_name, value){
if (localStorage.getItem(storage_name) === null) {
} else {
var ls_data = JSON.parse(localStorage.getItem(storage_name));
var index = ls_data.indexOf(value);
console.log("selected index:"+index);
if(index == -1){
// if not matched selected index
} else {
// is matched, remove...
ls_data.splice(index, 1);
localStorage.setItem(storage_name, JSON.stringify(ls_data));
console.log(ls_data);
}
}
}
value is the ID of an element, but ls_data is an array of objects, not IDs. So ls_data.indexOf(value) will not find the object in the array. And even if value were an object, this wouldn't work because object equality is based on identical objects in memory, not comparing contents.
You need to use findIndex to match the id property of an array element.
function lsdel(storage_name, value) {
if (localStorage.getItem(storage_name) === null) {} else {
var ls_data = JSON.parse(localStorage.getItem(storage_name));
var index = ls_data.findIndex(({id}) => id == value);
console.log("selected index:" + index);
if (index == -1) {
// if not matched selected index
} else {
// is matched, remove...
ls_data.splice(index, 1);
localStorage.setItem(storage_name, JSON.stringify(ls_data));
console.log(ls_data);
}
}
}

Repeated objects with input values

I have a javascript repeater that creates forms,
but the problem is that when I bring the values ​​they are all entered in a single object instead of separate objects, which inside array locations should create a similar structure.
"locations":[
{
"coordinates":[
-80.128473,
25.781842
],
"description":"Lummus Park Beach",
"day":1
},
{
"coordinates":[
-80.647885,
24.909047
],
"description":"Islamorada",
"day":2
},
]
My code takes information from inputs but puts it in the same object instead of separate objects.
//This is the code which take input value and inser in boject structure
const createTour_form = document.querySelector('.form-create__tour');
if (createTour_form) {
createTour_form.addEventListener('submit', (cr) => {
cr.preventDefault();
//Ceeate an empty array
let loc_coordinates = [];
let loc_description = [];
let loc_day = [];
let get_locations = [];
//Get Coordinates
document.querySelectorAll(".location_field_card").forEach(f => {
let obj = [];
f.querySelectorAll(".location_new_tour").forEach(ele => obj[ele.value] = ele.value || "");
loc_coordinates.push(Object.keys(obj));
});
//Get Descriptions
document.querySelectorAll(".location_field_card").forEach(f => {
let obj1 = {};
f.querySelectorAll(".description_location").forEach(ele => obj1[ele.name] = ele.value || "");
loc_description.push(obj1)
});
//Get Day
document.querySelectorAll(".location_field_card").forEach(f => {
let obj2 = {};
f.querySelectorAll(".location_day").forEach(ele => obj2[ele.name] = ele.value || "");
loc_day.push(obj2)
});
//Reverse Coordinates
const getGeo = [...loc_coordinates].toString().split(',').reverse().join(' ').replace(' ', ' ,');
get_locations.push(getGeo)
const getLocation = Object.values(...loc_description);
const getValLocation = getLocation.toString();
const getDay = Object.values(...loc_day);
const getValDay =parseInt(getDay.toString());
let getTotaLocation = new Object({
"coordinates":[...get_locations],
"description":getValLocation,
"day":getValDay
});
console.log(getTotaLocation);
})
}
<form class="form form-create__tour">
<h1 class="title--create--tourpage">Locations</h1>
<div class="form__group all_tours_options">
<div id="add_location_field">
<div class="location_field_card">
<p class="subfield_natours_create_tour">Location</p>
<input class="form__input location_new_tour" type="text" value="24.5647846,-81.8068843">
<p class="subfield_natours_create_tour">Location Description</p>
<input class="form__input description_location" type="text" value="Lummus Park Beach">
<p class="subfield_natours_create_tour">Day</p>
<input class="form__input location_day" type="number" value="1" >
</div>
</div>
<button class="btn btn--small--add btn--green" id="add_location_fields">Add Location Field</button>
</div>
<div class="form__group right"><button class="btn btn--small btn--green" id="createTour">Create Tour</button></div>
</form>
<!--This Javascript code generate new fields when Add Locaton field is clicked-->
<script>
const addLocation = document.getElementById('add_location_fields');
if(addLocation){
let count_createdCards = 0;
let count_Deletebutton = 0;
let incrementFunction = 0;
addLocation.addEventListener('click',(st)=>{
st.preventDefault();
let createAddField = document.getElementById('add_location_field');
// Crd
count_createdCards++;
count_Deletebutton ++;
incrementFunction ++;
let card = document.createElement('div');
card.setAttribute('class','location_field_card');
card.setAttribute('id','delete_card_'+ count_createdCards)
//First Card Title
let cartTitle1 = document.createElement('p');
cartTitle1.setAttribute('class','subfield_natours_create_tour');
cartTitle1.textContent = 'Location';
let inputLocation = document.createElement('input');
inputLocation.classList.add('form__input');
inputLocation.classList.add('location_new_tour');
inputLocation.setAttribute('type','text');
inputLocation.setAttribute('value','24.5647846,-81.8068843');
//Second Card Title
let cartTitle2 = document.createElement('p');
cartTitle2.setAttribute('class','subfield_natours_create_tour');
cartTitle2.textContent = 'Location Description';
let inputDescription_location = document.createElement('input');
inputDescription_location.classList.add('form__input');
inputDescription_location.classList.add('description_location');
inputDescription_location.setAttribute('type','text');
inputDescription_location.setAttribute('value','Lummus Park Beach');
//Third Card Title
let cartTitle3 = document.createElement('p');
cartTitle3.setAttribute('class','subfield_natours_create_tour');
cartTitle3.textContent = 'Day';
let inputDescription_day = document.createElement('input');
inputDescription_day.classList.add('form__input');
inputDescription_day.classList.add('location_day');
inputDescription_day.setAttribute('type','number');
inputDescription_day.setAttribute('value','1');
let removeButton = document.createElement('a');
removeButton.classList.add('btn');
removeButton.classList.add('btn--small--add');
removeButton.classList.add('btn--red');
removeButton.setAttribute('onclick','removeAction_'+count_Deletebutton+'()');
let removeScript = document.createElement('script');
removeScript.innerHTML = "function removeAction_".concat(count_Deletebutton, "() {\n\n var delCard_")
.concat(incrementFunction, " = document.getElementById(\"delete_card_")
.concat(count_createdCards, "\");\ndelCard_")
.concat(incrementFunction, ".remove();}");
removeButton.textContent = 'Remove Location Field';
card.appendChild(cartTitle1);
card.appendChild(inputLocation);
card.appendChild(cartTitle2);
card.appendChild(inputDescription_location);
card.appendChild(cartTitle3);
card.appendChild(inputDescription_day);
card.appendChild(removeButton);
card.appendChild(removeScript);
createAddField.appendChild(card);
});
}
</script>
I solved the problem by adding in the folds that repeat the dynamic id:
//Increment Coordinates
let incrementCoordiantes = 0;
//Increment Description
let incrementDescription = 0;
//Increment Day
let incrementDay = 0;
addLocation.addEventListener('click',(st)=>{
let createAddField = document.getElementById('add_location_field');
incrementCoordiantes ++;
incrementDescription ++;
incrementDay ++;
let card = document.createElement('div');
......
inputLocation.setAttribute('id','getCoordinates_'+ incrementCoordiantes);
inputDescription_location.setAttribute('id','getDescription_' + incrementDescription);
inputDescription_day.setAttribute('id','getDay_' + incrementDay );
I use querySelectorAll to get the number of colums from repeater and after that I use for to incremet id to match the id from html file, all the value it's push after that in an array, and it's work.
const push_location_data = [];
const getAll_locations = document.querySelectorAll(".location_field_card");
for (let i=1; i< getAll_locations.length; i++) {
let cord_lat_lng = 'getCoordinates_' + i;
let cord_description = 'getDescription_' + i;
let cord_day = 'getDay_' + i;
let dinamic_obj = {
coordinates:[[document.getElementById(cord_lat_lng).value].toString().split(',').reverse().join(' ').replace(' ', ' ,')],
description:document.getElementById(cord_description).value,
day:document.getElementById(cord_day).value
}
push_location_data.push(dinamic_obj);
};
location arrray

How to put the value of a function inside the template literal?

Im making a comment system and is required to put the stars inside of template literal with the purpose that the number of stars stay next to the name of the person.
Until now the value is showing me "undefined"
screenshoot screenshot comment system
this is the javascript code
const txtNombre = document.getElementById("text-nombre");
const txtParrafo = document.getElementById("text-area");
const boton = document.getElementById("btnAgregar");
const listado = document.getElementById("contenedor-filas");
const radio = document.getElementsByName("rate");
boton.addEventListener("click", agregarALista);
function agregarALista() {
let nombre = txtNombre.value;
var valor = txtParrafo.value;
const elHtml = document.createElement("div");
elHtml.innerHTML = `
<div class="row" id="fila-segunda">
<div class = "col-6">
${nombre}
</div>
<div class = "col-6">
${estrellitas()}
</div>
</div>
<div class="row" id="fila-tercera">
<div class = "col">
${valor}
</div>
</div>
`;
listado.appendChild(elHtml);
txtNombre.value = "";
txtParrafo.value = "";
}
let estrellitas = function() {
radio.forEach(function(elementos) {
if (elementos.checked) {
estrellas = document.createElement("h3");
estrellas.setAttribute("class", "stars");
let s = "";
for (i = 0; i < elementos.value; i++) {
s += "★";
}
estrellas.textContent = s;
listado.appendChild(estrellas);
}
});
}
Your function estrellitas() is missing a return statement and will therefore return undefined. Otherwise, your syntax for including function return values in string template literals is correct:
let x = (a, b) => a > b;
let a = 10, b = 20;
console.log(`${a} is greater than ${b}? ${x(a, b)}`);

Categories