Local storage saving multiples of the same items - javascript

I'm quite new to using storage settings in HTML/JavaScript. I'm building a hybrid app which is a not taking app on mobile using Phonegap. I want the user to type in a note name, then the note itself, and be able to save both by placing them into a jquery mobile list and putting them back on the home screen. My problem is that I can only save one note at a time. If I try to save another one, it just overwrites the previous one. How would I go about fixing it? Also, when I try refresh the browser the note disappears. Is this normal?
Please and thank you.
Here is the saving function I used:
function storeData() {
var i;
for (i=0; i<999; i++) {
var fname = document.getElementById('fname').value;
var wtf = document.getElementById('wtf').value;
localStorage.setItem('fname', fname);
localStorage.setItem('wtf', wtf);
}
var newEl = "<li><a href='#' id='savedNote'onclick='loadData'></a></li>"
document.getElementById("savedNote").innerHTML = localStorage.getItem("fname");
//try to create a new list element in main menu for this item being stored in
// and add an onclick load function for that
};
function loadData() {
var x;
for (x=0; x<999; x++) {
document.getElementById("fname").innerHTML = localStorage.getItem('fname', fnamei);
document.getElementById("wtf").innerHTML = localStorage.getItem('wtf', wtfi);
}
};

I'm not sure why you're using a loop for your functions. The storeData function looks 999 times for the value of #fname and #wtf, and save this 999x times in localStorage.fname and localStorage.wtf
This makes absolut no sense. Same Problem with your loadData function.
A nice way to save more then one string to the localStorage, is to create a javascript object, stringify it and then save it to the localStorage.
You only need to load the data from the localStorage, if you (re)load the page. But you need to save it to the localStorage, every time something changed, to be sure that the data in the localStorage is always up to date.
For display and manipulation on the page, you use the javascript object. in my example "myData". If you change something, you update your javascript object and then save it to the localStorage.
a side note. to be sure that the user don't overwrite something with a
identical name, you should use unique ids. like i did with the timestamp.
var postID = new Date().getTime();
Here a little example to show you a possible way. It's hard to code something functionally without your html code.
// Creating a object for all Data
var myData = {};
// Fill the Object with data if there is something at the LocalStorage
if (localStorage.myData){
loadDataFromLocalStorage();
}
function createNewPost(){
// Create a ID for the Post
var postID = new Date().getTime();
// Create a Object inside the main object, for the new Post
myData[postID] = {};
// Fill the Object with the data
myData[postID].fname = document.getElementById('fname').value;
myData[postID].wtf = document.getElementById('wtf').value;
// Save it to the LocalStorage
saveDataToLocalStorage();
// Display the Listitem. with the right postID
}
function loadPost (postID){
var singlePost = myData[postID];
// Display it
}
// A Helper Function that turns the myData Object into a String and save it to the Localstorage
function saveDataToLocalStorage(){
localStorage.myData = JSON.stringify(myData);
}
// A Helper Function that turns the string from the LocalStorage into a javascript object
function loadDataFromLocalStorage(){
myData = JSON.parse(localStorage.myData);
}

// Creating a object for all Data
var myData = {};
// Fill the Object with data if there is something at the LocalStorage
if (localStorage.myData){
loadDataFromLocalStorage();
}
function createNewPost(){
// Create a ID for the Post
var postID = new Date().getTime();
// Create a Object inside the main object, for the new Post
myData[postID] = {};
// Fill the Object with the data
myData[postID].fname = document.getElementById('fname').value;
myData[postID].wtf = document.getElementById('wtf').value;
// Save it to the LocalStorage
saveDataToLocalStorage();
// Display the Listitem. with the right postID
}
function loadPost (postID){
var singlePost = myData[postID];
// Display it
}
// A Helper Function that turns the myData Object into a String and save it to the Localstorage
function saveDataToLocalStorage(){
localStorage.myData = JSON.stringify(myData);
}
// A Helper Function that turns the string from the LocalStorage into a javascript object
function loadDataFromLocalStorage(){
myData = JSON.parse(localStorage.myData);
}

