I made some kind a game using HTML, CSS, JS, AJAX AND PHP.
However, in order to save the user's best score, I used localStorage (for the first time).
For some reason, even though the best score is being displayed in the "best score" box while the user
is still playing (as I wanted), it's being removed when you refresh the page, and turns into 0 again (which
I defined as the default value).
Can someone please point at the problem for me?
Here is the specific part of the code:
$(".pi_tab .best_result #score").html(localStorage.record);
$("#pi_input").keyup(function() { // On pressing a digit
var num = parseInt($("#counter").html()); // Convert counter's value to integer
if (!isNaN(num)) // If it's a legal number
{
if (num + 1 > localStorage.record) // If it's the score is a new record
{
localStorage.record = num + 1; // Update record
$(".pi_tab .best_result #score").html(localStorage.record); // Show record as "Best Score"
}
}
});
Try to use this code pattern from w3schools: http://www.w3schools.com/html/html5_webstorage.asp
Use setItem and getItem to set/get the data, in my opinion your code is creating another property on localStorage object called record which more likely same as other javascript variable
Try to use the property setItem :
localStorage.setItem("key", "value");
UPDATE
Note: Name/value pairs are always stored as strings. Remember to convert them to another format when needed!
Source : W3Schools
You execute :
if (num + 1 > localStorage.getItem("record")) // If it's the score is a new record
{
localStorage.setItem("record",num + 1);
...
}
Maybe it's your problem.
Replace by :
var record = num + 1;
var localRecord = localStorage.getItem("record");
if (record > parseInt(localRecord)) // If it's the score is a new record
{
localStorage.setItem("record", record);
...
}
Related
I have a code where i am able to add, display and delete objects in local storage and its working but whenever i try to update a particular object, it instead overrides everything instead of just changing the particular one i want
MY CODE
$(".qty-val-ls").on("change", function() {
let record = localStorage.getItem("guestCart");
let index = $(this).attr("id");
if(record == null)
{
recordObj = [];
}else{
recordObj = JSON.parse(record);
}
recordObj[index].price = $(this).val() * parseInt(recordObj[index].price);
localStorage.setItem('guestCart', recordObj[index].price);
})
MY INPUT
<input type="number" class="qty-val-ls" min="1" id="${index}" value="4000" onChange="">
The ${index} here is the id that is in the localstorage and the index in the jquery is the number where the object is like at in the localstorage, it starts from 0, 1, 2 etc
MY ARRAY(OBJECT IN LOCALSTORAGE)
[{"id":"11","name":"Rts 512GB USB Flash Drive Pendrive Memory USB 3.0","price":"3000","img":"newusb.png","qty":1},
{"id":"10","name":"MP3 Music Player Audio Player -Black","price":"5000","img":"mp3.png","qty":1},
{"id":"5","name":"Blue Louis Vuitton Women Bag","price":"10000","img":"newbag.png","qty":1},
{"id":"1","name":"Samsung Galaxy S9 6gb ram, 32gb rom, 16mpbs","price":"100000","img":"newphone.png","qty":1}]
So please how do i change the value after calculating and be able to put it back to where its supposed to be
EDIT: I have checked other similar questions on stackoverflow but none seems to work
I'll try to explain what was also said in the comments and give a good approach. First of all, you were overriding the stored object in localStorage with recordObj[index].price instead of the full recordObj. But, as you stated, storing recordObj and then getting its value gives "[object Object]" because it is parsed to string. Taking into account what I said about being careful when accessing to an items property because it could not exist yet, this code should work for you:
$('.qty-val-ls').on('change', function onChange() {
const record = localStorage.getItem('guestCart');
const recordObj = record ? JSON.parse(record) : [];
const index = $(this).attr('id');
if (recordObj[index]) {
recordObj[index].price = $(this).val() * parseInt(recordObj[index].price, 10);
}
localStorage.setItem('guestCart', JSON.stringify(recordObj));
});
Explaining what I did in more detail:
Get the localStorage item.
Parse it with JSON.parse if exists because it is stringified; if it doesn't exist, initialize it as an empty array.
If exists an item at the given index, set the price as you wanted. I also added the radix parameter to parseInt as it is a good practice and I'm used to follow that ESLint rule (https://eslint.org/docs/rules/radix)
Finally, store the modified (or not) and stringified array.
I'm trying to create a javascript/HTML game where points can be saved over multiple visits to the site, and the save function is working just fine, but when I turn that into a points variable on the load up of the page, the += operator will not work. Instead of using addition to update the variable, it will just add the number to the end of the variable's value. an example of this would be if you said 100 += 1 so that it would make sense for the output to be 101, but instead, it will be 1001.
I have figured out that it is, in fact, the local storage. If just set the points that I'm trying to display to 0 instead of a past score achieved it works fine. This error could possibly be occurring because I am using free web hosting with repl.it so I am sharing a domain with a lot of other sites. I thought about testing if it would work better with cookies but I have never used cookies so I thought I would check here first before trying to learn them.
var points = 0;
points += localStorage.points;
// The below is tied to a save button
function saveData() {
localStorage.points = points;
}
/*This is also tied to a button with an amount of one, and this is
where errors occur. */
function addPoints(amount) {
points += amount;
}
sorry if it's sloppy, I'm kind of new to both javascript and game development. Also, I did, in fact, have a checker to see if local storage was available.
localStorage always stores values as strings. Excerpt from mozilla:
The keys and the values are always strings (note that, as with objects, integer keys will be automatically converted to strings).
You need to first cast points to a number.
var points = 0;
points += +localStorage.points; // + casts it to a number
All data stored in localStorage is a string (or undefined).
So, instead of doing addition, the += operator will do string concatenation.
Try this: points += +localStorage.points or points += Number(localStorage.points)
You also have to make sure the initial value is not undefined.
The full solution would be:
var points = 0;
if (localStorage.getItem('points') !== null) {
// ^^ Similar to localStorage.points !== undefined
points += +localStorage.points; // Now points won't be type-casted to string
}
function saveData() {
localStorage.points = points;
}
/*This is also tied to a button with an amount of one, and this is
where errors occur. */
function addPoints(amount) {
points += amount;
}
To understand why that happens run this example:
const p = 0;
const s = '1';
const n = 1;
console.log(`p + s = ${p + s}, ${typeof(p+s)} | p + n = ${p + n}, ${typeof(p+n)} | p + +s = ${p + +s}, ${typeof(p + +s)}`);
I have an uncertain amount of modals in my page, all determined by an specific ID. What I'm doing is checking how many times a modal gets open, and then, by using a counter, I reach a certain limit.
This limit is taken from a JSON file and then compared with the amount of times the modal has been opened.
But here's the catch. I need to save this data (the one concerning the openings) into LocalStorage, so everytime I close my browser the data remains.
As you can see, I have a "testObject" variable created in LocalStorage, this one's equal to the alertCounter. Then I compare it to my ShowingLimit variable (extracted from the JSON file) and that shows me an alert.
The question's simple. How do I keep the data from rebooting?
var alertCounter = 0;
$("#" + modalName + "").on("shown.bs.modal", function(e){
alertCounter++;
localStorage.testObject = alertCounter;
if(localStorage.testObject == showingLimit){
alert("We've reached the limit");
});
}
})
You should try something like this:
if(localStorage.testObject){ //Is there any testObject?
if(+localStorage.testObject >= showingLimit )//is equal to the limit
{
alert("We've reached the limit");//or whatever
}
else{
+localStorage.testObject++; //+ 1
}
}else{
localStorage.testObject = 1; //first time
}
Note that the + is to cast as integer, because is stored as string.
What I'm trying to do is to contact WooCommerce every fifth seconds to check if a product have been edited. I can do that by asking for res[0].date_modified. Then I compare the time it was created (res[0].date_created) and last modified.
If the values are the same the product have never been modified. However if the product get modified I no longer want to compare the time the product was created and last modifed.
I now want to compare the time with the last time it got modified with "res[0].date_modified" so I can see if it gets modified another time.
This is what I have come up with:
function lookForEdit(){
WooCommerce.get('products/', function(err, WooData, res) {
res=JSON.parse(res)
var comp = res[0].date_created;
if(comp == res[0].date_modified){
console.log("the product haven't been modified")
}
else{
console.log("The product have been edited")
comp = res[0].date_modified;
}
})
}
setInterval(lookForEdit, 5000);
I understand why it doesn't work, but I don't know how to fix it.
How can I fix it?
Thanks
Using a global variable to store the last value would be enough, just check if it is defined first, if not take the date_create value.
Of course, you can check date_modifed only if it is not defined for a unmodifed item.
In that case, you just need to check if date_modifed value is defined, if it is, compare with comp (still global). Then if there are different store the new value.
PS: Sorry, I can't write a code since I didn't write javascript in a will. I end up in that question by mistake ^^
This would be a pseudocode of it
global comp;
function(){
if(comp not defined)
comp = date_created
if(comp != date_modified)
//changed
comp = date_modified;
}
Well, right off the bat, you are setting comp = res[0].date_created and then, if they are equal you are setting comp = res[0].date_modified but then the very next time you call the api, you are overwriting comp with the date created again. You should be using 2 separate variables to track the information. You should use 2 separate more descriptive names for the values you are trying to monitor.
Since your code runs every 5 seconds, I suppose you could check that the last modification happened less than 5 seconds ago :
if(comp == res[0].date_modified){
console.log("the product hasn't been modified")
}
else if (new Date(Date.now().getTime() - 5000) < res[0].date_modified) {
console.log("the product hasn't been modified since the last check");
}
else{
console.log("The product has been edited")
comp = res[0].date_modified;
}
I'm trying to clear all local storage when the user either completes the game loop or starts a new game, but also keep some values.
I can do this already with my sound values for volume:
// inside a conditional statement that fires when the user chooses to start a new game.
if (newGameBool === '1') {
var tst = myAu;
//myAu is the stored value that the user sets as sound using a range type input
localStorage.clear();
localStorage.setItem("Au", tst);//A newly cleared localStorage just got a new value, and it's the same as it was before.
UI.myLoad();//reload the function that uses LS to do things.
}
How do I do this for key's that have an iterating number attached to them?
Here is how I save them:
var i = +v + +1;
localStorage.setItem("v", i);
var vv = localStorage.getItem("v");
localStorage.setItem("LdrBrd_" + vv, JSON.stringify(LdrBrd));//saves all data with the iterating key name.
Calling them the way i did the sound function:
var gv = v + 1;//v calls the value from LS and adjusted for off-by-one error. gv is a local variable.
if (newGameBool === '1') {
var ldd, vg;
for (var ii = 0; ii < gv; ii++) {
var ld = localStorage.getItem("LdrBrd_" + ii);
if (ld != null) {
//these are the values that i want to pass beyond the clear point
ldd = JSON.parse(ld);//JSON string of data saved
vg = ii;//how many of them.
}
}
localStorage.clear();
for (var xx = 0; xx < vg; xx++) {
var nld = localStorage.getItem("LdrBrd_" + xx);
if (nld != null) {
localStorage.setItem("LdrBrd_" + ii, JSON.stringify(ldd));
}
}
localStorage.setItem("v", vg);
UI.myLoad();
}
I have been using console.log() in various spots to see what is going on. I comment-out the clear function just to see if the values were wrong and they don't save all all. I tried to make a fiddle, but the local storage wasn't working at all there. In visual studio, it works fine but the script to this file is almost 2000 lines long, so i tried to dress it up the best i knew how.
Thanks in advance for any help or guidance.
I was stuck on this for a few days, but i think i found something that will work, so i'll answer my own question in case there is value in posterity.
locatStorage.clear();
/* ^LS clear() function is above all new setItem codes, some variables are declared globally and some are declared at the top of the functional scope or as param^ */
var itemClass = document.querySelectorAll(".itemClass");//the strings are here
if (itemClass) {//make sure some exist
for (var p = 0; p < itemClass.length; p++) {//count them
mdd = JSON.parse(itemClass[p].innerText);//parse the data for saving
localStorage.setItem("v", v);//this is the LS item that saves the amount of items i have, it's declared at the top of the functions timeline.
localStorage.setItem("LdrBrd_" + p, JSON.stringify(mdd));//this setItem function will repeat and increment with 'p' and assign the right string back to the key name it had before.
}
}
The key is to keep the strings physically attached to an element, then call the class name. The i ran a loop counting them. 'mdd' will spit back each item i want. So then all that is left to do is re-set the item back to it's original status.
This has allowed me to create a way for my users to collect trophies and keep them even after clearing the localStorage when the he/she decides to start a new game.
I use CSS to hide the text from the string.
color:transparent;
In my gameLoop, i have a function that will read the saved strings and show them as cards just below the hidden strings.
Since you want to keep some values I recommend one of two things:
Don't call localStorage.clear() and instead only wipe out the values that you want using localStorage.removeItem('itemName'). Since you said the item names have a numeric component, maybe you can do this in a loop to reduce code.
Pull item(s) that you want saved first and restore them after calling clear(). This option is best if there are way more items that you want removed rather than saved (see below)
function mostlyClear() {
var saveMe = {};
saveMe['value1'] = localStorage.getItem('value1');
saveMe['anotherValue'] = localStorage.getItem('anotherValue');
localStorage.clear();
for(var prop in saveMe) {
if(!saveMe.hasOwnProperty(prop)) continue;
localStorage.setItem(prop, saveMe[prop]);
}
}