Creating a todo list in javascript only - javascript

I have a problem here.I need to create a todo list with the following specifications:
It should have list,form and local storage components as described below.
The list component's responsibilities are to:
Attach to the list element in the HTML.
Maintain the active todo list in the running web app.
Draw the list of todos.
Redraw the list when a new item is added or removed.
Interact with the storage service to retrieve the list of todo items from the browser's local storage on launch and save the list of todos to the browser's local storage whenever it changes.
The form component's responsibilities are to:
Attach to the list-form element in the HTML.
Draw the form, input, and submit button.
Add the new item to the todo list when the form is submited by interacting with the list component.
Clearing the input after the new todo item has been added allowing for a new item to be entered.
The local storage component's responsibilities are to:
Provide methods that store and retrieve the list of todos in the browser's local storage.
I have tired the following code:
function get_todos() {
var todos = new Array;
var todos_str = localStorage.getItem('todo');
if (todos_str !== null) {
todos = JSON.parse(todos_str);
}
return todos;
}
//local storage
function add() {
var task = document.getElementById('task').value;
var todos = get_todos();
todos.push(task);
localStorage.setItem('todo', JSON.stringify(todos));
show();
return false;
}
function remove() {
var id = this.getAttribute('id');
var todos = get_todos();
todos.splice(id, 1);
localStorage.setItem('todo', JSON.stringify(todos));
show();
return false;
}
//local storage
function show() {
var todos = get_todos();
var html = '<ul>';
for(var i=0; i<todos.length; i++) {
html += '<li>' + todos[i] + '<button class="remove" id="' + i + '">x</button></li>';
};
html += '</ul>';
document.getElementById('k').innerHTML = html;
//document.getElementsByTagName("list");
var buttons = document.getElementsByClassName('remove');
for (var i=0; i < buttons.length; i++) {
buttons[i].addEventListener('click', remove);
};
}
document.getElementById('add').addEventListener('click', add);
show();
Please I need your assistance.

Related

JavaScript - Issues recovering a map in an object after being saved in localStorage

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.

How would I use local storage for a to do list?

