localStorage resets on Chrome after getItem, setItem - javascript

I am trying to save data in localStorage with jQuery. The data I am trying to save resets every time I refresh my Chrome browser. First, I retrieve the data from a dictionary through getItem, then I set it using setItem. Sounds pretty simple, but I can't get it to save. Any help is appreciated. Thanks
Here's my js:
moneylove = {"snacks":{"c":1,"m":1,"e":2},"food":{"c":2,"m":0,"e":1},"soap":{"c":2,"m":0,"e":0},"toys":{"c":2,"m":1,"e":2}} //dog state
for (state in moneylove["snacks"]){
stateadd = JSON.parse(localStorage.getItem(state))
stateadd += moneylove["snacks"][state]
localStorage.setItem(state,JSON.stringify(stateadd))
}
console.log(localStorage)

You replace the keys because the each sub-object has same properties so that it replaces anyway. Change to be like this.
var moneylove = {"snacks":{"c":1,"m":1,"e":2},"food":{"c":2,"m":0,"e":1},"soap":{"c":2,"m":0,"e":0},"toys":{"c":2,"m":1,"e":2}} //dog state
for (state in moneylove["snacks"]){
stateadd = JSON.parse(localStorage.getItem(state))
stateadd += moneylove["snacks"][state]
localStorage.setItem("snacks" + state,JSON.stringify(stateadd)) // Make key be unique.
}
console.log(localStorage)
EDIT
The complete calculation and storage method as following example. This can calculate the states in each object in moneylove.
var moneylove = {"snacks":{"c":1,"m":1,"e":2},"food":{"c":2,"m":0,"e":1},"soap":{"c":2,"m":0,"e":0},"toys":{"c":2,"m":1,"e":2}} //dog state
for(var itemKey in moneylove) {
var item = moneylove[itemKey];
for (var stateKey in item){
var storageKey = itemKey + "-" + stateKey;
var stateadd = JSON.parse(localStorage.getItem(storageKey) || '0')
stateadd += item[stateKey];
localStorage.setItem(storageKey, JSON.stringify(stateadd)) // Make key be unique.
}
}
console.log(localStorage)

Try this!
var DB = function(){
this.Read = function(index){
return JSON.parse(localStorage[index]).data;
};
this.Write = function(index, data){
localStorage[index] = JSON.stringify({data : data});
};
this.Test = function(){ // test support localStorage!
return typeof localStorage == typeof {};
};
this.Clear = function(index){
if(typeof index === "undefined"){
localStorage = {};
} else {
localStorage[index] = JSON.stringify({data : []});
}
};
}
// example:
var x = new DB(); // new data base
if(!x.Test()) alert('Error!'); // not support!
x.Write('food', ['food','bar','google']); // write data
console.log(x.Read('food')); // get data!
x.Clear('food'); // clear data!
console.log(x.Read('food')); // get data!

Related

Why i have to get item from local storage before even storing it?

Why in this code I am getting an item from local storage first even before storing it
let addnote = document.getElementById("addbtn");
addnote.addEventListener("click", saveNote );
let message = document.getElementById("notes2");
function saveNote() {
let TXT = document.getElementById("addtxt");
let note = localStorage.getItem("notes");
console.log("save");
if(note == 0){
noteData2 = [];
}
else{
noteData2 = JSON.parse(note);
}
noteData.push(TXT.value);
localStorage.setItem("notes", JSON.stringify(noteData));
TXT.value = "";
};
Thanks
If you don't, then the second time you called saveNote you would overwrite the previous note instead of storing an array with two notes in it.

JavaScript - Issues recovering a map in an object after being saved in localStorage

