I'm trying to use localStorage to save a variable with value generated randomly from an array in a JavaScript file, and pass it to another HTML file. However, the value in Javascript file (Random_Msg) and the value in HTML file (Random_Msg1) are not the same, means it's not saved, instead it generated randomly another value.
These are the code to generate variable and save in localStorage:
function CreateRandomMsg(){
var RandomMsg = Msgs_Arr[Math.floor(Math.random()* Msgs_Arr.length)];
return RandomMsg;
}
var Random_Msg = CreateRandomMsg();
function alertMsg(){
alert(Random_Msg);
}
window.localStorage.setItem("Random_Msg1",Random_Msg);
In my HTML file, I just retrieved the variable first:
var Random_Msg1 = window.localStorage.getItem("Random_Msg1");
And use it in if statement:
if (Random_Msg1 == Msgs_Arr[0] || Random_Msg1 == Msgs_Arr[1]){
value = facesDet.photos[0].tags[0].attributes.glasses.value;
confidence = facesDet.photos[0].tags[0].attributes.glasses.confidence;
} else if (Random_Msg1 == Msgs_Arr[2] || Random_Msg1 == Msgs_Arr[3]) {
value = facesDet.photos[0].tags[0].attributes.smiling.value;
confidence = facesDet.photos[0].tags[0].attributes.smiling.confidence;
};
You can check on pageload if value for necessary key exists in localStorage. If value is missing, then compute and save new value. You can also have an extra event on which you can override value of this key, but this will be a user action.
Note: Stack Overflow does not give access to localStorage and any testing should be done on JSFiddle.
Sample
JSFiddle
function computeRandomValue() {
var data = ["test", "test1", "test2", "test3", "test4"];
var index = Math.floor(Math.random() * 10) % data.length;
return data[index];
}
function setToLocalStorage(newVal) {
var lsKey = "_lsTest";
localStorage.setItem(lsKey, newVal);
}
function getFromLocalStorage() {
var lsKey = "_lsTest";
return localStorage.getItem(lsKey);
}
function initializePage() {
var _val = getFromLocalStorage();
if (!(_val && _val.trim().length > 0)) {
_val = computeAndSaveNewValue();
}
printValue(_val, "lblResult");
}
function computeAndSaveNewValue() {
var newVal = computeRandomValue();
setToLocalStorage(newVal);
printValue(newVal);
return newVal;
}
function printValue(value) {
var id = "lblResult";
document.getElementById(id).innerHTML = value;
}
(function() {
window.onload = initializePage;
})()
<p id="lblResult"></p>
<button onclick="computeAndSaveNewValue()">Save new Value</button>
Related
I have json object with a key named favorite, it has a value of true, when the button is pressed I want to overwrite the value of the favorite key to false and vica versa.
This is what`s inside the json object:
allPlaces: "[{"title":"Test1 ","description":"Test 2","category":"restaurant","favourite":false}]"
function favourite(element) {
var allPlaces = JSON.parse(localStorage.getItem("allPlaces"));
var placeIndex = element.getAttribute("data");
places = {allPlaces}
if (allPlaces["favourite"] == true) {
places.favourite[placeIndex] = false;
element.querySelector('ion-icon').setAttribute('name', 'star-outline');
} else {
console.log("working");
places.favourite[placeIndex] = true;
element.style.color = '#FFE234';
element.querySelector('ion-icon').setAttribute('name', 'star');
}
localStorage.setItem("allPlaces", JSON.stringify(places));
}
allPlaces is an array (in this case it has 1 item) so therefore in order to change the property of an object inside it you have to give it an index like so allPlaces[0].favorite = true
I added some code as a reference
const allPlaces = '[{"title":"Test1 ","description":"Test 2","category":"restaurant","favourite":false}]';
const places = JSON.parse(allPlaces);
places[0].favorite = true;
console.log(places[0]);
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.
Three different web pages have three contenteditable areas each (content1, content2, and content3).
Each page links to one JavaScript which uses local storage to store the user's input and present it again on their return.
When I change the content on one page, it changes the content in the same editable area all three pages.
I want each page to be able to use the same script to save it's own data independently of the other pages.
I've tried adding page location (url) to the local storage key, to get each page to use the same script to store and retrieve it's own data, but I can't get it to work. Am new to JavaScript - would be grateful for any help. Thanks!
window.addEventListener('load', onLoad);
function onLoad() {
checkEdits();
}
// Get page location
var loc = encodeURIComponent(window.location.href);
// Add location to local storage key
function checkEdits() {
if (localStorage.userEdits1 != null) {
var userEdits1 = (loc + userEdits1);
document.getElementById('content1').innerHTML = localStorage.userEdits1;
}
if (localStorage.userEdits2 != null) {
var userEdits2 = (loc + userEdits2);
document.getElementById('content2').innerHTML = localStorage.userEdits2;
}
if (localStorage.userEdits3 != null) {
var userEdits3 = (loc + userEdits3);
document.getElementById('content3').innerHTML = localStorage.userEdits3;
}
};
document.onkeyup = function (e) {
e = e || window.event;
console.log(e.keyCode);
saveEdits();
};
function saveEdits() {
// Get editable elements
var editElem1 = document.getElementById('content1');
var editElem2 = document.getElementById('content2');
var editElem3 = document.getElementById('content3');
// Get edited elements contents
var userVersion1 = editElem1.innerHTML;
var userVersion2 = editElem2.innerHTML;
var userVersion3 = editElem3.innerHTML;
// Add page location to storage key
var userEdits1 = (loc + userEdits1);
var userEdits2 = (loc + userEdits2);
var userEdits3 = (loc + userEdits3);
// Save the content to local storage
localStorage.userEdits1 = userVersion1;
localStorage.userEdits2 = userVersion2;
localStorage.userEdits3 = userVersion3;
};
function clearLocal() {
if (confirm('Are you sure you want to clear your notes on this page?')) {
localStorage.setItem("userEdits1", "");
localStorage.setItem("userEdits2", "");
localStorage.setItem("userEdits3", "");
document.getElementById('content1').innerHTML = "";
document.getElementById('content2').innerHTML = "";
document.getElementById('content3').innerHTML = "";
alert('Notes cleared');
}
}
The actual problem of your script is this:
localStorage.userEdits1
To access the property of an object with a string (e.g. stored in a variable) you have to use the bracket notation:
locationStorage[userEdits1]
But I would propose a slightly more generic (and, imho, cleaner) solution...
Store the content of the editable elements in an object
var cache = {
<elementX id>: <content>,
<elementY id>: <content>,
<elementZ id>: <content>,
...
};
And then store this "cache" in the local storage with a page-specific key
localStorage.setItem(window.location.pathName, JSON.stringify(cache));
A possible implementation could be:
window.addEventListener('load', checkEdits);
getContentEditables().forEach(function(editable) {
// This prevents the function to execute on every keyup event
// Instead it will only be executed 100ms after the last keyup
var debouncedFunc = debounce(100, function(e) {
saveEdits();
});
editable.addEventListener("keyup", debouncedFunc);
});
function checkEdits() {
var cache = localStorage.getItem(window.location.pathName);
if (cache !== null) {
cache = JSON.parse(cache);
Object.keys(cache)
.forEach(function(key) {
var element = document.getElementById(key);
if (element !== null) {
element.innerHTML = cache[key];
}
});
}
}
function saveEdits() {
var cache = {};
getContentEditables().forEach(function(element) {
cache[element.id] = element.innerHTML;
});
localStorage.setItem(window.location.pathName, JSON.stringify(cache));
};
function clearLocal() {
if (confirm('Are you sure you want to clear your notes on this page?')) {
localStorage.removeItem(window.location.pathName);
getContentEditables().forEach(function(element) {
element.innerHTML = "";
});
alert('Notes cleared');
}
}
// helper
function getContentEditables() {
var elements = [];
document.querySelectorAll("[contenteditable]")
.forEach(function(element) {
if (element.id) {
elements.push(element);
}
});
return elements;
}
function debounce(timeout, func) {
var timeoutId;
return function() {
var that = this,
args = arguments;
clearTimeout(timeoutId);
timeoutId = setTimeout(function() {
func.apply(that, args);
}, timeout);
}
}
Use
localStorage[userEdits1]
Instead of
localStorage.userEdits1
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')
I fill my array in the checklistRequest.js and I want to access it in my Termine_1s.html file which contains js code. I can access it but when I want to iterate through it, it gives me only single digits instead of the strings.
How can I solve this?
checklistRequest.js
//Calls the checkbox values
function alertFunction()
{
//Retrieve the object from storage
var retrievedObject = localStorage.getItem('checkboxArray');
console.log('retrievedObject: ', JSON.parse(retrievedObject));
return retrievedObject;
}
Termine_1s.html
//Checks if title was checked already
var checklistRequest = alertFunction();
var titleAccepted = true;
for (var a = 0; a < checklistRequest.length; a++)//Iterates through whole array
{
if(title != checklistRequest[i] && titleAccepted == true)//Stops if false
{
titleAccepted = true;
}
else
{
titleAccepted = false;
}
}
you need to parse the object at some point.
Try:
return JSON.parse(retrievedObject);