I am being asked to have a to do list and save each task (that the user supplies as well as original) through local storage. My teacher did a very simple demo on something completely different and I spent a few hours trying to figure it out. When I looked at the solution, I honestly cannot figure it out. It looks really complicated, and I don't even know where to start. If anyone can give me any hints, that would be awesome!
My code:
let ul = document.querySelector('ul');
let newItem = document.querySelector('input[type=text]');
let checkbox = document.createElement('input');
checkbox.setAttribute('type', 'checkbox');
function output() {
let newTodo = document.createElement('li');
newTodo.innerText = newItem.value;
newTodo.classList.add('todo');
let ulAppend = ul.append(newTodo);
ul.append(newTodo);
let checkboxAppend = newTodo.append(checkbox);
newTodo.append(checkbox);
newItem.value = '';
}
let button = document.querySelector('.btn');
button.addEventListener('click', output);
ul.addEventListener('click', function(e) {
if (e.target.tagName === 'LI') {
e.target.remove();
} else if (e.target.tagName === 'INPUT') {
e.target.parentElement.classList.toggle('finished');
}
});
My teacher's code/local storage solution:
const todoForm = document.getElementById("newTodoForm");
const todoList = document.getElementById("todoList");
// retrieve from localStorage
const savedTodos = JSON.parse(localStorage.getItem("todos")) || [];
for (let i = 0; i < savedTodos.length; i++) {
let newTodo = document.createElement("li");
newTodo.innerText = savedTodos[i].task;
newTodo.isCompleted = savedTodos[i].isCompleted ? true : false;
if (newTodo.isCompleted) {
newTodo.style.textDecoration = "line-through";
}
todoList.appendChild(newTodo);
}
todoForm.addEventListener("submit", function(event) {
event.preventDefault();
let newTodo = document.createElement("li");
let taskValue = document.getElementById("task").value;
newTodo.innerText = taskValue;
newTodo.isCompleted = false;
todoForm.reset();
todoList.appendChild(newTodo);
// save to localStorage
savedTodos.push({ task: newTodo.innerText, isCompleted: false });
localStorage.setItem("todos", JSON.stringify(savedTodos));
});
todoList.addEventListener("click", function(event) {
let clickedListItem = event.target;
if (!clickedListItem.isCompleted) {
clickedListItem.style.textDecoration = "line-through";
clickedListItem.isCompleted = true;
} else {
clickedListItem.style.textDecoration = "none";
clickedListItem.isCompleted = false;
}
// breaks for duplicates - another option is to have dynamic IDs
for (let i = 0; i < savedTodos.length; i++) {
if (savedTodos[i].task === clickedListItem.innerText) {
savedTodos[i].isCompleted = clickedListItem.isCompleted;
localStorage.setItem("todos", JSON.stringify(savedTodos));
}
}
});
Even though my code is more simpler (at least from what I can tell), it works exactly as his code does.
Local storage saves a JSON object to the user's computer. You should create an array of todos, append that array with every new todo, then set that item to local storage.
let ul = document.querySelector('ul');
const savedTodos = JSON.parse(localStorage.getItem("todos")) || []; // Retrieves local storage todo OR creates empty array if none exist
let newItem = document.querySelector('input[type=text]');
let checkbox = document.createElement('input');
checkbox.setAttribute('type', 'checkbox');
function output() {
let newTodo = document.createElement('li');
newTodo.innerText = newItem.value;
newTodo.classList.add('todo');
ul.append(newTodo);
newTodo.append(checkbox);
savedTodos.push({task: newItem.value, isCompleted: false}); // Appends the new todo to array
localStorage.setItem("todos", JSON.stringify(savedTodos)); //Converts object to string and stores in local storage
newItem.value = '';
}
I've annotated the solution you posted with some comments to help you step through it.
// Retrieve elements and store them in variables
const todoForm = document.getElementById("newTodoForm");
const todoList = document.getElementById("todoList");
// Get data stored in localStorage under the key "todos".
// The data type will be a string (local storage can only store strings).
// JSON is a global object that contains methods for working with data represented as strings.
// The `||` syntax is an OR operator and is used here to set an empty array as a fallback in case `localStorage` is empty
const savedTodos = JSON.parse(localStorage.getItem("todos")) || [];
// Create a loop the same length as the list of todos
for (let i = 0; i < savedTodos.length; i++) {
// Create an <li> element in memory (does not appear in the document yet)
let newTodo = document.createElement("li");
// Set the inner text of that new li with the contents from local storage.
// The savedTodos[i] is accessing data in the localStorage array.
// The [i] is a different number each loop.
// The `.task` is accessing 'task' property on the object in the array.
newTodo.innerText = savedTodos[i].task;
// Create a new property on the element called `isCompleted` and assign a boolean value.
// This is only accessible in code and will not show up when appending to the DOM.
newTodo.isCompleted = savedTodos[i].isCompleted ? true : false;
// Check the value we just set.
if (newTodo.isCompleted) {
// Create a style for the element if it is done (strike it out)
newTodo.style.textDecoration = "line-through";
}
// Actually append the new element to the document (this will make it visible)
todoList.appendChild(newTodo);
}
// `addEventListener` is a function that registers some actions to take when an event occurs.
// The following tells the browser - whenever a form is submitted, run this function.
todoForm.addEventListener("submit", function(event) {
// Don't try to send the form data to a server. Stops page reloading.
event.preventDefault();
// Create a <li> element in memory (not yet visible in the document)
let newTodo = document.createElement("li");
// Find element in the document (probably a input element?) and access the text value.
let taskValue = document.getElementById("task").value;
// Set the text of the <li>
newTodo.innerText = taskValue;
// Set a property on the <li> call `isCompleted`
newTodo.isCompleted = false;
// Empty out all the input fields in the form
todoForm.reset();
// Make the new <li> visible in the document by attaching it to the list
todoList.appendChild(newTodo);
// `push` adds a new element to the `savedTodos` array. In this case, an object with 2 properties.
savedTodos.push({ task: newTodo.innerText, isCompleted: false });
// Overwrite the `todos` key in local storage with the updated array.
// Use the JSON global object to turn an array into a string version of the data
// eg [1,2,3] becomes "[1,2,3]"
localStorage.setItem("todos", JSON.stringify(savedTodos));
});
// This tells the browser - whenever the todoList is clicked, run this function.
// The browser will call the your function with an object that has data about the event.
todoList.addEventListener("click", function(event) {
// the `target` of the event is the element that was clicked.
let clickedListItem = event.target;
// If that element has a property called `isCompleted` set to true
if (!clickedListItem.isCompleted) {
// update the styles and toggle the `isCompleted` property.
clickedListItem.style.textDecoration = "line-through";
clickedListItem.isCompleted = true;
} else {
clickedListItem.style.textDecoration = "none";
clickedListItem.isCompleted = false;
}
// The code above changes the documents version of the data (the elements themselves)
// This loop ensures that the array of todos data is kept in sync with the document
// Loop over the array
for (let i = 0; i < savedTodos.length; i++) {
// if the item in the array has the same text as the item just clicked...
if (savedTodos[i].task === clickedListItem.innerText) {
// toggle the completed state
savedTodos[i].isCompleted = clickedListItem.isCompleted;
// Update the localStorage with the new todos array.
localStorage.setItem("todos", JSON.stringify(savedTodos));
}
}
});
Keep in mind, there are 2 sources of state in your todo list. One is how the document looks, and the other is the array of todos data. Lots of challenges come from making sure these 2 stay in sync.
If somehow the document showed one of the list items as crossed out, but your array of data shows that all the todos are not completed, which version is correct? There is no right answer here, but state management will be something you might consider when designing apps in the future. Redux is a good js library with a well understood pattern that helps solve this problem. Hope this last comment doesn't confuse too much. Best of luck!
The important part is in (de)serializing the data. That means:
reading from localStorage (JSON.parse(localStorage.getItem("todos")) || [])
We add the default [] because if the todos key does not exist, we will get null and we expect a list
saving to localStorage (localStorage.setItem("todos", JSON.stringify(savedTodos)))
We need JSON.parse and its complementary operation JSON.stringify to parse and save strings because localStorage can store only strings.
In your case you need to read the data from localStorage and render the initial list. To save it to localStorage, again, you have to serialize the data. See the below snippets (link to working JSFIDDLE, because the below example does not work in the StackOverflow sandbox environment):
let ul = document.querySelector('ul');
let newItem = document.querySelector('input[type=text]');
const Store = {
serialize () {
return [].slice.call(document.querySelectorAll("li")).map(c => {
return {
text: c.textContent,
finished: c.querySelector("input").checked
}
})
},
get () {
return JSON.parse(localStorage.getItem("todos")) || []
},
save () {
return localStorage.setItem("todos", JSON.stringify(Store.serialize()))
}
}
const firstItems = Store.get()
firstItems.forEach(it => {
output(it.text, it.finished)
})
function output(v, finished) {
let newTodo = document.createElement('li');
newTodo.innerText = v || newItem.value;
newTodo.classList.add('todo');
let ulAppend = ul.append(newTodo);
ul.append(newTodo);
// Create a checkbox for each item
let checkbox = document.createElement('input');
if (finished) {
checkbox.checked = true
}
checkbox.setAttribute('type', 'checkbox');
let checkboxAppend = newTodo.append(checkbox);
newTodo.append(checkbox);
newItem.value = '';
}
let button = document.querySelector('.btn');
button.addEventListener('click', () => {
output()
Store.save()
});
ul.addEventListener('click', function(e) {
if (e.target.tagName === 'LI') {
e.target.remove();
} else if (e.target.tagName === 'INPUT') {
e.target.parentElement.classList.toggle('finished');
}
// Update the value in localStorage when you delete or add a new item
Store.save()
});
<ul></ul>
<input type="text" /> <button class="btn">Submit</button>
I have added the Store variable to simplify the way you get and set the data in localStorage.
The serialize method will read the TODOs from the list. document.querySelectorAll("li") returns a NodeList, but by doing [].slice.call(...) we convert it to an Array.