Store an array.
var arrayX = [];
arrayX.push(valueY);
localStorage.setItem('localSaveArray', arrayX);

Related

Show the element saved in localStorage when reload the page

I'm learning js.
I want to show the saved li with localStorage created with appendChild when I reload the page.
<ul id="gfg">
<li>Computer Network</li>
<li>Data Structures</li>
</ul>
<button onclick="test()">Submit</button>
function test() {
var node = document.createElement('li');
node.textContent = 'Hi';
abc = document.getElementById('gfg').appendChild(node);
//localStorage
localStorage.setItem('abc', 'abc');
let a = localStorage.getItem('abc');
console.log(abc);
}
We can use a pair of functions to work with your items in the storage:
function getStorageItems() {
var data = localStorage.getItem('items');
return data ? JSON.parse(data) : null;
}
function saveStorageItem(text) {
var array = getStorageItems() || [];
array.push(text);
localStorage.setItem('items', JSON.stringify(array));
}
With this functions you can save and load an array of text (the text of each li). In the storage, we save a text, this functions also convert/parse your array to a JSON text.
We can create another function to add one li item to your page:
function addItem(text, save) {
var node = document.createElement('li');
node.textContent = text;
document.getElementById('gfg').appendChild(node);
if (save !== false)
saveStorageItem(text);
}
By default, we save in the storage the text. Only if we pass save=false, we omit the save action. In this form, we can add and save an item and also only add (without saving).
Your test function, in this form, add and save the item:
function test() {
addItem("Hi");
}
And a last function to load items from storage:
function loadFromStorage() {
var array = getStorageItems();
if (array) {
for (var i = 0; i < array.length; i++)
addItem(array[i], false);
}
}
Here we use false in addItem because only want add the item, not saving again. You can invoke loadFromStorage to load your saved items.
NOTE: here I only save the text because is the only data required to create your HTML. If you need more data, I suggest you use an object and save/load this serialized object in the same way or the HTML.

Table contents disappear on refresh

