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.
Related
I have a button to add a photo to a webpage. The button is currently set up to input a dummy image. I'm trying to get it to allow me to select my own image and then have it save in local storage to stay on the page when it's reloaded. I've tried a few things to get this but I can't. I've been sat looking at the code trying to work it out for ages.
The two tasks are as follows:
When an image entry is added to the DOM, make an image item containing the image data, and store it in local storage.
When the file input element selection changes, use a FileReader object to convert the file to a data URL and add an image entry to the DOM using this data URL.
The add image part of the code is as follows:
function addImageEntry(key, data) {
// Create a image element
var imgElement = new Image();
imgElement.alt = "Photo entry";
imgElement.src = data;
addSection(key, imgElement);
}
function addEntryClick() {
var key = "diary" + Date.now();
var initialText = "";
var isNewEntry = true;
addTextEntry(key, initialText, isNewEntry);
}
function addPhotoClick() {
var inputElement = document.querySelector("#image input");
inputElement.click();
}
function processFile(inputChangeEvent) {
console.log("processFile called with arguments:", {
inputChangeEvent,
});
function addImage(data) {
console.log("addImage called with arguments:", {
data,
});
var key = "diary" + Date.now();
addImageEntry(key, data);
// TODO: Task 1 of 2
// Make an image item using the given data URL
// (demonstrated elsewhere in this file)
// Store the item in local storage using the given key
// (demonstrated elsewhere in this file)
var imageData = data;
var item = makeItem("image", imageData);
localStorage.setItem(key, item);
}
// Add a 'dummy' image entry
addImage(window.DUMMY_DATA_URL);
// TODO: Task 2 of 2
// Complete this function to read a file when it is selected:
// (imgElement and messageElement do not exist in this app so remove that code)
// ...then call addImage using the data URL you obtain
// ...and comment out line above using window.DUMMY_DATA_URL
// Clear the file selection (allows selecting the same file again)
inputChangeEvent.target.value = "";
}
The TODO parts is where I am working and have some comments with them. I think I have task 1 done as when the dummy image is added and the page is refreshed it still appears.
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
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!
I'm in need of some minor assistance. I'm having trouble getting an array (larray3) populated with two other array objects (larray1 and larray2) to pass both from data.js into the subsequent model.js and view.js. Data.js correctly builds the multidimensional array however when the results are received in model.js/view.js I only receive the results for larray1. Because only the first values come thru I cannot tell if both larray1 and larray2 are actually passing thru. Can someone please tell me how I should alter my syntax in either model.js or view.js to access both array values or what else I could change? Thank you in advance.
data.js.
function getCountries(done) {
var sqlite3 = require('sqlite3').verbose();
var file = 'db/locations.sqlite3';
var db = new sqlite3.Database(file);
var larray1 = [];
var larray2 = [];
var larray3 = [];
db.all('SELECT * FROM Country', function(err, rows) {
// This code only gets called when the database returns with a response.
rows.forEach(function(row) {
larray1.push(row.CountryName);
larray2.push(row.CountryCode);
})
larray3.push(larray1);
larray3.push(larray2);
return done(larray3[0], larray3[1]);
});
db.close();
}
model.js
function Countries(done) {
//Pull location values from data
return getCountries(done);
}
view.js
function viewCountries() {
var viewCou = Countries(function(results) {
// Code only gets triggered when Countries() calls return done(...);
var container = document.getElementById('country-select');
var fragment = document.createDocumentFragment();
results.forEach(function(loc, index) {
var opt = document.createElement('option');
opt.innerHTML = loc;
opt.value = loc;
fragment.appendChild(opt);
});
container.appendChild(fragment);
})
}
In data.js you send two arguments to the done callback:
return done(larray3[0], larray3[1]);
This done function is passed through in your model.js:
return getCountries(done);
And that done is passed in from view.js:
Countries(function(results) { // ...
So it is this anonymous function (function(results) {...}) that is called in data.js. But notice that this function only has one parameter, so you're doing nothing with the second argument that data.js sends. result gets the value of larray3[0], but larray3[1] is not captured anywhere.
You could solve this in different ways. Personally, I think the design with two arrays is wrong from the start. I would not separate data that belongs in pairs (name and code) into two different arrays.
Instead make an array of objects, and pass that single array around:
In data.js:
rows.forEach(function(row) {
larray1.push({
name: row.CountryName,
code: row.CountryCode
});
})
return done(larray1);
In view.js:
opt.textContent = loc.name;
opt.value = loc.code;
Side-note: .textContent is preferred over .innerHTML when assigning plain text.
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);