I am creating a shopping cart where user can add an item to cart. Once user clicked the addtocart button, I want to save the product id, name, price and quantity to local storage and then retrieve them on the cart page. So I tried this
var cart = new Array;
if (cart != []) {
cart = JSON.parse(localStorage["cart"]);
}
$('#addtocart').on('click', function(e) {
var qty = document.getElementById("p-qty").value;
var li = $(this).parent();
var product = {};
product.id = productid;
product.name = document.getElementById("nomenclature").innerHTML;
product.price = document.getElementById("productprice").innerHTML;
product.quantity = qty;
addToCart(product);
});
function addToCart(product) {
// Retrieve the cart object from local storage
if (localStorage) {
var cart = JSON.parse(localStorage['cart']);
cart.push(product);
localStorage.setItem('cart', JSON.stringify(cart));
}
// window.location = "html/cart.html"
}
but I keep getting this error
Uncaught TypeError: cart.push is not a function
What am I doing wrongly and how can I fix it?
You don't check that localStorage['cart'] is defined and don't check that the deserialized variable is an array. I'd suggest doing something like this:
function addToCart(product) {
if (localStorage) {
var cart;
if (!localStorage['cart']) cart = [];
else cart = JSON.parse(localStorage['cart']);
if (!(cart instanceof Array)) cart = [];
cart.push(product);
localStorage.setItem('cart', JSON.stringify(cart));
}
}
Note, however, that if you have a serialized object or other non-array variable in localStorage['cart'], it will be overwritten with this method.
localStorage in HTML5 is Object, you can set item by using .setItem() and get item by .getItem()
Demo get old values, push new value and save values with localStorage
var Values = [];
//get olds values
Values = JSON.parse(localStorage.getItem('Storage'));
//push new value
Values.push(item);
//saved values
localStorage.setItem('Storage', JSON.stringify(Values));
Now with your edit, problem you have here is this makes no sense. First You set the array to be empty, so it will always be empty. Now second issue is [] will never equal new Array so it will always go into the if statement. And since you probably never set localStorage["cart"] with anything, it will be invalid.
var cart = new Array; // <-- you define an array?
if (cart != []) { // <- than you check the array you just created? How would it have a value if this check would actually work?
cart = JSON.parse(localStorage["cart"]);
}
So what you need to do is get rid of that if, since it does nothing. Next you just need to check localstorage if it has a value, if it does not, than set it to an emoty array. So add a conditional that if it is undefined, it uses a new array
Now what your codde should have been was
var cart = []; //define the array
if (localStorage["cart"]) { // Check that it has a value in storage
cart = JSON.parse(localStorage["cart"]); //If yes, parse it
}
or another way could be
var cart = JSON.parse(localStorage['cart'] || '[]');
Related
I wanted to save data in local storage in form of array.
the first item is adding successfully but when i try to ad second item it replace item 1
this is my script file
function store(title, description) {
let titl = JSON.parse(localStorage.getItem("titl"));
let descriptio = JSON.parse(localStorage.getItem("descriptio"));
if (titl == null) {
t = [title];
localStorage.setItem("titl", JSON.stringify(t));
} else {
t = [title]
titl.push(t);
}
if (descriptio == null) {
d = [description];
localStorage.setItem("descriptio", JSON.stringify(d));
} else {
d = [description];
titl.push(d);
}
}
you dont update localstorage for the second values, and your pushing an array with a value onto an array (i think you just want to push a value onto the array)?
I think something like this is what your trying to acheive?
function store(title, description) {
// load the existing values (default to an empty array if not exist)
let _title = JSON.parse(localStorage.getItem("title") || "[]")
let _description = JSON.parse(localStorage.getItem("description") || "[]")
// add the new items
_title.push(title)
_description.push(description)
// update stored values
localStorage.setItem("title", JSON.stringify(_title)
localStorage.setItem("description", JSON.stringify(_description)
}
I'm trying to build 'wishlist' functionality. When you click a button, it saves the name and link for the particular 'property' in an array in local storage. I will then output this on the page for the user.
So far it works, my only problem is that it will always insert the property name and link, even if it's already present in the array. I need to create a check, to see if it's already there, and only push it if it can't be found.
Here's a JSFiddle that works. Click the "save" buttons and check localStorage and you will see that the data is added. But click the same button again and you'll see it's added, again.
https://jsfiddle.net/g9kkx3fh/3/
Here's the basic code. It grabs the property name and link from the closest clicked button, it pulls data back from the array in localStorage, then uses .push to add the new data, then re-stringifys it and adds it back to localStorage.
var name = $(this).closest('.text-long').find('.intro-text h4').text();
var permalink = $(this).closest('.text-long').find('.button-slot a').attr('href');
var property = [name, permalink]; // create an array of the name + permalink
var wishlist = JSON.parse(localStorage.getItem("wishlist")); // get the wishlist from storage
wishlist.push(property); // append the new array into the wishlist from storage
localStorage.setItem('wishlist', JSON.stringify(wishlist)); // put the wishlist back in storage
I knew I needed to iterate over the array, being multi-dimensional, and look for the same name var. So I started with this:
for (var i = 0; i < wishlist.length; i++) {
var isPresent = ($.inArray(name, wishlist[i]));
}
if (isPresent == -1){
wishlist.push(property);
localStorage.setItem('wishlist', JSON.stringify(property));
}
Here's the problem with this. If the localStorage var wishlist is empty, then its length is 0. Therefore the for loop never works, because i < wishlist.length is never true, because wishlist is always 0.
So how do I fix this? I'm never able to add anything to the array, because I can never get the value of isPresent, because my for loop never works.
Here's a JSFiddle for the broken code, but with the for loop and if statement added:
https://jsfiddle.net/bdxa0sgz/1/
I've also tried the following:
if (isPresent == -1 || wishlist.length == 0){
...
}
So that if the wishlist is empty, it'll still run. However this seems to jumble together the name data and overwrite the array. I'm very confused.
https://jsfiddle.net/bdxa0sgz/5/
Before you push the property array to the wishlist array you have to check if wishlist contains it right. So you might simply do it like this. Let's invent a generic Array.prototype.compare() method. However since this is going to be a generic method it also takes care of the possibility of array elements being objects. So we have an Object.prototype.compare() too (in this case we don't need it but it's good to know) So here is the code;
Object.prototype.compare = function(o){
var ok = Object.keys(this);
return typeof o === "object" && ok.length === Object.keys(o).length ? ok.every(k => this[k] === o[k]) : false;
};
Array.prototype.compare = function(a){
return this.every((e,i) => typeof a[i] === "object" ? a[i].compare(e) : a[i] === e);
};
var button1 = ["29 Melton Road32 York Road","http://localhost:8888/test-properties/properties/29-melton-road/"],
button2 = ["32 York Road","http://localhost:8888/test-properties/properties/32-york-road/"],
wishlist = [],
push2wl = btn => wishlist.some(a => a.compare(btn)) ? wishlist : wishlist.concat([btn]); // if exists return wishlist untouched
wishlist = push2wl(button1);
wishlist = push2wl(button2);
wishlist = push2wl(button1); // this won't get inserted
wishlist = push2wl(button2); // this won't get inserted
console.log(wishlist);
I use arrow functions but you may replace them with their conventional counterparts if you want to see your code work on Safari 9 or IE.
Use Map (key, value) pair to store your properties so that you can check using
myMap.get(key)
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/get
Here, have a look at this detailed article: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Map
For your example,
var myMap = new Map();
$('body').on('click', '.icon.heart button', function(e) {
var name = $(this).closest('.text-long').find('.intro-text h4').text();
var permalink = $(this).closest('.text-long').find('.button-slot a').attr('href');
var property = [name, permalink];
console.log(property);
if (myMap.get(name) === null) {
var wishlist = JSON.parse(localStorage.getItem("wishlist"));
console.log('Wishlist from localStorage = ' + wishlist);
wishlist.push(property);
console.log(wishlist);
localStorage.setItem('wishlist', JSON.stringify(wishlist));
myMap.set(name, permalink);
}
});
You can also iterate through the map to get all the properties like this:
var mapIter = myMap[Symbol.iterator]();
console.log(mapIter.next().value);
I hope this works for you.
I'm trying to set objects into localStorage with a format similar to the following:
[{"1":{"property1":false,"property2":false}},{"2":{"property1":false,"property2":false}}]
Where I'd be able to set the 1 or 2 based on a dynamic value I'm getting from a REST call. What I have so far is:
// check if session exists and create if not
var StorageObject = JSON.parse(localStorage.getItem("session")) || [];
//see if the current id from the REST call is in storage and push with properties if not
if ( !StorageObject[thisItemsListID] ) {
var itemProperties = {};
itemProperties[thisItemsListID] = {};
itemProperties[thisItemsListID]["property1"] = false;
itemProperties[thisItemsListID]["property2"] = false;
StorageObject.push(itemProperties);
localStorage.setItem('session', JSON.stringify(StorageObject));
}
I can get the data into localStorage using this format but StorageObject[thisItemsListID] always gets into the if statement and generates a duplicate item in localStorage and I'm not sure how to access this with a variable. I'm trying to append the new ID if it doesn't exist so if {1:{} exists but current ID is 2 I need to push the new value.
I'm close here and maybe I need to reevaluate the format I'm storing the data string but I'm going in circles here and could use a point in the right direction.
Well, the duplicate item is happening in StorageObject.push(itemProperties).
Try this to update the object:
//StorageObject.push(itemProperties); <-- remove
StorageObject[thisItemsListID] = itemProperties;
[EDIT]
If you want to keep [{"1":{"property1":false,"property2":false}},{"2":{"property1":false,"property2":false}}]. To conditional would be a bit different.
var haveItem = StorageObject.filter(function(item){
return Objects.keys(item)[0] == thisItemsListID;
}).length > 0;
if ( !haveItem ) {
var itemProperties = {};
itemProperties[thisItemsListID] = {};
itemProperties[thisItemsListID]["property1"] = false;
itemProperties[thisItemsListID]["property2"] = false;
StorageObject.push(itemProperties);
localStorage.setItem('session', JSON.stringify(StorageObject));
}
Are you trying to update the object or just overwrite it? Filipes response illustrates how to update the entire storage object by just reassigning the object with the new value.
If you wanted to update just as section/ value of the object you could do so using a for loop. This would allow you to scan the array locate the one property and then remove it, updated it, overwrite it etc.
Here is an example of the loop. Bear in mind This is a snippet from a report library I was building. It uses angular $scope but it is a complex type doing a similar action to your update (here I am setting a label as a favorite/bookmark)
function OnFavoriteComplete(response) {
var id = response.config.data.reportId; //dynamic values set by client
var isFavorite = response.config.data.isFavorite;//dynamic values set by client
var arrayCount = $scope.reportList.length;
//loop my current collection and look for the property id of the label
//then check to see if true or false/this was a toggle enable disable
if (isFavorite) {
for (var i = 0, iLen = arrayCount; i < iLen; i++) {
if ($scope.reportList[i].reportId == id) {
$scope.reportList[i].isFavorite = false;
}
}
}
//if false update the property with the new value
else {
for (var i = 0, iLen = arrayCount; i < iLen; i++) {
if ($scope.reportList[i].reportId == id) {
$scope.reportList[i].isFavorite = true;
}
}
}
};
If you are using another framework like lowDash it has some really nice helper functions for updating and evaluating arrays.
I am trying to create an array of objects that contain two pieces of information relating to an order:
Product Stock Code
Product Quantity
Currently I am doing it like this:
$(".orderBtn").click(function(event){
//Show the order Box
$(".order-alert").show();
event.preventDefault();
//Create the Array
var productArray = [];
//Get reference to the product clicked
var stockCode = $(this).closest('li').find('.stock_code').html();
//Get reference to the quantity selected
var quantity = $(this).closest('li').find('.order_amount').val();
var key = "stockCode";
var obj = {
'stockCode' : stockCode,
'quantity' : quantity
};
productArray.push(obj);
$.cookie('order_cookie', JSON.stringify(productArray), { expires: 1, path: '/' });
console.log(productArray);
if(quantity == 0){
console.log("Quantity must be greater than 0")
}
I would expect that each time the order button is clicked that the new object would be added to the array of existing objects but instead It just outputs the array with 1 object, the object I've just added.
Is there something I am missing?
Move your array declaration outside of the function into the global scope.
What happens in your case is that each time you call the function a new array is created(function scope) and therefore only one result is produced.
Read this about scopes\hoistings.
var productArray = [];
$(".orderBtn").click(function(event){
//Show the order Box
$(".order-alert").show();
event.preventDefault();
//Create the Array
//Get reference to the product clicked
var stockCode = $(this).closest('li').find('.stock_code').html();
//Get reference to the quantity selected
var quantity = $(this).closest('li').find('.order_amount').val();
var key = "stockCode";
var obj = {
'stockCode' : stockCode,
'quantity' : quantity
};
productArray.push(obj);
$.cookie('order_cookie', JSON.stringify(productArray), { expires: 1, path: '/' });
console.log(productArray);
if(quantity == 0){
console.log("Quantity must be greater than 0")
}
declare as global variable
var productArray = [];
$(".orderBtn").click(function(event){
// do here
//productArray.push("anyObject");
});
You are recreating / overwriting the productArray every time the button is clicked. Try moving the var productArray = [] to outside of the click handler
Not so, because your
var productArray = [];
is within the function that sets the cookie, so it's getting defined afresh then having one element added each time the function is called.
You'd need to define productArray outside of the function (as a global variable?) so that it retains its previous value, and new objects are added to it
With var productArray = []; you're declaring a new array on every click. Move that line outside the click handler and the code should start working.
I am creating a web page where the user can add an item into a dropbox buy clicking a button. The sessionstorage store the partnum and quantity of the item. The dropbox will display the details (quantity would be 1)of the item selected. How do I update the quantity to 2 if the same item is selected?
$("#btnBuy0").click(function()
{
$("#dropbox").append('<span><img class = "thumb" src="../images/21_metoyou.jpg" />' + teddy[0].desc + ", Price £"
+ teddy[0].price + ", Quantity: " + quantity + "</span><br/>");
if (Modernizr.sessionstorage)
{ // check if the browser supports sessionStorage
myids.push(teddy[0].partnum + quantity); // add the current username to the myids array
sessionStorage["ids"]=JSON.stringify(myids); // convert it to a string and put into sessionStorage
}
else
{
// use cookies instead of sessionStorage
}
for (var item =0; item<sessionStroage.length; item++)
{
var key = sessionStorage.key(teddy[0].partum);
if (teddy[0].partnum == teddy[item].partnum)
{
var q = sesstionStorage.getItem(quantity, quantity++);
}
I would suggest you make use of a differnt data structure for storing the user's basket. Instead of using an Array (myids), you could make use of an Associative Array (by using a JavaScript object) to map the partnum against a quantity, eg:
// Basket is initially empty.
basket = {};
function saveOrder(teddy, quantity) {
var partnum = teddy[0].partnum;
// Create a mapping between the partnum and the quantity
basket[partnum] = quantity;
// Write the basket to sessionStorage.
sessionStorage.basket = JSON.stringify(basket);
}
Using a map would allow you to create helper methods to read and write the basket object from SessionStorage, eg:
function fetchBasketFromSession() {
return JSON.parse(sessionStorage.basket);
}
function writeBasketToSession(basket) {
sessionStorage.basket = JSON.stringify(basket)
}
function getPartNumOf(teddy) {
return teddy[0].partnum;
}
function getQuantityInSessionBasketOf(teddy) {
// Fetch the basket from sessionStorage
var sessionBasket = fetchBasketFromSession(),
partnum = getPartNumOf(teddy);
// Return the quantity mapped to the partnum in the basket, or 0 if nothing
// is mapped.
return sessionBasket[partnum] || 0;
}
// Combining these functions would allow you to update the users basket.
function addToBasket(teddy, quantityToAdd) {
var sessionBasket = fetchBasketFromSession(),
currentQuantity = getQuantityInSessionBasketOf(teddy),
partnum = getPartNumOf(teddy);
// Update the quantity for this partnum and write it back out.
sessionBasket[partnum] = currentQuantity + quantityToAdd;
writeBasketToSession(sessionBasket);
}
Hope that helps :)