I'm trying to make a money tracker but every time I refresh they disappear. Anyone know how I can use local storage to make them stay? I've tried using local storage but I can't wrap my head around it and it is very confusing for me. Code Pen - https://codepen.io/jordandevelops/pen/wvPWzxL
const table = document.getElementById('contentTable'),
inputText = document.getElementById('inputText'),
inputPrice = document.getElementById('inputPrice'),
inputDate = document.getElementById('inputDate'),
form = document.getElementById('form');
form.addEventListener('submit', (e) => {
e.preventDefault();
addNewItem();
});
function addNewItem(){
if(inputPrice.value == ''){
alert('Error, please enter price of purchase.');
return;
}
if(inputDate.value == ''){
alert('Error, please enter date of purchase.');
return;
}
let newTr = document.createElement('tr');
let newTd1 = document.createElement('td');
let newTd2 = document.createElement('td');
let newTd3 = document.createElement('td');
table.appendChild(newTr);
newTr.appendChild(newTd1);
newTr.appendChild(newTd2);
newTr.appendChild(newTd3);
newTr.classList.add('createdTr')
newTd1.classList.add('tdName');
newTd2.classList.add('tdPrice');
newTd3.classList.add('tdDate');
newTd1.innerText = inputText.value;
newTd2.innerText = `$${inputPrice.value}`;
newTd3.innerText = inputDate.value;
}
In local storage, you store the data structure in JSON format (not the HTML that contains the data).
To store data:
function addNewItem(){
//... check and validate the input like you do
// grab the current local storage or create an empty container
let theData = localStorage.get('theData') || "[]";
theData = JSON.parse(theData); // get it into object format
//add to it
theData.push({text: inputText.value, price: inputPrice.value, date: inputDate.value});
// store that back into local storage as a string
localStorage.set('theData', JSON.stringify(theData));
//... continue on with your code
To retrieve the data, do it on page load
document.addEventListener('DOMContentLoaded', () => {
let theData = localStorage.get('theData') || "[]";
JSON.parse(theData).forEach(d => {
// ... this is where you take the existing local storage list and populate it into your HTML.
// You can leverage your existing addNewItem function but you'll need to update it to allow for sending input directly into it.
})
Local storage can work ok, but I'd recommend using IndexedDB if you want to store data like this.
IndexedDB is even more complicated than local storage in some ways, but there's a great library called "Dexie" that makes it a lot easier. You can see it here: https://dexie.org/
Using Dexie, you can save, restore and query your data. It will take a little time to experiment with and learn how to do, but it will be a great tool to have in your toolbox.

LocalStorage data appearing in console but not in the DOM

I am currently building a to-do list app and I have already saved the data using the localStorage API.
The desired data, however, appears in the console whenever I console.log it but it still doesn't save in the DOM.
I also added the getItem() function and logged it into the console and I can still view it in the console, find here:
getItem content in the console
But it just doesn't store in the browser
Seeing this, it is in your inclination that it should have stored in the DOM and the content still remains after reloading but that just isn't the case here.
This function below adds a new item to the list, it also deletes and crosses out completed items too:
let id = 0;
function addTaskFunc() {
const aTask = `
<div class="task" id="task-${id}">
<button class="done__btn">
<i class="far fa-check-square"></i>
</button>
<p>${box.value}</p>
<button class="priority">Make priority</button>
<button class="cancel__btn">
<i class="far fa-times-circle"></i>
</button>
</div>
`;
const x = box.value;
if (x) {
taskList.insertAdjacentHTML('afterbegin', aTask);
box.value = '';
;
let cid = id;
const cancelBtn = document.querySelector(`#task-${id} .cancel__btn`);
cancelBtn.addEventListener('click', () => {
deleteItem(cid);
});
let cid2 = id;
// code for marking out an item as done
let cid3 = id;
// code for appending an item to the top of DOM
let cid4 = id;
persistData(cid4);
readData(cid4);
id++;
}
}
newTask.addEventListener('click', addTaskFunc); // Button to activate the function
persistData = id => {
const el = document.querySelector(`#task-${id}`);
localStorage.setItem('addedTasks222', el.innerHTML);
};
readData = id => {
const el = document.querySelector(`#task-${id}`);
const saved = localStorage.getItem('addedTasks222');
if (saved) el.innerHTML = saved;
console.log(el.innerHTML); // This line of code appears in the console
}
I also tried doing it this way inside of the addTaskFunc:
const r = document.querySelector(`#task-${id} .task`);
r.addEventListener('load', () => {
persistData(cid4);
readData(cid4);
});
When I try it with the method above I get the error code in the console:
Cannot read property of addEventListener of null.
I feel there is something wrong somewhere but I just cannot seem to find out where I am missing it.
One last thing, the localStorage only seems to store only one item into the key. Do I need a loop to sort that out?
you can store an array in the local storage like this
localStorage.setItem('array', JSON.stringify(YOURARRAY))
and then you can load that with
var restoredArray = JSON.parse(localStorage.getItem('array'));
sorry for the time..
So I was looking in to your code, and appears that you have some problems..
1- The first one I saw, was in the persistData() function. Accidentally you are just selecting one task to store with document.querySelector(.task);
to select all you need to use document.querySelectorAll(.task), this will return you an array. Because of that you only store one task.
2- Secondly is that you are trying to store html. with .innerHtml, and the innerHtml of your (".class") is buttons and etc.. You should store values.
3- At the end, when you are trying to print the data, you do document.querySelector(.task), and as you can see its returning you undefined, that's because you haven't a .task div yet.
So How you can appropriately make your app work.
1- The first thing you need to do is creating an array variable up on your js file.
let tasks = [];
2-That array will be used to store the values of your tasks with something like this
function addItem(){
let value = item.value; //you need to define the item some way
tasks.push(value);
print() //a function to print the values;
persistData() // store the array
}
3-To print the tasks
function print(){
tasks.forEach(task => {
let div = document.createElement("div");
div.innerHTML = `copy your html task to here, use ${task} to print the task value`
})
}
4-Store the tasks
function persistData(){
localStorage.setItem('addedTasks', tasks); //store the array
};
function readData(){
if (typeof(Storage) !== "undefined") { //check if the browser has localStorage
tasks = localStorage.getItem('addedTasks'); //update your array
print();
} else {
//No Web Storage message
}
};
5- Just run readData() when you load your document with
document.addEventListener("DOMContentLoaded", function(event) {
readData();
});
I hope that I can help

How do I submit an array from the client to a server (ExpressJs) using AJAX?

I'm working on a web application in which a user can drag and drop div elements, whose content is generated from a database, into their preferred order. I want the user to be able to, when they are finished arranging the divs, submit their list (in order) to the server and store the new order in a table. I'm using AJAX to do this, however I'm not sure if that is necessary/the proper way to do this, since I don't need to asynchronously update the page (I just need to submit the data). I've tried a variety of methods to get my array to the server in a usable format (it needs to be iterable and allow for element locations to be compared). I have tried using JSON.stringify/parse, creating a custom object, simply submitting the array on its own, and so on. Here is my code, the most relevant bits are towards the bottom by the makeRouteArray function. Ideally to accomplish this I would like to use just JavaScript (no jQuery). Finally, please excuse my messy code, I'm learning.
// get two groups of elements, those that are draggable and those that are drop targets
let draggable = document.querySelectorAll('[draggable]');
let targets = document.querySelectorAll('[data-drop-target]');
// div immediately surrounding bus routes
var busList = document.getElementById("bus-list");
const button = document.getElementById("button");
// store the id of the draggable element when drag starts
function handleDragStart(e) {
e.dataTransfer.setData("text", this.id); // sets 'text' value to equal the id of this
this.classList.add("drag-start"); // class for styling the element being dragged, sets opacity
}
function handleDragEnd(e) {
e.target.classList.remove('drag-start');
}
function handleDragEnterLeave(e) {
// should provide visual feedback to user?
}
// handles dragover event (moving your source div over the target div element)
// If drop event occurs, the function retrieves the draggable element’s id from the DataTransfer object
function handleOverDrop(e) {
e.preventDefault();
var draggedId = e.dataTransfer.getData("text"); // retrieves drag data (DOMString) for specified type
var draggedEl = document.getElementById(draggedId);
draggedEl.parentNode.insertBefore(draggedEl, this); // inserts element being dragged into list
var draggedArray = Array.from(draggedEl.parentNode.children); // creates new array which updates current location of each route
e.target.classList.remove('drag-start'); // sets opacity back to 1
// if (e.type === "drop") {
// // when dropped, update localstorage
savePage(draggedArray);
// }
}
// get each full bus-route div in #bus-list with p content as single arr item each
// called when item is dropped
function savePage(dArray) {
// honestly i can't remember what this does precisely
// but i can't seem to add to localstorage in the way i want without it
var arr = Array.prototype.map.call(dArray, function(elem) {
return elem.outerHTML;
});
localStorage.newList = JSON.stringify(arr); // have to stringify the array in order to add it to localstorage
}
// ideally it should just update the order of the bus routes to reflect local storage
// and add classes/ids to the divs etc. (hence using outerHTML)
function makePage() {
// getting the item from localstorage
var getData = localStorage.getItem("newList");
// parsing it back into an array
var parsedData = JSON.parse(getData);
// string to hold contents of array so they can be display via innerHTML
var fullList = "";
if (localStorage.getItem("newList") === null) {
return; // maybe this is wrong but if there's nothing in local storage, don't do anything
} else {
for (let i = 0; i < parsedData.length; i++) {
fullList = fullList + parsedData[i];
}
busList.innerHTML = fullList;
// reassigning targets after calling function in order to re-register event handlers
draggable = document.querySelectorAll('[draggable]');
targets = document.querySelectorAll('[data-drop-target]');
}
}
// probably better way to do this
for (let i = 0; i < draggable.length; i++) {
draggable[i].addEventListener("dragstart", handleDragStart);
draggable[i].addEventListener("dragend", handleDragEnd);
}
// drop target elements
for (let i = 0; i < targets.length; i++) {
targets[i].addEventListener("dragover", handleOverDrop);
targets[i].addEventListener("drop", handleOverDrop);
targets[i].addEventListener("dragenter", handleDragEnterLeave);
targets[i].addEventListener("dragleave", handleDragEnterLeave);
}
// rolling average: new_average_score = old_average_score * (total_users-1)/total_users + user_route_rank/total_users
// user id, column per route (score)
// session id
// submit button to save changes to db
// when submit is clicked
// get current results from either local storage or from currently ordered + displayed list
// data will be in array format
// do i need AJAX to be able to submit something other than form data to a server?
// is submitting data in this format (taken from page's HTML ordering) even possible?
// i'd prefer to not use jQuery
// how do i submit an array to the server (express) and then parse (?) it to make it useable?
// so far i have tried JSON.stringify/parse, making a custom object, just submitting array, etc.
// ultimately what i need is a data type that i can loop over and compare positions of stored elements
var makeRouteArray = function() {
var currentOrderArr = Array.from(busList.children);
var idData = currentOrderArr.map(function(el) {
return Number(el.id.slice(2));
});
return idData; // not sure if having two return statements like this is okay
};
button.addEventListener("click", function(e) {
var request = new XMLHttpRequest();
request.open('POST', '/submit', true);
request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
request.send(data);
});
makePage();
The makeRouteArray function is taking ids from an HTML ul and stripping them of the first two characters because I only want to use the numbers (the ids are structured as #r-num). An array of these numbers is what I would like to submit to the server and if possible, once on the server, return the JSON object to an array.
Thanks!

Properly storing an object in chrome.storage?

I'm trying to store an object in my chrome extension containing other objects using chrome.storage - but am having trouble initializing it and properly fetching it using chrome.storage.sync.get. I understand that I'm supposed to get objects in the form of chrome.storage.sync.get(key: "value", function(obj) {} - the issue is I'm not sure how to
Initialize the object the first time with get
Properly update my object with set
I have the following code to create the object and add the data I need.
allData = {};
currentData = {some: "data", goes: "here"};
allData[Object.keys(allData).length] = currentData;
This will correctly give me an object with it's first key (0) set to currentData. (Object: {0: {some: "data", goes: "here"}}) Working as intended, and allData[Object.keys(allData).length] = currentData; will properly push whatever currentData is at the time into my Object later on.
But how do I properly store this permanently in chrome.storage? chrome.storage.sync.get("allData", function(datas) {}) fails to create an empty allData variable, as does allData: {}, allData = {}, and a variety of different things that return either undefined or another error. How do I properly initialize an empty object and store it in chrome.storage? Or am I going about this all wrong and need to break it down into associative arrays in order for it to work?
I essentially need that small block of working code above to be stored permanently with chrome.storage so I can work with it as needed.
You first need to set the data inside the storage:
allData = {};
currentData = {some: "data", goes: "here"};
// to initialize the all data using the storage
chrome.storage.sync.get('allData', function(data) {
// check if data exists.
if (data) {
allData = data;
} else {
allData[Object.keys(allData).length] = currentData;
}
});
// Save it using the Chrome extension storage API.
chrome.storage.sync.set({'allData': allData}, function() {
// Notify that we saved.
message('Settings saved');
});
After that you should be able to access the data using the chrome.storage.sync.get('allData', function(){ ... }) interface.
You can easily do this with the new JavaScript (ECMAScript 6), have a look into Enhanced Object Properties:
var currentData = {some: "data", goes: "here"};
chrome.storage.local.set({allData: currentData });
In the old way, was something like this:
var obj = {};
var key = "auth";
obj[key] += "auth";
obj[key] = JSON.stringify({someKey: someValue});

Categories