HTML5 provides the localStorage
and sessionStorage
objects that let the web page use JavaScript to store data in name
and value
pairs. In this tutorial, I will show you how to use the local storage using JavaScript with a practical 🔥Todo List example.
JavaScript localStorage Object Methods and Syntax
The localStorage
is retained indefinitely.
localStorage.setItem("itemname", "value") // saves the data in the item localStorage.getItem("itemname") // get the data in the item localStorage.removeItem("itemname") // removes the item localStorage.clear() // removes all items
JavaScript sessionStorage Object Methods and Syntax
The sessionStorage
is lost when the user closes the browser.
sessionStorage.setItem("itemname", "value") // saves the data in the item sessionStorage.getItem("itemname") // get the data in the item sessionStorage.removeItem("itemname") // removes the item sessionStorage.clear() // removes all items
The shortcut syntax for getting or saving an item
localStorage.itemname // saves or gets the data sessionStorage.itemname // saves or gets the data
setItem Method
The setItem
method requires two parameters that provide the name
of an item and the value
for the item. For instance, you can use code like this to add items named "email" and "phone" that store the email address and phone number of the user:
localStorage.setitem("email", "[email protected]"); localStorage.setitem("phone", "+91 111222333");
getItem Method
Now you can use the getItem
method with the item name
as the parameter to retrieve the data for the phone item with the statement as follows:
localStorage.getItem("phone");
To simplify, you can use the shortcut syntax as shown in the below example:
localStorage.email = "[email protected]" localStorage.phone = "+91 111222333"
An example to get the local storage value into the variable:
var phone = localStorage.phone;
Todo List Example
Here I am giving an example of a beautiful Todo list created using the JavaScript localStorage
object:
HTML Code
<html lang="en"> <head> <meta charset="utf-8"> <title>Todo List</title> <link rel="stylesheet" href="style.css"> </head> <body> <section class="todoapp"> <header class="header"> <h1>todo list</h1> <input id="newTodo" class="new-todo" placeholder="What needs to be done?"> </header> <section id="main"> <input id="toggleInputAll" class="toggle-all" type="checkbox"> <label for="toggle-all">Mark all as complete</label> <ul id="todoListView" class="todo-list"></ul> </section> <footer class="footer"> <span class="todo-count"><strong id="todoCount">0</strong> item left</span> <ul class="filters"> <li> <a class="selected" id="allWorks" onclick="changeClass(this)" href="#/">All</a> </li> <li> <a href="#active" id="activedItems" onclick="changeClass(this)">Active</a> </li> <li> <a href="#completed" id="completedTodos" onclick="changeClass(this)">Completed</a> </li> </ul> <button class="clear-completed" id="btnClear">Clear completed</button> </footer> </section> <script src="todo-list.js"></script> </body> </html>
CSS Code
html, body { margin: 0; padding: 0; } button { margin: 0; padding: 0; border: 0; background: none; font-size: 100%; vertical-align: baseline; font-family: inherit; font-weight: inherit; color: inherit; } button, input[type="checkbox"] { outline: none; } body { font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif; line-height: 1.4em; background: #f5f5f5; color: #4d4d4d; min-width: 230px; max-width: 550px; margin: 0 auto; font-weight: 300; } .hidden { display: none; } .todoapp { background: #fff; margin: 130px 0 40px 0; position: relative; box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1); } .todoapp input::input-placeholder { font-style: italic; font-weight: 300; color: #e6e6e6; } .todoapp h1 { position: absolute; top: -155px; width: 100%; font-size: 100px; font-weight: 100; text-align: center; text-transform: capitalize; color: #cc9a9a; } .new-todo, .edit { position: relative; margin: 0; width: 100%; font-size: 24px; border: 0; outline: none; padding: 6px; border: 1px solid #999; box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2); box-sizing: border-box; } .new-todo { padding: 16px 16px 16px 60px; border: none; background: rgba(0, 0, 0, 0.003); box-shadow: inset 0 -2px 1px rgba(0,0,0,0.03); } .main { position: relative; z-index: 2; border-top: 1px solid #e6e6e6; } label[for='toggle-all'] { display: none; } .toggle-all:before { content: '❯'; font-size: 22px; color: #e6e6e6; padding: 10px 27px 10px 27px; } .toggle-all:checked:before { color: #737373; } .toggle-all { position: absolute; top: 5px; left: -12px; width: 60px; height: 34px; text-align: center; border: none; /* Mobile Safari */ -webkit-transform: rotate(90deg); transform: rotate(90deg); -webkit-appearance: none; } .todo-list { margin: 0; padding: 0; list-style: none; } .todo-list li { position: relative; font-size: 24px; border-bottom: 1px solid #ededed; } .todo-list li:last-child { border-bottom: none; } .todo-list li.checked { color: #979797; font-weight: normal; text-decoration: line-through; } .todo-list li.checked input[type="checkbox"]:after { border: 1px solid #166B94; border-radius: 3px; color: #fff; content: ""; display: block; height: 16px; line-height: 16px; position: absolute; text-align: center; visibility: visible; width: 16px; } .todo-list li.checked input[type=checkbox]:checked:after { border: 1px solid #979797; color: #979797; content: "✓"; font-size: 25px; color: green; } .todo-list li .itemList { text-align: center; height: 20px; /* auto, since non-WebKit browsers doesn't support input styling */ position: absolute; top: 0; bottom: 0; margin: auto 0; } .todo-list li label { white-space: pre-line; word-break: break-all; padding: 15px 60px 15px 15px; margin-left: 45px; display: block; line-height: 1.2; transition: color 0.4s; } .todo-list input[type=checkbox] { cursor: pointer; visibility: hidden; margin-left: 20px; } .todo-list input[type="checkbox"]:after { border: 1px solid #166B94; border-radius: 3px; color: #fff; content: ""; display: block; height: 16px; line-height: 16px; position: absolute; text-align: center; visibility: visible; width: 16px; } .todo-list input[type=checkbox]:checked:after { border: 1px solid #979797; color: #979797; content: "✓"; font-size: 25px; color: green; } .todo-list input[type=checkbox]:checked + label { color: #979797; font-weight: normal; text-decoration: line-through; } .todo-list li .remove { display: none; position: absolute; top: 0; right: 10px; bottom: 0; width: 40px; height: 40px; margin: auto 0; font-size: 30px; color: #cc9a9a; margin-bottom: 11px; transition: color 0.2s ease-out; cursor: pointer; } .todo-list li .remove:hover { color: #af5b5e; } .todo-list li .remove:after { content: '×'; } .todo-list li:hover .remove { display: block; } .edit { display: none; } li.editing { display: block; width: 430px; } li.editing > label { display: none; } li.editing > input.edit { display: block !important; } li:hover.editing > button.remove { display: none ; } .todo-list li.editing .edit { display: block; width: 506px; padding: 13px 17px 12px 17px; margin: 0 0 0 43px; } .show-all { display: block; } .todo-list li.editing:last-child { margin-bottom: -1px; } .footer { color: #777; padding: 10px 15px; height: 20px; text-align: center; border-top: 1px solid #e6e6e6; } .footer:before { content: ''; position: absolute; right: 0; bottom: 0; left: 0; height: 50px; overflow: hidden; box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2), 0 8px 0 -3px #f6f6f6, 0 9px 1px -3px rgba(0, 0, 0, 0.2), 0 16px 0 -6px #f6f6f6, 0 17px 2px -6px rgba(0, 0, 0, 0.2); } .todo-count { float: left; text-align: left; } .filters { margin: 0; padding: 0; list-style: none; position: absolute; right: 0; left: 0; } .filters li { display: inline; } .filters li a { color: inherit; margin: 3px; padding: 3px 7px; text-decoration: none; border: 1px solid transparent; border-radius: 3px; } .filters li a.selected { border-color: rgba(175, 47, 47, 0.2); } .clear-completed, html .clear-completed:active { float: right; position: relative; line-height: 20px; text-decoration: none; cursor: pointer; } .clear-completed:hover { text-decoration: underline; }
JavaScript Code
'use strict' function Todo(id, content, isDone) { this.id = id; this.content = content; this.isDone = isDone; }; /** * Declare a controller */ function TodoController() { this.todoList = []; this.id = 1; this.ENTER_KEY = 13; this.todoInput = document.getElementById('newTodo'); this.todoListView = document.getElementById('todoListView'); }; TodoController.prototype = { /** * @param {argument} key - get to localstorage */ getTodoFromLocalstorage: function (key) { var todoList = JSON.parse(localStorage.getItem(key)) || []; return todoList; }, /** * @param {argument} key - set into localstorage */ setTodoLocalstorage: function (key) { localStorage.setItem('todoList', JSON.stringify(key)); }, /** * @param {sting} value - content todo */ handleTodoItem: function (value) { this.isDone = false; var mainArray = todoController.getTodoFromLocalstorage('todoList'); this.id = todoController.idLargestOfLocal(mainArray) + 1; var todoItem = new Todo(this.id, value, this.isDone); return todoItem; }, /** * @param {array} mainArray - find id last in array at localstorage */ idLargestOfLocal: function (mainArray) { var lengthArr = mainArray.length; if (lengthArr !== 0) { return mainArray[lengthArr - 1].id; } else { return 0; } return lastId; }, /** * Presentation create new a todo item * @param {array} list - id for todo * @return {object} todo - return todo object */ addNewTodo: function (todo, list) { list.push(todo); todoController.setTodoLocalstorage(list); return todo; }, /** * Presentation create new a todo item * @param {value attribute} attrs - value attribute for element html * @return {attribute} element - attribute for element html */ setAttributes: function (element, attrs) { for (var key in attrs) { element.setAttribute(key, attrs[key]); } }, /** * Create new checkbox input element * @param {number} todoId - id checkbox */ checkboxView: function (todoId) { var inpCheckbox = document.createElement('input'); this.setAttributes(inpCheckbox, { type: 'checkbox', class: 'itemList', id: todoId }); //event check for input checkbox inpCheckbox.addEventListener('click', function (e) { //get list array from localStorage var list = todoController.getTodoFromLocalstorage('todoList'); var id = e.target.getAttribute('id'); for (var i = 0; i < list.length; i++) { if (list[i].id == id) { list[i].isDone = e.target.checked; } } //save list todo to localStorage todoController.setTodoLocalstorage(list); todoController.countItem(); }); return inpCheckbox; }, /** * Create new lable element * @param {object} todo - item todo from addNewTodo */ createLableView: function (todo) { var lbContent = document.createElement('label'); this.setAttributes(lbContent, { value: todo.content, class: 'labelContent ' }); lbContent.innerHTML = todo.content; //return node lable return lbContent; }, /** * Create new li element * @param {object} todo - item todo from addNewTodo */ initTodoITem: function (todo) { var item = document.createElement('li'); item.setAttribute('class', 'todoItem'); // this.setAttributes(item, { , class: 'todoItem ' }); //event event double click in node li item.addEventListener('dblclick', function (e){ item.classList.add('editing'); }); //return node li return item; }, /** * Create new input edit element * @param {object} todo - item todo from addNewTodo */ editInputView: function (todo) { //get array from localStorage var list = todoController.getTodoFromLocalstorage('todoList'); var inputEdit = document.createElement('input'); this.setAttributes(inputEdit, { id: todo.id, class: 'edit', value: todo.content, type: 'text', }); inputEdit.focus(); //event onblur get value edit and delete class editing when click outside this input inputEdit.onblur = function (e) { todoController.handleTodoUpdate(e); }; //event onkeyup get value edit form inputEdit inputEdit.onkeypress = function (e) { if (event.which == todoController.ENTER_KEY || event.keyCode == todoController.ENTER_KEY) { todoController.handleTodoUpdate(e); } }; //return node input for edit todo return inputEdit; }, handleTodoUpdate: function (event) { var list = todoController.getTodoFromLocalstorage('todoList'); var inputEdit = event.target; var todoItem = new Todo(inputEdit.id, inputEdit.value, false); todoController.updateTodoEdit(todoItem, list); var editing = document.querySelector('.editing'); editing.classList.remove('editing'); todoController.renderTodo(); }, /** * Presentation update todo edit * @param {object} todo - get item todo from event get value edit * @param {array} list - array in localStorage */ updateTodoEdit: function (todo, list) { for (var i = 0; i < list.length; i++) { if (list[i].id == todo.id) { list[i].content = todo.content; todoController.setTodoLocalstorage(list); break; } } //return new object have edit return todo; }, /** * Presentation create new button remove item todo * @param {object} todo - get item todo from event get value edit */ removeButtonView: function (todo) { var btnRemove = document.createElement('button'); this.setAttributes(btnRemove, { class: 'remove', id: todo.id }); //event click mouse into btnRemove a item todo btnRemove.addEventListener('click', function (e) { var id = e.target.getAttribute('id'); todoController.removeTodo(id); todoController.renderTodo(); todoController.countItem(); }); //return node button return btnRemove; }, /** * Presentation create new a todo item * @param {object} todo - object render to view */ todoView: function (todo) { var item = this.initTodoITem(todo);//create node li var inpCheckbox = this.checkboxView(todo.id),//create node input checkbox lbContent = this.createLableView(todo),//create node lable inputEdit = this.editInputView(todo),//create node input edit btnRemove = this.removeButtonView(todo);//create node button remove item todo //item append each element item.appendChild(inpCheckbox); item.appendChild(lbContent); item.appendChild(inputEdit); item.appendChild(btnRemove); //ul append each item document.querySelector('#todoListView').appendChild(item); //return node li contain inpCheckbox, lbContent, inputEdit, btnRemove return item; }, /** * Presentation remove a item todo * @param {number} id - id button remove item todo * @param {array} list - list array get from localStorage */ removeTodo: function (id, list) { list = todoController.getTodoFromLocalstorage('todoList'); for (var i = 0; i < list.length; i++) { if (list[i].id == id) { list.splice(i, 1); break; } } //set value after remove item to localStorage todoController.setTodoLocalstorage(list); }, /** * Presentation remove a item todo * @param {index} index - index in array object * @param {array} list - list array get from localStorage */ countItem: function (index, list) { list = todoController.getTodoFromLocalstorage('todoList'); index = 0; for (var i = 0; i < list.length; i++) { if (!list[i].isDone) { index++; } } // return index display to UI; document.getElementById('todoCount').innerHTML = index; }, /** * Presentation the events for todo */ events: function () { // Event add todo todoController.todoInput.onkeyup = function (event) { if (event.which == todoController.ENTER_KEY || event.keyCode == todoController.ENTER_KEY) { //get from localStorage var todoList = todoController.getTodoFromLocalstorage('todoList'); //attach value for todo var todoItem = todoController.handleTodoItem(todoController.todoInput.value); //add new a Todo var todo = todoController.addNewTodo(todoItem, todoList); //Execute display to UI todoController.todoView(todo); //clear input todoController.todoInput.value = ''; todoController.countItem(); } }; //event check all checkbox in list item var list = document.getElementsByClassName('itemList'); var checkAll = document.getElementById('toggleInputAll'); checkAll.addEventListener('change', function (e) { var check; for (var i = 0; i < list.length; i++) { list[i].checked = this.checked; check = e.target.checked; todoController.checkAllTodo(check); } todoController.countItem(); }); //Show all items var listWork = document.getElementsByClassName('todoItem'); var showAllItem = document.getElementById('allWorks'); showAllItem.addEventListener('click', function () { for (var i = 0; i < listWork.length; i++) { listWork[i].style.display = 'block'; } }); // Filter todo list with actived items var activeItem = document.getElementsByClassName('todoItem'); var todoActive = document.getElementById('activedItems'); todoActive.addEventListener('click', function () { for (var i = 0; i < list.length; i++) { if (!list[i].checked) { activeItem[i].style.display = 'block'; } else { activeItem[i].style.display = 'none'; } } }); //Filter completed todo list var completeItem = document.getElementsByClassName('todoItem'); var todoCompleted = document.getElementById('completedTodos'); todoCompleted.addEventListener('click', function () { for (var i = 0; i < list.length; i++) { if (list[i].checked) { completeItem[i].style.display = 'block'; } else { completeItem[i].style.display = 'none'; } } }); // Added event clear completed items for button var clearButton = document.getElementById('btnClear'); clearButton.addEventListener('click', function () { //get from localStorage var list = todoController.getTodoFromLocalstorage('todoList'); todoController.clearCompleted(list); todoController.setTodoLocalstorage(list); todoController.renderTodo(); }); }, /** * Presentation clear all item todo have isDone * @param {array} list - get from localstorage */ clearCompleted: function (list) { while (list.find(({ isDone }) => isDone)) { list.splice(list.indexOf(list.find(({ isDone }) => isDone)), 1); } }, /** * Presentation set status isDone into localstorage * @param {boolean} check - isDone from event checkall * @param {array} todoList - list array get from localStorage */ checkAllTodo: function (check, todoList) { todoList = todoController.getTodoFromLocalstorage('todoList'); for (var i = 0; i < todoList.length; i++) { todoList[i].isDone = check; todoController.setTodoLocalstorage(todoList); } }, /** * Presentation set status isDone into localstorage * @param {array} list - list array get from localStorage */ renderTodo: function () { //get from localStorage var list = todoController.getTodoFromLocalstorage('todoList'); todoController.removeElement(); for (var i = 0; i < list.length; i++) { var element = todoController.todoView(list[i]); if (list[i].isDone) { element.classList.add('checked'); } } }, removeElement: function () { var todoListView = document.getElementById('todoListView'); while (todoListView.hasChildNodes()) { todoListView.removeChild(todoListView.firstChild); } }, }; //change class selected function changeClass(elem) { var a = document.getElementsByTagName('a'); for (var i = 0; i < a.length; i++) { a[i].classList.remove('selected'); }; //add class selected for element user click elem.classList.add('selected'); }; //todoController handle all action add, delete, edit, events var todoController = new TodoController(); //todo create new object todo var todo = new Todo(); //performing the events todoController.events(); // //performing render todo display to UI todoController.renderTodo(); //performing count all item active todoController.countItem();