I've been dealing with this for some time. I've a list of sections in which the user checks some checkboxes and that is sent to the server via AJAX. However, since the user can return to previous sections, I'm using some objects of mine to store some things the user has done (if he/she already finished working in that section, which checkboxes checked, etc). I'm doing this to not overload the database and only send new requests to store information if the user effectively changes a previous checkbox, not if he just starts clicking "Save" randomly. I'm using objects to see the sections of the page, and storing the previous state of the checkboxes in a Map. Here's my "supervisor":
function Supervisor(id) {
this.id = id;
this.verif = null;
this.selections = new Map();
var children = $("#ContentPlaceHolder1_checkboxes_div_" + id).children().length;
for (var i = 0; i < children; i++) {
if (i % 2 == 0) {
var checkbox = $("#ContentPlaceHolder1_checkboxes_div_" + id).children()[i];
var idCheck = checkbox.id.split("_")[2];
this.selections.set(idCheck, false);
}
}
console.log("Length " + this.selections.size);
this.change = false;
}
The console.log gives me the expected output, so I assume my Map is created and initialized correctly. Since the session of the user can expire before he finishes his work, or he can close his browser by accident, I'm storing this object using local storage, so I can change the page accordingly to what he has done should anything happen. Here are my functions:
function setObj(id, supervisor) {
localStorage.setItem(id, JSON.stringify(supervisor));
}
function getObj(key) {
var supervisor = JSON.parse(localStorage.getItem(key));
return supervisor;
}
So, I'm trying to add to the record whenever an user clicks in a checkbox. And this is where the problem happens. Here's the function:
function checkboxClicked(idCbx) {
var idSection = $("#ContentPlaceHolder1_hdnActualField").val();
var supervisor = getObj(idSection);
console.log(typeof (supervisor)); //Returns object, everythings fine
console.log(typeof (supervisor.change)); //Returns boolean
supervisor.change = true;
var idCheck = idCbx.split("_")[2]; //I just want a part of the name
console.log(typeof(supervisor.selections)); //Prints object
console.log("Length " + supervisor.selections.size); //Undefined!
supervisor.selections.set(idCheck, true); //Error! Note: The true is just for testing purposes
setObj(idSection, supervisor);
}
What am I doing wrong? Thanks!
Please look at this example, I removed the jquery id discovery for clarity. You'll need to adapt this to meet your needs but it should get you mostly there.
const mapToJSON = (map) => [...map];
const mapFromJSON = (json) => new Map(json);
function Supervisor(id) {
this.id = id;
this.verif = null;
this.selections = new Map();
this.change = false;
this.selections.set('blah', 'hello');
}
Supervisor.from = function (data) {
const id = data.id;
const supervisor = new Supervisor(id);
supervisor.verif = data.verif;
supervisor.selections = new Map(data.selections);
return supervisor;
};
Supervisor.prototype.toJSON = function() {
return {
id: this.id,
verif: this.verif,
selections: mapToJSON(this.selections)
}
}
const expected = new Supervisor(1);
console.log(expected);
const json = JSON.stringify(expected);
const actual = Supervisor.from(JSON.parse(json));
console.log(actual);
If you cant use the spread operation in 'mapToJSON' you could loop and push.
const mapToJSON = (map) => {
const result = [];
for (let entry of map.entries()) {
result.push(entry);
}
return result;
}
Really the only thing id change is have the constructor do less, just accept values, assign with minimal fiddling, and have a factory query the dom and populate the constructor with values. Maybe something like fromDOM() or something. This will make Supervisor more flexible and easier to test.
function Supervisor(options) {
this.id = options.id;
this.verif = null;
this.selections = options.selections || new Map();
this.change = false;
}
Supervisor.fromDOM = function(id) {
const selections = new Map();
const children = $("#ContentPlaceHolder1_checkboxes_div_" + id).children();
for (var i = 0; i < children.length; i++) {
if (i % 2 == 0) {
var checkbox = children[i];
var idCheck = checkbox.id.split("_")[2];
selections.set(idCheck, false);
}
}
return new Supervisor({ id: id, selections: selections });
};
console.log(Supervisor.fromDOM(2));
You can keep going and have another method that tries to parse a Supervisor from localStorageand default to the dom based factory if the localStorage one returns null.

localStorage .parse .stringify

I need help with pushing 2 data values into localStorage. I know a little about the stringify and parse methods but cant grasp how to implement them.The 2 data values are from "Scores" and "saveName"(a username that is put into an input box).
var Score = (answeredCorrect * 20) + (timeleft);
var saveName = document.querySelector("#saveName");
function Storage() {
localStorage.setItem("User", JSON.stringify(saveName.value));
localStorage.setItem("Scores", JSON.stringify(Score));
var GetStorage = localStorage.getItem("User");
var GetStorage2 = localStorage.getItem("Scores");
return {
first:console.log("GetStorage: "+ GetStorage + GetStorage2),
second:GetStorage,
third:GetStorage2,
};
};
var values = Storage();
var first = values.first;
var second = values.second;
var third = values.third;
As mentioned in the comments you need to parse it once retrieved from storage with JSON.parse, also naming Storage should be avoided.
Since your making a wrapper for localstorage, it could be done like this:
const Store = {
set: (key, value) => localStorage[key] = JSON.stringify(value),
get: key => JSON.parse(localStorage[key])
}
Then you can simply call it like the following, with a set and get methods:
//
Store.set('Score', Score)
Score = Store.get('Score')
//
Store.set('User', saveName.value)
saveName = Store.get('User')
Though you only need to get() on page load as you already have the value in Score/saveName etc.

Can't update javaScript global variable

