remove and replace item from object in array javascript - javascript

I have read and tried all of the posts of SO on this subject, but for some reason none of the answers are providing the desired effect.
I have written a shopping basket program and once the user clicks the'Buy now' button I wish to make POST request containing an object with the users order.
Problem
The user has the option to purchase three different items. Each time the user clicks on an item, which is a html input box, to increase the amount they wish to purchase I want to update the object to only contain the latest amount chosen.
In its simplest format the basket, when initiated, looks like this :
var basket = {items:[
{item:"Trousers", quantity:1, cost:"10"},
{item:"Trainers", quantity:1, cost:"5"},
{item:"Jacket", quantity:1, cost:"30"}
]}
Each time the user clicks the input button I wish for the basket to be updated so if the user clicked to increase the jacket to a quantity of 3, and the trousers to 4 I want the object to look like this:
var basket = {items:[
{item:"Trousers", quantity:4, cost:"40"},
{item:"Trainers", quantity:1, cost:"5"},
{item:"Jacket", quantity:3, cost:"90"}
]}
Then if a user decides to reduce the number of trousers by 1, to 3, I would want the basket.items object to look like this:
var basket = {items:[
{item:"Trousers", quantity:3, cost:"30"},
{item:"Trainers", quantity:1, cost:"5"},
{item:"Jacket", quantity:3, cost:"90"}
]}
I have written the code for all the calculations etc. so this is not the issue but the issue is to update basket.items to only contain the three items listed above at once, with the latest data.
I cannot use the filter method as this needs to work in older versions of IE. I have tried all solutions listed in this and this along with many more but none of these answers are providing the solution I am looking for.
Let me know if any further information is required.

try this:
var basket = {
items: [
{
item: "Trousers",
quantity: 1,
cost: "10"
}, {
item: "Trainers",
quantity: 1,
cost: "5"
}, {
item: "Jacket",
quantity: 1,
cost: "30"
}]
};
function updateBasket(item) {
basket.items = basket.items.map(function (product) {
if (product.item == item.item) return item;
else return product;
});
}
updateBasket({
item: "Jacket",
quantity: 9,
cost: "30"
});
updateBasket({
item: "Trainers",
quantity: 9,
cost: "30"
});
console.log(basket)

Don't know if for you having an array of objects is mandatory if that's not the case you can structure your data differently, for instance
basket = { items : { item_1 : { quantity: 1, cost: 1 } } }
so updating the basket it will be simply
function updateBasket(item, value) {
// item -> item_1
// value - > { quantity: 2, cost: 2}
basket['items'][item] = value;
}

To be honest, I think the problem could be solved if you kept your data in a little different way. For example, something like this
var products = {
trousers:0,
jackets:0,
trainers:0,
};
var prices = {
trainers:5,
jackets: 30,
trousers: 10
}
//to increase the amount of products after user event
products.jackets +=2;
products.trainers +=3;
products.trousers +=1;
//finally generate your desired format
var basket = {items:[]};
for(product in products){
basket.items.push({
item: product,
quantity: products[product],
cost: products[product]*prices[product]
});
}
console.log(basket);
You can see that basket is now in your desired format :)

Cost should be a number and not string.
If you are not keeping a global object for what is the price of 1 item then once you have updated your basket object you will loose the information on price of 1 item and you wouldn't know how much to increase the price.
Considering same, below would be my recommendation of changes:
var basket = {items:[
{item:"Trousers", quantity:4, itemCost:40, totalCost:40},
{item:"Trainers", quantity:1, itemCost:5, totalCost:5},
{item:"Jacket", quantity:3, itemCost:90, totalCost:90},
]}
function updateQuantity(itemName, qIncreaseBy, qDecreaseBy){
console.log(basket);
for(var propt in basket.items){
if(basket.items[propt].item == itemName){
if(qIncreaseBy != 0){
basket.items[propt].quantity = (basket.items[propt].quantity + 1);
basket.items[propt].totalCost = (basket.items[propt].totalCost + basket.items[propt].itemCost);
} else{
basket.items[propt].quantity = (basket.items[propt].quantity - 1);
basket.items[propt].totalCost = (basket.items[propt].totalCost - basket.items[propt].itemCost);
}
break;
}
}
console.log(basket);
}
Usage:
updateQuantity("Trainers", 0, 1); //To add item
updateQuantity("Trainers", 1, 0) //To remove item

