I'm trying to calculate the total price of my cart. It works when I only select the same product but when I chose another product it just multiplies the number of clicks to the total price. How can I rewrite this so it doesn't multiply the amount of clicks?
GIF of my problem: https://gyazo.com/c273f1d8a3caa3cded6debef52cfadaf
const shopContainer = document.querySelector(".shop-content");
let productTitle;
let productDescription;
let productImage;
let productPrice;
let productCategory;
let productId;
let productKey = [];
let productArray = [];
let output = "";
const url = "https://fakestoreapi.com/products";
let data = fetch(url)
.then((res) => res.json())
.then((data) => {
for (let i = 0; i < data.length; i++) {
productTitle = data[i].title;
productDescription = data[i].description;
productImage = data[i].image;
productPrice = data[i].price;
productCategory = data[i].category;
productId = data[i].id;
productArray[i] = [
productTitle,
productDescription,
productImage,
productPrice,
productCategory,
productId,
];
productKey[i] = data[i].id;
localStorage.setItem(productKey[i], JSON.stringify(productArray[i]));
}
showApi();
})
.catch((error) => {
console.error("Error message:", error);
});
function showApi() {
for (let i = 0; i < productArray.length; i++) {
productId = productArray[i][5];
output += `
<div class="product-box">
<img class="product" src="${productArray[i][2]}" alt="product image">
<h2 class="product-title">${productArray[i][0]}</h2>
<div class="bottom-box">
<span class="price">${productArray[i][3]}$</span>
<i class='bx bx-shopping-bag add-cart' "data-id="${productId}" onclick="returnKey(${productArray[i][5]})"></i>
</div>
</div>
`;
}
shopContainer.innerHTML = output;
}
let inputCart = document.querySelector(".inputCart");
function returnKey(clickedId) {
cart.classList.add("active");
console.log(clickedId);
if (localStorage.length !== 0) {
let sum = 0;
Object.keys(localStorage).forEach(function (key) {
productObject = JSON.parse(localStorage.getItem(key));
completeProduct = productObject;
sum += completeProduct[3];
if (completeProduct[5] == clickedId) {
let cartPrice = document.createElement("p");
let cartTitle = document.createElement("p");
let cartImage = document.createElement("img");
inputCart.appendChild(cartPrice);
inputCart.appendChild(cartImage);
inputCart.appendChild(cartTitle);
cartPrice.setAttribute("class", "cart-price")
cartTitle.setAttribute("class", "cart-title");
cartImage.setAttribute("src", completeProduct[2]);
cartImage.setAttribute("width", "75");
cartImage.setAttribute("height", "75");
cartTitle.innerHTML = completeProduct[0];
cartPrice.innerHTML = "$" + completeProduct[3];
console.log(cartPrice);
console.log(cartTitle);
document.getElementById('priceTotal').innerHTML = "Total: " + sum + "$";
console.log(sum)
}
})
}
};
// function totalSum(cartPrice) {
// sum = 0;
// cartPrice = document.querySelectorAll(".cart-price");
// for (let i = 0; i < cartPrice.length; i++) {
// sum = sum + completeProduct[3];
// console.log("Product price " + sum);
// document.getElementById('priceTotal').innerHTML = "Total: " + sum + "$";
// }
// }
let removeBtn = document.getElementById("removeBtn").addEventListener("click", clearCart);
let buyBtn = document.getElementById("buyBtn").addEventListener("click", buyCart);
function clearCart() {
removeCart = window.confirm("Are you sure you want to clear your cart?");
if (removeCart) {
inputCart.innerHTML = "";
document.getElementById('priceTotal').innerHTML = "Total: " + "0" + "$";;
console.clear();
}
};
function buyCart() {
shopMore = window.confirm("Do you want to checkout?");
if (shopMore) {
alert("Thank your for shopping at CatchShop!");
window.location.reload();
}
};
let cartIcon = document.querySelector("#cart-icon");
let cart = document.querySelector(".cart");
let closeCart = document.querySelector("#close-cart");
cartIcon.onclick = () => {
cart.classList.add("active");
};
closeCart.onclick = () => {
cart.classList.remove("active");
};
Thanks in advance! :)
You are calling the totalSum() function for every item. And sum always gets "reset" to 0. Try to add let sum = 0 before this line Object.keys(localStorage).forEach(function (key) {
function totalSum() {
cartPrice = document.querySelectorAll(".cart-price");
let sum = 0; // Everytime this function gets called, sum gets reset
for (let i = 0; i < cartPrice.length; i++) {
sum = sum + completeProduct[3];
console.log(sum);
document.getElementById('priceTotal').innerHTML = "Total: " + sum + "$";
}
}
Solution:
let inputCart = document.querySelector(".inputCart");
function returnKey(clickedId) {
cart.classList.add("active");
console.log(clickedId);
if (localStorage.length !== 0) {
let sum = 0;
Object.keys(localStorage).forEach(function (key) {
productObject = JSON.parse(localStorage.getItem(key));
completeProduct = productObject;
if (completeProduct[5] == clickedId) {
let cartPrice = document.createElement("p");
let cartTitle = document.createElement("p");
let cartImage = document.createElement("img");
inputCart.appendChild(cartPrice);
inputCart.appendChild(cartImage);
inputCart.appendChild(cartTitle);
cartPrice.setAttribute("class", "cart-price")
cartTitle.setAttribute("class", "cart-title");
cartImage.setAttribute("src", completeProduct[2]);
cartImage.setAttribute("width", "75");
cartImage.setAttribute("height", "75");
cartTitle.innerHTML = completeProduct[0];
cartPrice.innerHTML = "$" + completeProduct[3];
console.log(cartPrice);
console.log(cartTitle);
totalSum(sum);
}
})
}
};
function totalSum(sum) {
cartPrice = document.querySelectorAll(".cart-price");
for (let i = 0; i < cartPrice.length; i++) {
sum = sum + completeProduct[3];
console.log(sum);
document.getElementById('priceTotal').innerHTML = "Total: " + sum + "$";
}
}
Edit Solution:
You don't even need the totalSum function. You can simply increase the value of the sum variable with the current price of the local storage object you are iterating.
let inputCart = document.querySelector(".inputCart");
function returnKey(clickedId) {
cart.classList.add("active");
console.log(clickedId);
if (localStorage.length !== 0) {
let sum = 0;
Object.keys(localStorage).forEach(function (key) {
productObject = JSON.parse(localStorage.getItem(key));
completeProduct = productObject;
sum += completeProduct[3];
if (completeProduct[5] == clickedId) {
let cartPrice = document.createElement("p");
let cartTitle = document.createElement("p");
let cartImage = document.createElement("img");
inputCart.appendChild(cartPrice);
inputCart.appendChild(cartImage);
inputCart.appendChild(cartTitle);
cartPrice.setAttribute("class", "cart-price")
cartTitle.setAttribute("class", "cart-title");
cartImage.setAttribute("src", completeProduct[2]);
cartImage.setAttribute("width", "75");
cartImage.setAttribute("height", "75");
cartTitle.innerHTML = completeProduct[0];
cartPrice.innerHTML = "$" + completeProduct[3];
console.log(cartPrice);
console.log(cartTitle);
document.getElementById('priceTotal').innerHTML = "Total: " + sum + "$";
}
})
}
};
Edit:
function returnKey(clickedId) {
cart.classList.add("active");
console.log(clickedId);
if (localStorage.length !== 0) {
Object.keys(localStorage).forEach(function (key) {
productObject = JSON.parse(localStorage.getItem(key));
completeProduct = productObject;
if (completeProduct[5] == clickedId) {
let cartPrice = document.createElement("p");
let cartTitle = document.createElement("p");
let cartImage = document.createElement("img");
inputCart.appendChild(cartPrice);
inputCart.appendChild(cartImage);
inputCart.appendChild(cartTitle);
cartPrice.setAttribute("class", "cart-price")
cartTitle.setAttribute("class", "cart-title");
cartImage.setAttribute("src", completeProduct[2]);
cartImage.setAttribute("width", "75");
cartImage.setAttribute("height", "75");
cartTitle.innerHTML = completeProduct[0];
cartPrice.innerHTML = "$" + completeProduct[3];
console.log(cartPrice);
console.log(cartTitle);
let cartElements = document.getElementsByClassName('cart-price');
let sum = 0;
for (let i = 0; i < cartElements.length; ++i) {
let item = cartElements[i];
let price = item.innerText;
// Get rid of the $ sign and convert it to int
sum += parseInt(price.slice(1));
}
let inputCart = document.querySelector(".inputCart");
document.getElementById('priceTotal').innerHTML = "Total: " + sum + "$";
}
})
}
};
You are rewriting the innerHTML of the priceTotal element with the current sum value every cycle of the for loop.
the problem is only in the bottom function objectPutter
specifically the line with wowza.split(' '); labelled with the comment
let eq
let x = null
let bracketNum = 0
let k = 0
let pre = 0
class subEqCreator { //subEq object
constructor() {
this.precede = 0;
this.text = '';
}
parser() {
this.text += eq[k]
}
ma() {
this.text.split(' ')
}
};
function trigger() { //used for HTML onClick method
show();
brackets();
subEqDynamic()
parseEquation();
objectPutter()
};
function show() {
const recent = document.querySelector("ol");
const txt = document.getElementById('input');
eq = txt.value;
li = document.createElement('li');
li.innerText = eq;
recent.appendChild(li);
txt.value = '';
};
function brackets() { //counts how many brackets appear
for (let i = 0; i < eq.length; i++) {
if (eq[i] == "(") {
bracketNum++;
};
};
};
let subEqDynamic = function() { // creates a new object for each bracket
for (let count = 0; count <= bracketNum; count++) {
this['subEq' + count] = x = new subEqCreator()
};
};
function parseEquation() { // assign characters to SubEq object
let nextIndex = 0;
let currentIndex = 0;
let lastIndex = [0];
let eqLen = eq.length;
let nex = this['subEq' + nextIndex]
for (k; k < eqLen; k++) {
if (eq[k] == "(") {
nextIndex++;
pre++
this['subEq' + currentIndex].text += '( )';
this['subEq' + nextIndex].precede = pre;
lastIndex.push(currentIndex);
currentIndex = nextIndex;
} else if (eq[k] == ")") {
pre--
currentIndex = lastIndex.pop();
} else {
this['subEq' + currentIndex].parser()
}
}
}
function objectPutter() {
for (let i = 0; i < bracketNum; i++) {
let wowza = this['subEq' + i].text
wowza.split(' '); // 🚩 why isnt it working here
console.log(subEq0);
for (let j = 1; j <= wowza.length; j += 2) { // for loop generates only odds
let ni = i++
wowza.splice(j, 0, this['subEq' + ni])
console.log(i)
}
}
}
to fix this i tried;
making a method for it ma() in the constructor.
putting in the function parseEquation above in case it was a scope issue.
also, i noticed subEq0.split(' ') worked in browser console even replicating it to the way i done it using this['subEq' + i].text.split(' ') where i = 0.
After it runs the it says .splice is not a function and console.log(subEq0) shows subEq0.text is still a string
.split() does not change the variable it returns the splitted variable
I want to create a function called totalPriceCheck that console.log's the total of all shoppingCart items together.
var shoppingCart = [];
function addToCart (name, price) {
var object = {};
object.name = name;
object.price = price;
shoppingCart.push(object);
}
function priceCheck(item){
for (var i = 0; i < shoppingCart.length; i += 1) {
if (item === shoppingCart[i].name) {
console.log(shoppingCart[i].price + " sheqalim");
} else {
console.log("the searched item is not in the shopping cart array!");
}
}
}
function totalPriceCheck(){
for (var i = 0; i < shoppingCart.length; i += 1) {
var totalPriceOf = shoppingCart[i].price;
var myTotal = 0;
for(var i = 0, len = totalPriceOf.length; i < len; i++) {
myTotal += totalPriceOf.price;
}
console.log(myTotal);
}
}
addToCart ('beer', 5);
totalPriceCheck();
I can't understand your question properly but I think you need output like this.
I am doing some changes in your code, please refer below code
output of below code is :- 15
if you add addToCart('beer', 5); than out put will be 20
var shoppingCart = [];
function addToCart(name, price) {
var object = {};
object.name = name;
object.price = price;
shoppingCart.push(object);
}
addToCart('beer', 5);
addToCart('beer', 5);
addToCart('beer', 5);
function totalPriceCheck() {
var myTotal = 0;
for (var i = 0; i < shoppingCart.length; i += 1) {
var totalPriceOf = shoppingCart[i].price;
myTotal += totalPriceOf;
}
console.log(myTotal);
}
totalPriceCheck();
You can use reduce to get the sum :
function totalPriceCheck(){
return shoppingCart.reduce(
(acc, elem)=>acc + elem.price,
0
);
}
I have an array of objects and want to create another array of objects based on.
I want to check if an object is repeated just want to show the count, otherwise show the object itself with count = 1.
<!-- I have an array-->
var arr =[{name:"coke",price:20},{name:"coke",price:20},{name:"coke",price:20},{name:"kabab",price:250}];
// I want to create another array based on "arr" like the one below
var test =[{name:"coke",price:20,count:3},{name:"kabab",price:20,count:1}];
//Any hint please
This may help you. This answer considers name or some identifier will be unique for each object.
counter = {}
var arr = [{
name: "coke",
price: 20
}, {
name: "coke",
price: 20
}, {
name: "coke",
price: 20
}, {
name: "kabab",
price: 250
}];
var obj = {};
var counter = {}
for (var i = 0, len = arr.length; i < len; i++) {
obj[arr[i]['name']] = arr[i];
counter[arr[i]['name']] = (counter[arr[i]['name']] || 0) + 1
}
newArr = new Array();
for (var key in obj){
newArr.push(extend( obj[key], {count:counter[key]}));
}
function extend(a, b){
for(var key in b)
if(b.hasOwnProperty(key))
a[key] = b[key];
return a;
}
console.log(newArr)
var arr =[{name:"coke",price:20},{name:"coke",price:20},{name:"coke",price:20},{name:"kabab",price:250}];
var countNameMapping = {}, finalArr = [];
var arrLength = arr.length;
for(i=0; i<arrLength; i++){
var tempObj = {name:arr[i], price:arr[i].price, occurance:1};
var productName = arr[i].name;
if(countNameMapping[productName] === undefined){
countNameMapping[productName] = tempObj;
}else{
countNameMapping[productName].occurance += 1;
}
}
for(var k in countNameMapping){
finalArr.push(countNameMapping[k])
}
console.log(finalArr );
You can try this one:
var arr =[{name:"coke",price:20},{name:"coke",price:20},{name:"coke",price:20},{name:"kabab",price:250}];
var result = [];
arr.map(function(arrObject) {
if (result.length > 0) {
result.map(function(resultObject) {
if (resultObject.name != arrObject.name) {
arrObject.count = 1;
result.push(arrObject);
} else {
resultObject.count++;
}
})
} else {
arrObject.count = 1;
result.push(arrObject);
}
})
console.log(result);
This will provide the result you are looking for:
var arr =[{name:"coke",price:20},{name:"coke",price:20},{name:"coke",price:20},{name:"kabab",price:250}];
var map = arr.reduce((accum, item) => {
var obj = accum.get(item.name) || Object.assign({}, item, {count:0});
obj.count++;
return accum.set(item.name, obj);
}, new Map());
var res = [...map.values()];
More or less...
var arr = [{
name: "coke",
price: 20
}, {
name: "coke",
price: 20
}, {
name: "coke",
price: 20
}, {
name: "kabab",
price: 250
}];
// I want to create another array based on "arr" like the one below
// var test =[{name:"coke",price:20,count:3},{name:"kabab",price:20,count:1}];
var count = {};
var test = [];
for (var i = 0, len = arr.length; i < len; i++) {
var id = JSON.stringify(arr[i]);
if (count.hasOwnProperty(id)) {
count[id].count++;
} else {
test.push(arr[i]); // Data contamination. Too lazy to copy object
count[id] = test[test.length - 1]; // Could be better.
count[id].count = 1;
}
}
console.log(test);
This is probably what are you looking for:
How does it work?
First, your array arr will use a forEach loop to find each object and if if new you will add it to the results array. The method isNew() will return true if the object is new.
For each new object founded you will count the number of occurrences using findOccurrences() To reduce the number of "loops" you will slice the array according to the index. So you don't need to search again over the already processed data.
So now you can build an new object, using the name, price and count.
Finally, you can push() the new object to the results array.
var arr =[{name:"coke",price:20},{price:20,name:"coke"},{name:"coke",price:20},{name:"kabab",price:250}];
var results = [];
var index = 0;
var originalDiv = document.getElementById('original');
var resultsDiv = document.getElementById('results');
arr.forEach(function(obj) {
if (isNew(obj)) {
var counter = findOccurrences(obj, arr.slice(index, arr.length));
var newObj = {
name: obj.name,
price: obj.price,
count: counter
}
results.push(newObj);
}
index++;
});
printArray(arr, originalDiv);
printArray(results, resultsDiv);
function isNew(newObj) {
var wasFound = true;
if (typeof results != "undefined" && results != null && results.length > 0) {
results.forEach(function(obj) {
if (newObj.name === obj.name && newObj.price === obj.price) {
return false;
} else {
wasFound = false;
}
});
return !wasFound;
} else {
return true;
}
}
function findOccurrences(newObj, objects) {
var count = 0;
if (typeof objects != "undefined" && objects != null && objects.length > 0) {
objects.forEach(function(obj) {
if (newObj.name === obj.name && newObj.price === obj.price) {
count++;
}
});
}
return count;
}
function printArray(objects, div) {
var count = 0;
if (typeof objects != "undefined" && objects != null && objects.length > 0) {
objects.forEach(function(obj) {
var newElement = document.createElement('p');
newElement.innerHTML = 'item ' + count + ': ';
Object.keys(obj).forEach(function(key) {
newElement.innerHTML += key + ': ' + obj[key] + ', ';
});
newElement.innerHTML = newElement.innerHTML.slice(0, -2);
div.appendChild(newElement);
count++;
});
}
}
<div id="original"><p>Original Array</p></div>
<div id="results"><p>Results Array</p></div>
Update:
More optimization.
var arr =[{name:"coke",price:20},{name:"coke",price:20},{name:"coke",price:20},{name:"kabab",price:250},{name:"coke",price:20},{name:"coke",price:20},{name:"kabab",price:250}];
var accumulator = {};
var results = [];
var index = 0;
var originalDiv = document.getElementById('original');
var resultsDiv = document.getElementById('results');
String.prototype.hashCode = function() {
var hash = 0;
if (this.length == 0) return hash;
for (i = 0; i < this.length; i++) {
var char = this.charCodeAt(i);
hash = ((hash << 5) - hash) + char;
hash |= 0; // Convert to 32bit integer
}
var c = (hash & 0x0FFFFFFF)
.toString(16)
.toUpperCase();
return '0000000'.substring(0, 7 - c.length) + c;
};
arr.forEach(function(obj) {
var id = JSON.stringify(obj).hashCode();
console.log(id);
if (accumulator.hasOwnProperty(id)) {
accumulator[id].count++;
} else {
results.push(obj);
accumulator[id] = results[results.length - 1];
accumulator[id].count = 1;
}
});
printArray(arr, originalDiv);
printArray(results, resultsDiv);
function printArray(objects, div) {
var count = 0;
if (typeof objects != "undefined" && objects != null && objects.length > 0) {
objects.forEach(function(obj) {
var newElement = document.createElement('p');
newElement.innerHTML = 'item ' + count + ': ';
Object.keys(obj).forEach(function(key) {
newElement.innerHTML += key + ': ' + obj[key] + ', ';
});
newElement.innerHTML = newElement.innerHTML.slice(0, -2);
div.appendChild(newElement);
count++;
});
}
}
<div id="original">
<p>Original Array</p>
</div>
<div id="results">
<p>Results Array</p>
</div>
I need to sort list strings under the table ,so for that i have written following lines of code but on console i am not getting any values:
var j = 9;
var rows = element.all(by.repeater('row in renderedRows'));
var column = element.all(by.repeater('col in renderedColumns'));
expect(rows.count()).toEqual(5); //here its printing number of rows
expect(column.count()).toEqual(5); //here its printing number of columns
var arr = [rows.count()];
for (var i = 0; i < rows.count(); i++) {
console.log("aai" + i);
if (i = 0) {
//var columnvalue=column.get(9).getText();
var columnvalue = column.get(9).getText().then(function(ss) {
return ss.trim();
arr[i] = ss.trim(); //here it will save the value first value of column
console.log("value1" + arr[i]);
expect(arr[i]).toEqual('DN');
console.log("aa" + ss.trim());
});
} else {
var j = j + 8;
var columnvalue = column.get(j).getText().then(function(ss) {
return ss.trim();
arr[i] = ss.trim(); //here it will save the other values of column
console.log("value" + arr[i]);
expect(arr[i]).toEqual('DN');
console.log("ab" + ss.trim());
});
}
}
Sorting_Under_Table: function(col){
test = [];
var m;
var dm = 0;
element(by.xpath('//div[#class="ngHeaderScroller"]/div['+col+']')).click();
element.all(by.repeater('row in renderedRows')).then(function(row) {
m = row.length;
for (i = 1; i <= row.length; i++)
{
user_admin_table_name = browser.driver.findElement(by.xpath('//div[#class="ngCanvas"]/div['+i+']/div['+col+']'));
user_admin_table_name.getText().then(function(text) {
var test_var1 = text.toLowerCase().trim();
test.push(test_var1);
var k = test.length
if (k == m){
for (j = 0; j < test.length; j++){
test.sort();
d=j+1;
user_admin_table_name1 = browser.driver.findElement(by.xpath('//div[#class="ngCanvas"]/div['+d+']/div['+col+']'));
user_admin_table_name1.getText().then(function(text1) {
var test_var2 = text1.toLowerCase().trim();
if (test_var2 == test[dm]){
expect(test_var2).toEqual(test[dm]);
dm = dm +1;
}else {
expect(test_var2).toEqual(test[dm]);
log.error("Sorting is not successful");
dm = dm +1;
}
});
}
}
});
}
});
},
You can use this code for sorting and verifying is it sorted or not
I'm not sure how your above example is doing any sorting, but here's a general solution for trimming and then sorting:
var elementsWithTextToSort = element.all(by.xyz...);
elementsWithTextToSort.map(function(elem) {
return elem.getText().then(function(text) {
return text.trim();
});
}).then(function(trimmedTexts) {
return trimmedTexts.sort();
}).then(function(sortedTrimmedTexts) {
//do something with the sorted trimmed texts
});