Here I have global variable userId, and i want to update it inside signInUserFunction(), to use is in other function. I have tried to define it using var, window, But all these didn't help. This variable doesn't update. As i see its about AJAX async. So, what can i do with it?
And yes, I know that its not good to make authentication with JS, I am quite new to it. So, I am just creating random methods to improve.
var userId = 1;
function signInUser() {
$.getJSON('http://localhost:8887/JAXRSService/webresources/generic/getAllUsers', function(data) {
var items = [];
var i = 0;
$.each(data, function(firstname, value) {
var str = JSON.stringify(value);
data = JSON.parse(str);
var innerId;
for (p in data) {
innerId = data[p].id;
if ($('#nameSignIn').val() == data[p].first_name && $('#passwordSignIn').val() == data[p].password) { //
userId = innerId;
window.location.href = "content.html";
break;
} else {
i++;
if (i == data.length) {
alert("Ощибка в логине или пароле!")
}
}
}
});
});
}
How are you determining whether or not it has been set? It looks like immediately after you set it, you navigate to a different page. When you get to that page, you will have an entirely new window.
Try alerting the value before navigating away.
EDITED: Here is how you could pass it to the other page (but you shouldn't do this in a real app)
window.userId=innerId;
alert(window.userId);
//this isn't a very secure way to do this. I DON'T recommend this
window.location.href = "content.html?id=" + innerId ;
Then in the other page, you could access it off the document.location:
alert(document.location.toString().split("?id=")[1]);
After reading my comments, you may want to try this:
var userId = 1;
function signInUser(){
$.getJSON('http://localhost:8887/JAXRSService/webresources/generic/getAllUsers', function(data){
var items = [], actors = data.Actors, l = 0;
$.each(actors, function(i, o){
l++;
if($('#nameSignIn').val() === o.first_name && $('#passwordSignIn').val() === o.password){
userId = o.id;
// this will redirect before any other code runs -> location = 'content.html';
if(l === actors.length){
alert('End of Loop');
}
}
});
});
}
signInUser();
I would not store sensitive data in JSON such as passwords. Use a database. There is no need to get all the data at the same time either.
Using the idea #mcgraphix proposed (and giving you the same warning...this would certainly not be the way to transfer data like this in a production environment), here is one way to do it:
function signInUser() {
var url = 'http://localhost:8887/JAXRSService/webresources/generic/getAllUsers';
var userId;
$.getJSON(url, function(data) {
$.each(data.Actors, function(index, actor) {
// Cache the values of the #nameSignIn and #passwordSignIn elements
var name = $('#nameSignIn').val();
var password = $('#passwordSignIn').val();
if (actor.first_name === name && actor.password === password) {
// We have found the correct actor.
// Extract its ID and assign it to userId.
userId = actor.id;
window.location.href = "content.html?userId=" + userId;
}
});
// This alert should only be reached if none of the actor objects
// has a name and password that matches your input box values.
alert("Ощибка в логине или пароле!");
});
}
// On the next page...
// Top answer from http://stackoverflow.com/questions/2090551/parse-query-string-in-javascript
// This approach can handle URLs with more than one query parameter,
// which you may potentially add in the future.
function getQueryVariable(variable) {
var query = window.location.search.substring(1);
var vars = query.split('&');
for (var i = 0; i < vars.length; i++) {
var pair = vars[i].split('=');
if (decodeURIComponent(pair[0]) == variable) {
return decodeURIComponent(pair[1]);
}
}
console.log('Query variable %s not found', variable);
}
var userId = getQueryVariable('userId');
Thanks you for help.Ended it all with usage of:
sessionStorage.getItem('label')
sessionStorage.setItem('label', 'value')

How to convert values of an array into recursive field names of another variable in Javascript

I need to convert values from one Array variable into fields of another variable in Javascript.
My variable is
field = ["entries", "body"]
and it needs to become something like
req.body.entries.body
I tried doing something like
field.forEach(function(prop){
req.body[prop] = "...";
}
but that works only on req.body.entries and req.body.body. And I need it to go all the way to req.body.entries.body
I'm doing this to get the data from a form in a document field (named entries[body]), do some cleaning up on that data, and then pass it back to node.js as if it was the request that was originally made.
UPDATE
All I need to do is to basically
exports.sanitize = function(field){
// field = ["entry","body"];
return function(req, res, next){
val = getField(req, field); // val = "Some string with data"
val = some_process(val); // some_process is a function that cleans up the string
req.body.entry.body = val; // HOW TO TAKE entry.body from the field array???
next();
}
};
As you can see, all I want is to NOT hard code entry.body but take it from field array values that passes the name of the field for processing.
If you can think of a more elegant solution to do this, please, let me know.
Thanks!
This works:
var fields = [ "field1", "field2", "field3", "field4" ];
var obj = req.body;
fields.forEach(function(prop) {
obj[prop] = {};
obj = obj[prop];
});
You want
var obj = req.body;
for (var i=0; i<fields.length-1; i++)
obj = obj[fields[i]];
var prop = fields[i];
obj[prop] = cleanUp(obj[prop]);
This will work only if req.body.entries.body is already defined:
field = ["entries","body"];
var toeval="req.body";
field.forEach(function(prop){
toeval+="."+prop;
});
toeval+="=\"...\"";
eval(toeval);
I was able to accomplish this using recursion. Hope this helps!
var foo = {
bar: {}
};
var fields = ['foobar', 'barfoo'];
function setVar (currentVar, arr, counter) {
if (arr[counter] === undefined) {
return;
}
currentVar[arr[counter]] = {};
setVar(currentVar[arr[counter]], arr, counter + 1);
}
setVar(foo.bar, fields, 0);

Categories

Resources