Printing List to DOM from array in Local Storage

I feel like I am very close on this.
Have a checklist which I'm pushing to an array, and setting to local storage. I want to reprint the list from local storage when the browser is re-instantiated
<script>
localStorage.clear();
var Array_ToDoList = [];
var toDoCount = 0;
$("#add-to-do").on("click", function(event) {
event.preventDefault();
var toDoTask = $("#to-do").val().trim();
Array_ToDoList.push(toDoTask)
localStorage.setItem("STR_Tasks", JSON.stringify(Array_ToDoList))
console.log(Array_ToDoList);
var toDoItem = $("<p>");
toDoItem.attr("id", "item-" + toDoCount);
toDoItem.append(" " + toDoTask);
var toDoClose = $("<button>");
toDoClose.attr("data-to-do", toDoCount);
toDoClose.addClass("checkbox");
toDoClose.append("✓");
toDoItem = toDoItem.prepend(toDoClose);
$("#to-dos").append(toDoItem);
$("#to-do").val("");
toDoCount++;
});
$(document.body).on("click", ".checkbox", function() {
var toDoNumber = $(this).attr("data-to-do");
$("#item-" + toDoNumber).remove();
Array_ToDoList.splice(toDoNumber, 1);
console.log(Array_ToDoList);
localStorage.setItem("STR_Tasks", JSON.stringify(Array_ToDoList))
});
var StoredToDos = Array_ToDoList.length;
for (var i = 0; i < StoredToDos; i++) {
$("#to-dos").append(localStorage.getitem(STR_Tasks[i]));
}
</script>
I know that I have to read the array and reprint, it may be something to with de-stringifying what I have in store.
according to my understanding on the literally code:
it's 'localStorage.getItem' not 'getitem'
the key store in localStorage was "STR_Tasks", it's just string, not iterable type
i think you should push the object 'todoItem' into 'Array_ToDoList', then 'JSON.stringify' it then storge into the localStorage
at last, you can do like this:
var tasks = JSON.parse(localStorage.getItem("STR_Tasks"));
for (var i = 0; i < StoredToDos; i++) {
$("#to-dos").append(tasks[i]);
}
In the first line of the script you clear all the keys in the local storage so you can not use the previous list instead replace localStorage.clear() with :
var Array_ToDoList = JSON.parse(localStorage.getItem('STR_Tasks') || '[]');
This will make your script use the currently saved STR_Tasks.