Related

Is there a way to use a lookup list inside a loop in GTM?

I have an add to cart event that sends the cart to the Data Layer. A cart item includes sku, quantity and price. In GTM, I need to transform the sku into a product url and an image url.
I was hoping to use a lookup list, but I'm not sure if this is even possible, what would the input variable be if so? Is my only option to create a javascript function that does this or can I utilize GTM variables somehow?
[{
sku: "SU-LG",
quantity: 1,
price: 100.00},
{
sku: "RS-SM",
quantity: 1,
price: 50.00}]
This is probably best done with a function as the lookup table is going to output a variable on that dataLayer.push, not a variable for each of the skus in an array.
You could use a JSON saved in a GTM variable, then reference the GTM variable in a function:
var array = [
{
sku: "SU-LG",
quantity: 1,
price: 100.00
},
{
sku: "RS-SM",
quantity: 1,
price: 50.00
}
]
var gtmJsonProduct = {
"SU-LG": "su-lg-product.png",
"RS-SM": "rs-sm-product.png"
};
var gtmJsonImage = {
"SU-LG": "su-lg-image.png",
"RS-SM": "rs-sm-image.png"
};
// Set these as a GTM variable instead?
// var gtmJsonProduct = {{gtmJsonProduct}};
// var gtmJsonImage = {{gtmJsonImage}};
for (var i = 0; i < array.length; i++) {
var sku = array[i]['sku'];
var productUrl = gtmJsonProduct[sku];
var imageUrl = gtmJsonImage[sku];
console.log(`product url for ${sku} = ${productUrl}`);
console.log(`image url for ${sku} = ${imageUrl}`);
}
JSFiddle

Return new Object that includes filtered nested array

I basically have a menu system where the user clicks on the store name and it displays information for that store.
That works.
Now, I also have a filter panel where the user can choose to sort the menu list based on the filter button clicked. I can't for the life of me figure this out.
How do I use array functions to create an array that returns a new object that also has updated menus?
burgers.forEach(function(e){
e.menu.filter (el => el.itemPrice < 3).map(el => {
if(el.itemPrice < 3){
console.log(el);
}
});
})
When I log (e) it all burger stores menu item that is less than 5. I want to then create a new object that has all the information from the original but the menu section should be modified to only show the items less than $5.
Object:
let burgers = [
{
"storeSpace": "Open Space",
"storeName": "Mcdonalds",
"menu": [
{
"itemImage": "https://www.mcdonalds.com/is/image/content/dam/ca/nfl/web/nutrition/products/header/en/mcdonalds-hamburger.jpg?$Product_Desktop$",
"itemName": "Hamburger",
"itemPrice": 2.99,
},
{
"itemImage": "https://www.mcdonalds.com/is/image/content/dam/ca/nfl/web/nutrition/products/header/en/mcdonalds-hamburger.jpg?$Product_Desktop$",
"itemName": "Hamburger",
"itemPrice": 3.99,
},
{
"itemImage": "https://www.mcdonalds.com/is/image/content/dam/ca/nfl/web/nutrition/products/header/en/mcdonalds-hamburger.jpg?$Product_Desktop$",
"itemName": "Hamburger",
"itemPrice": 6.99,
},
]
},
]
If I call the object again, it does include the items that are less than $5 but it also shows all the other menu items which i don't want. It should only show the first 2 but it returns the whole list of items.
Here is an image: https://i.imgur.com/jOHkB6a.png
As you see, that time I set the max amount to $3 and only 1 item in the object is under $3 but it returns the whole menu list. That is why I need to somehow update the current menu item.
Here is code:
const newBurgersMenu = burgers.map(function(burger){
const newMenu = burger.menu.filter(function(item){
if(item.itemPrice < 5){
return item
}
})
return newMenu;
})
// First way to create new burgers
const newBurgersObj = [{...burgers[0], menu:newBurgersMenu[0]}]
// OR Second way to create new burgers
const newBurgers = burgers.slice()
newBurgers[0].menu = newBurgersMenu
console.log({newBurgersObj})
console.log({newBurgers})
Is this what you are looking for. Also link to jsfiddle https://jsfiddle.net/vrheL4tw/1/
Hope I answered your question

