Local storage not working issues with for loop - javascript

I am using local storage to allow the user to return to a form after it has been submitted and amend with previous values persisting.
I succeeded in using the jQuery Storage Api (for set() and get()) but only by writing out long hand for each form element, not ideal. Instead I wanted to push all the form element ids to an array and loop through the array. First part, pushing to the array, works like a charm but the for loop I used is not working.
I intend to use jQuery .each() function but want to understand why my loop is not working first. Thanks.
(function() {
var selectArray = [];
// Getting select ids
$("select").each(function() {
selectArray.push($(this).attr("id"));
});
// Using Local Storage Api
var storage = $.localStorage;
for (var i = 0; i < selectArray.length; i++){
// Get select element
$("#" + selectArray[i]).val(storage.get(selectArray[i]));
// Set select element
$("#" + selectArray[i]).change(function() {
var selectValue = $("#" + selectArray[i]).val();
storage.set(selectArray[i], selectValue);
});
// Check loop is working
console.log(i + ". " + selectArray[i]);
}
}());
Resources:
jQuery v1.11.0
jQuery Storage API

Just change the change event handler like this, avoid reference to i. variable i is getting dangled here.
$("#" + selectArray[i]).change(function() {
var selectValue = $(this).val();
storage.set($(this).attr('id'), selectValue);
});
This should work.
Example

You are right, inside the change handler function you refer to the loop variable 'i'. When the change handler is actually called, 'i' is dereferenced and always contains the last value: selectArray.length

Related

Binding to lines in flowchart.js

I'm using flowchart.js to create diagrams. I want to be able to bind a click event to each arrow on the diagram to perform some action to that unique path.
As far as I can see in the inspector, these lines don't have IDs... Is there a way to get around this?
I verified what you wrote and you're correct, the lines (svg paths) don't have IDs. Also, it looks like they don't have much of a programming API. So I came up with a hacky way of assigning IDs for each path.
After you make your call to diagram.drawSVG(...); add the following code create unique IDs for each path.
var i = 0;
$("path").each(function() {
$(this).attr("id", "path" + i.toString());
i++;
});
I then added a click handler to the path elements to verify the IDs were properly assigned.
$(document).on("click", "path", function () {
//Display to the console
var clickedPath = $(this)[0];
console.log(clickedPath);
// Build a string of attributes by looping them
var alertString="";
for (i=0; i < clickedPath.attributes.length; i++) {
alertString += clickedPath.attributes[i].name + "=" + clickedPath.attributes[i].value + "\n";
}
//Alert the attributes
alert(alertString);
});
You can view the results at https://codepen.io/anon/pen/EoqPQG?editors=0010

keeping localStorage objects that iterate whilst using clear() within the same function

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]);
}
}

How to save to local storage

So I have made a table table elements and functions for the pop up and the form. Appending element on clicking save button also works. However I can't make it work the content to be stored and pulled from local storage in refresh page. I am somehow trying to populate the cell with currently generated ID . Considering the fact that I me new at JavaScript I am totally missing something Can someone give me idea what is that. The Code
/*save to td */
$('#save').click(function () {
localStorage.setItem(clickID, JSON.stringify(clickID));
var theName = $('input[name=name]').val();
var theLastName = $('input[name=lastname]').val();
$('input[name=name]').val("");
$('input[name=lastname]').val("");
var $fullCell = $('<p>' + theName + '' + theLastName + '</p>');
if((theLastName+theLastName).length > 0){
$(callingID).append($fullCell);
$(callingID).css('background-color', 'yellow');
}
});
https://jsfiddle.net/9zcj3ab8/27/
In javascript keys for an object must be strings. You can think of localStorage as a persistent Javascript object. Since you are calling JSON.stringify on clickID I am assuming clickID is a javascript object.
The first argument to setItem must be a string, followed by any valid js type for the second argument (documentation for setItem here: https://developer.mozilla.org/en-US/docs/Web/API/Storage/setItem)
If clickID is a string:
Additionally, you are saving to localStorage just clickID and a stringified version of clickID. It seems to me that the intended behavior is to store to localStorage a string called clickID as a key (first argument) with the first name and last name as the value (second argument).
Not sure if that is the wrong jsfiddle but your $('#save').click function is nowhere to be found there.

Update the DB value associated with an <input> element when its value changes

I tried to make something like this http://jsfiddle.net/4e756/
$(document).ready(function(){
$('input[type=text]').keyup(function(){
var c=0;
var a=$(this).attr('name'); //a is string
//if var a change..a=a(old)+a(new) and c++; than i will
//explode string and use it for ajax POST
});
});
Every time that var a changes I want to use its value to increment some another variable. This will allow me to save the name of every <input> which changes.
Make the a variable global and add to it.
$(document).ready(function(){
var a=''; // initialize it as global and an empty string
$('input[type=text]').click(function(){
var c=0;
a = a + $(this).attr('name'); //a is string
//if var a change..a=a(old)+a(new) and c++; than i will
//explode string and use it for ajax POST
});
});
jsFiddle Demo
Create a map outside of the scope of your change handler. This handler will be fired only after all changes to the field are complete, not on every keyup. This will allow to you store the name and the updated value of all of the fields which change. You can then POST that to your server, or process it and POST only a subset if that's required.
Because it is a map, keys are unique. This means that if you change a field more than once it will still appear in the map only once, with its latest value.
$(document).ready(function(){
var changedFields = {};
$('input[type=text]').change(function(){
changedFields[this.name] = $(this).val();
});
});

Javascript dropdownlist

How can I get the previous selected index on change event of dropdown list using Javascript.
No, it is not possible, but you can use a variable inside onchange event that tracks the previous selection
Example:
var previousSelected;
function track(d){
if(typeof previousSelected != 'undefined'){
alert("Previous selected value " + previousSelected );
}
previousSelected = d.selectedIndex;
alert("selected value " + d.selectedIndex);
}
Place a meta variable in the ul or ol object that is the index of the last selected item so that when you goto the item again you can just ask for that property again and, presto, you know the index of the last selected item.
A common way of placing a meta variable inside an object is by adding a class to the last item that was selected with javascript and then finding the list item with that class when you want to see which one was selected. I see JQuery users doing this alot (btw you should be using JQuery to help with all of your javascript).
For example, to mark the last item as selected:
$('ul li:last').addClass('selected');
Then to find it again:
$('ul li.selected')
Its actually a pretty easy way of tracking this kind of code.
You could have a javascript global variable which will track this value. So when the change event is trigerred you would have the new value and the old one. Then you would update the global variable with the new value.
Here's an example pseudo code:
var selectedValue = '';
document.getElementById('someId').onchange = function() {
var newValue = this.value;
// TODO: compare with the old value
selectedValue = newValue;
};

Categories