append table data into table using loop

I want to append table data that I have saved in local storage. I have tried this loop to add in its cells and loop through changing the numbers based on the count or rows it reads. here is my JS code:
$(function() {
$("#loadTask").change(function() {
var task = loadTaskFromStorage1($("#loadTask").val());
var rows = $('#items-table tr').length;
var loop = 0;
var r = 1;
while (loop < rows) {
$("#items-table").append('<tr>'
+'<td>'+task.cells[r][0]+'</td>'
+'<td>'+task.cells[r][1]+'</td>'
+'<td>'+task.cells[r][2]+'</td>'
+'<td>'+task.cells[r][3]+'</tr>')
r += 1;
loop += 1;
}
})
})
this obviously does not work since im guessing when I JSON.Stringify the table data it saves it into one long string becuase when I added alert(row); before and after the loop I got 1 everytime even though the task had two rows.
Here is what I use to append the data into the table which I later save in local storage using a special name so I can save multiple different table datas :
function addRow() {
var item_text = $('#item-input').val();
var item_color = $('#color-input').val();
var size_text = $('#sizes-item').val();
var any_color = $('#any-color').is(':checked') ? 'Any Color' : '';
var any_size = $('#any-size').is(':checked') ? 'Any Size' : '';
$('#items-table').append('<tr>'
+'<td>'+item_text+', '+item_color+'</td>'
+'<td>'+size_text+'</td>'
+'<td>'+any_color+', '+any_size+'</td>'
+'<td><button class="remove-btn"><div class="thex">X</div></button><td>'
+'</tr>');
}
$(function(){
$('#add-item').click(function(){
addRow();
return false;
});
$('body').on('click', '.remove-btn', function(){
$(this).parent().parent().remove();
});
});
I thought that maybe since it wont count the table rows properly the only real thing that doesnt change at any table row is the remove button that gets added with every row.
So it tried changing
var rows = $('#items-table tr').length;
to:
var rows = $('#items-table button').length;
which I thought would work but when I added the alert part before and after the loop I got 0 every time.
What could I do to be able to count each row somehow to be able to append them properly back into the table the same way they were added in.
here is the javascript that saves the table data into localStorage:
$(function() {
loadAllTasks();
$("#addTask").click(function() {
let cells = Array.prototype.map.call($("#items-table")[0].rows, row => {
return Array.prototype.map.call(row.cells, cell => cell.innerHTML);
});
// create task object from cells
var task = {
cells: cells
};
var itemCount = $("#items-table tr").length - 1;
var lengthrows = {
itemCount: itemCount
}
saveLength(lengthrows);
var rowsCount = loadLength()
alert(rowsCount);
// set name property of the task
task.Name = $("#taskName").val();
// call save method using the new task object
saveTaskInStorage(task);
});
function saveTaskInStorage(task) {
// Get stored object from localStorage
var savedTasks = JSON.parse(localStorage.getItem('tasks'));
// To be sure that object exists on localStorage
if (!savedTasks || typeof(savedTasks) !== "object")
savedTasks = {};
// Set the new or exists task by the task name on savedTasks object
savedTasks[task.Name] = task;
// Stringify the savedTasks and store in localStorage
localStorage.setItem('tasks', JSON.stringify(savedTasks));
alert("Task has been Added");
}
function saveLength(lengthrows) {
var count = localStorage.getItem('lengthrows');
if (!count || typeof(count) !== "object")
savedCount = {};
savedCount[task.Name] = task;
localStorage.setItem('itemCount', savedTasks);
}
function loadLength(taskName) {
var lengthCount = localStorage.getItem("itemCount");
return lengthCount[taskName];
}
function loadAllTasks() {
// Get all saved tasks from storage and parse json string to javascript object
var savedTasks = JSON.parse(localStorage.getItem('tasks'));
// To be sure that object exists on localStorage
if (!savedTasks || typeof(savedTasks) !== "object")
return;
// Get all property name of savedTasks object (here it means task names)
for (var taskName in savedTasks) {
$("#loadTask").append('<option>' + taskName + '</option>')
}
}
});
function loadTaskFromStorage1(taskName) {
var savedTasks = JSON.parse(localStorage.getItem('tasks'));
//Return the task by its name (property name on savedTasks object)
return savedTasks[taskName];
}
I am also trying to save the count of the rows in each specific task. The stuff I attempted below with the saveLength doesn't work any suggestions?
Any help is appreciated Thank You <3
Your code when you need load task might be looks like that:
$(function() {
$("#loadTask").change(function() {
var task = loadTaskFromStorage1($("#loadTask").val());
var rows = task.cells;
let tpl = (rows) => {
return rows.slice(1).map(e => '<tr>' + e.map(e => `<td>${e}</td>`) + '</tr>');
}
$("#items-table").append(tpl(rows));
})
})
For removing tasks you need to add removeTask function which i've wrote:
function removeTask (taskName) {
var tasks = JSON.parse(localStorage.getItem('tasks'));
if (typeof tasks !== "object")
return false; // our tasks list not set. return negative.
delete tasks[taskName];
$('#loadTask > option:contains(' + taskName + ')').remove();
localStorage.setItem('tasks', JSON.stringify(tasks));
return true;
};
And modify your click listener at .remove-btn. Your listener should be look like that:
$('body').on('click', '.remove-btn', function(){
$(this).parent().parent().remove();
if ($('#items-table > tbody').children().length < 2) {
console.log("attemping to remove...");
if (removeTask($("#loadTask").val()))
alert('Task successfully removed.');
}
});