Return json array if matches input

Need help:
I have my JSON formatted array. What I can't seem to wrap my head around is how to all the contents of said array when it matches user input. I can display the whole array and i can check if the input is in the array.
Code:
//user input
var product = document.getElementById('product').value;
var price = document.getElementById('price').value;
var quantity = document.getElementById('quantity').value;
//Products
var viewInventory = [{
id : 'a',
name : 'iphone',
model : 10,
price : 900,
quantity : 25
}, {
id: 'b',
name : 'pixel',
model : 1,
price : 800,
quantity : 40
},{
id: 'c',
name : 'pants',
model : 8,
price : 700,
quantity : 80
},{
id: 'd',
name : 'essential',
model : 10,
price : 900,
quantity : 25
}];//end of viewInventory
console.log(viewInventory);//just testing to see it JSON obj works
function hello(){
var item;
for (var i = 0; item = viewInventory[i].name; i++){
console.log(item);
// console.log(viewInventory[i].name)
if (product === item){
console.log(viewInventory[i]);
console.log(item + "This is input");
// document.write(myTable);
}
}
Problem:
Below is the problem from my book ( i am self learning).
Pulling data from a file into a complex data structure makes parsing much simpler. Many programming languages support the JSON format, a popular way of representing data.
Create a program that takes a product name as input and retrieves the current price and quantity for that product.The product data is in a data file in the JSON format and looks like this:
{
_"products" : [
_{"name": "Widget", "price" : 25.00, "quantity": 5 },
__{"name": "Thing", "price": 15.00, "quantity": 5},
__{"name": "Doodad", "price": 5.00, "quantity": 10}
__]
}
Print out the product name, price, and quantity if the product is found. If no product matches the search, state, that no product was found and start over.
Example output
What is the product name? iPad
Sorry, that product was not found in our inventory
What is the product name? Widget
Name: Widget
Price: $25.00
Quantity on hand: 5
Constraints
The file is in the JSON format. Use a JSON parser to pull the values out of the file.
If no record is found, prompt again.
Challenges
Ensure that the product search is case-insensitive.
When a product is not found, ask if the product should be added. If yes, ask for the price and the quantity, and save it in the JSON file. Ensure the newly added product is immediately available for searching without restarting the program.
you can use the Array.prototype.filter function:
var product = document.getElementById('product').value;
var price = document.getElementById('price').value;
var quantity = document.getElementById('quantity').value;
var matchingProducts = viewInventory.filter((v)=>v.name.indexOf(product)>-1);
if(!matchingProducts.length) alert('Sorry, that product was not found in our inventory');
else {
alert(
matchingProducts.reduce(
(c,i)=>c+i.name+' found with price='+i.price+' and the quantity='+i.quantity+'\n',
''
)
);
}

How to find duplicates, count elements in array using javascript/jquery

I have a form in HTML. In this form, I can build catalog preferences.
When I'm done with that I can click on save button and build a next one. The result is saving in an array.
When I have more than one saved catalog(sku=stock keeping unit) in my array it's possible that there are some duplicates. How can I remove the duplicates and count them (The quantity should stay even if there is a duplicate)?
Jsfiddle
Array(Array(
0:5016s18gercol, //sku(stock keeping unit)
1: 100, //quantity
2: 5017ext10002, //extra sku for extra costs(cataloge in color)
3: 1
),
Array(
0:5016s43gerbw, //sku
1: 100, //quantity
2: 5017ext10001,//extra sku for extra costs(catalog own cover)
3: 1 //quanitity extra costs
),
Array(
0: "5016s43gercol" //sku
1: "400" //quantity
2:"5017ext10001" //extra sku (own cover)
3:"1" //quantity sku
4:"5017ext10002" //extra sku (in color)
5:"1" //quantity sku
)
)
This is what i get. It should look like this:
array(5016s18gercol,
500,
5017ext10002,
2,
5017ext10001,
2)
Every sku is unique so i cant have two same sku's. I have to count them if there are more than one.
Use array.prototype.map and array.prototype.some:
var values = [
{ name: 'someName1' },
{ name: 'someName2' },
{ name: 'someName4' },
{ name: 'someName2' }
];
var valueArr = values.map(function(item){ return item.name });
var isDuplicate = valueArr.some(function(item, idx){
return valueArr.indexOf(item) != idx
});
console.log(isDuplicate);

how to increase custom count in jquery json

If laptop model and serial id are same, i've to add new field totalModel and increase count. For example in below case: serialid "1" and laptop model "xyz" are coming two time so i want to add "totalModel" count as 2 and so on. How can i achieve this in jquery
This question is not really about jQuery, it is about mapping and filtering arrays and objects. However, we can use some jQuery convenience methods to solve it.
A large part of solving these problems is by properly defining what you want to do. It sounds from your question that you want to get a map of unique serial ids per laptop model type. We can use JavaScript's Array.prototype.reduce to produce just such a map (Note that we will take the 'sold' value for the first of each laptop model we encounter):
var laptop_models = data.reduce(function (memo, obj) {
if (!memo[obj.laptopModel]) {
memo[obj.laptopModel] = {
unique_serial_ids: [],
sold: obj.sold
};
}
if ($.inArray(obj.serialid, memo[obj.laptopModel].unique_serial_ids) === -1) {
memo[obj.laptopModel].unique_serial_ids.push(obj.serialid);
}
return memo;
}, {});
Next, we can map our laptop_models object into the array you specified as your expected result:
var result = $.map(laptop_models, function (laptop_model, model_name) {
return {
laptopModel: model_name,
totalModel: laptop_model.unique_serial_ids.length,
sold: laptop_model.sold
};
});
You got the idea already. Iterate through the array.
if them item is in a hash, increment the count, otherwise, add to the hash and set the count to 1
var hash = {};
for (var i = 0;i<data.length;i++) {
if (hash[data[i].laptopModel) {
hash[data[i].laptopModel]++;
}
else
hash[data[i].laptopModel] = 1;
}
var data = [
{
"serialid": 1,
"laptopModel": "xyz",
"sold": "yes",
"cnt": 5
},
{
"serialid" :1,
"laptopModel": "xyz",
"sold": "yes",
"cnt": 4
},
{
"serialid": 1,
"laptopModel": "abc",
"sold": "yes",
"cnt": 3
},
{
"serialid": 3,
"laptopModel": "xyz",
"sold": "yes",
"cnt": 2
}];
var result = []; //work if result = {};
var tempArray = []; // used to store unique name to prevent complex loop
data.forEach(function(item){
if($.inArray(item.laptopModel, tempArray)< 0){// unique name
result.push(formatData(item));
tempArray.push(item.laptopModel);
}
else{
var indexNew = $.inArray(item.laptopModel, tempArray);
result[indexNew]["totalModel"] += 1;
}
});
function formatData(item){
return{
"laptopModel": item.laptopModel,
"sold": item.sold,
"totalModel": 1
}
}
alert(JSON.stringify(result)); //expect array 2 item but it's empty array
console.log(result); //Will have result 2 item when I view console window
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Categories

Resources