Switching between button class's using localstorage

I am trying to use javascript to switch between class's when I push a button. At the same time keeping their state the same when the page is refreshed. The script below runs correctly, because I see the button changes state when clicked. However, when the page is refreshed it is all gone. I did read around this forum about using a cookie in jquery, but I thought I would use local storage because why not.
What am I doing wrong please?
<button name='idButton' class='glyphicon glyphicon-eye-open' id=confirmButton onclick='addBasket(this)'>Click Me</button>
<script>
function addBasket($element) {
var className = $element.getAttribute("class");
if (className == "glyphicon glyphicon-eye-open") {
$element.className = "glyphicon glyphicon-eye-close";
}
else {
$element.className = "glyphicon glyphicon-eye-open";
}
localStorage.setItem("item", $element); //Store the element so it can be accessed later.
localStorage.setItem("class", $element.className); //Store the last class name
}
localStorage.getItem("item").className = localStorage.getItem("class").name;
//The last line should run when page loads because it is outside the scope of the method
</script>
You can't store an element in localStorage. It only stores strings.
Try the following:
//Storing
localStorage.setItem("class", className);
//Page Load (after element exists)
var btnClass = localStorage.getItem("class")
if (btnClass) {
document.getElementById('confirmButton ').className = btnClass;
}
for more advanced objects you can JSON.stringify to store and JSON.parse when you retrieve from storage
I know this is late, but I made an example for persistent button states using dynamically created buttons. You can check out the comments to see what is going on! Persistent Button State using LocalStorage
//These are shortcut helper methods
let select = document.querySelector.bind(document);
let selectAll = document.querySelectorAll.bind(document);
function init() {
//First, create grid of buttons (for testing)
let sethtml = '';
for (var y = 0; y < 5; y++) {
for (var x = 0; x < 5; x++) {
sethtml += "<button class='glyphicon changestate glyphicon-eye-open' id='eyebtn" + x + "" + y + "' onclick='changeState(this)'></button>";
}
sethtml += '<br>';
}
document.body.innerHTML = sethtml;
//Next, get all of the elements whose state can be changed and are persistent
let changeEls = selectAll('.changestate');
//for each one in this list
for (var i = 0; i < changeEls.length; i++) {
let el = changeEls[i];
let id = el.id;
//see if there is a reference to them already in the storage
//and if there is not add that reference
if (localStorage) {
if (!localStorage.getItem(id)) {
//Save the states of the buttons to localStorage
localStorage.setItem(id, JSON.stringify([id, JSON.stringify(el.classList)]));
}
else {
//Set the states based on stored data
let data = JSON.parse(localStorage.getItem(id));
let elid = data[0];
let classList = JSON.parse(data[1]);
//Eliminate previous classes
document.getElementById(elid).className = "";
//Add in classes gathered from storage
for (let myclass in classList) {
select('#' + elid).classList.add(classList[myclass]);
}
}
}
}
}
//Change state of each button
function changeState(el) {
let id = el.id;
//if open, set to close
if (el.classList.contains('glyphicon-eye-open')) {
el.classList.remove('glyphicon-eye-open');
el.classList.add('glyphicon-eye-close');
}
//if close, set to open
else {
el.classList.remove('glyphicon-eye-close');
el.classList.add('glyphicon-eye-open');
}
if (localStorage) {
//set the localStorage to reflect this
localStorage.setItem(id, JSON.stringify([id, JSON.stringify(el.classList)]));
}
}
init();

Categories

Resources