Welcome to a tutorial and example on how to create a simple Javascript to-do list. Looking to create a web application without the use of server-side scripts? Yep, you read that right – This is a pure vanilla Javascript to-do list that uses local storage only. No PHP and no database are required. Read on!
TABLE OF CONTENTS
PURE JAVASCRIPT TO-DO LIST
All right, let us get into the details of how the Javascript to-do list is being built.
TO-DO LIST DEMO
PART 1) HTML PAGE
<div id="todo-wrap">
<!-- (B) ADD NEW ITEM -->
<form id="todo-add">
<input type="text" id="todo-item" placeholder="New Item" required>
<input type="submit" id="todo-save" value="✚">
</form>
<!-- (B) LIST ITEMS -->
<div id="todo-list"></div>
<!-- (C) ITEM TEMPLATE -->
<template id="todo-template">
<div class="todo-row">
<input type="button" class="todo-del" value="✖">
<input type="button" class="todo-edit" value="✎">
<input type="text" class="todo-item" disabled>
<input type="button" class="todo-done" value="✔">
</div>
</template>
</div>
This can be a little “scary” for beginners, but keep calm and look carefully.
- Just a simple “add item” HTML form.
- An empty
<div>
to generate the list of items. - The template for the items.
Easy.
PART 2) THE JAVASCRIPT
2A) INITIALIZE TO-DO LIST
// (A) INITIALIZE TO DO LIST
data : [], // todo list data array
hAdd : null, // html add item text field
hTemplate : null, // html item row template
hList : null, // html to do list
init : () => {
// (A1) INIT LOCALSTORAGE
if (localStorage.todo == undefined) { localStorage.todo = "[]"; }
// (A2) RESTORE PREVIOUS SESSION
todo.data = JSON.parse(localStorage.todo);
// (A3) GET HTML ELEMENTS
todo.hAdd = document.getElementById("todo-item");
todo.hTemplate = document.getElementById("todo-template").content;
todo.hList = document.getElementById("todo-list");
// (A4) "ENABLE" ADD ITEM FORM
document.getElementById("todo-add").onsubmit = todo.add;
// (A5) DRAW TO DO LIST
todo.draw();
},
// (H) PAGE INIT
window.addEventListener("load", todo.init);
On window load, todo.init()
will run to initialize the to-do list. What it does is straightforward once you trace through it –
- Get the HTML elements, “enable” the add item form.
- Load the previous session from
localStorage.todo
, parse back it intotodo.data
. - By the way,
todo.data
is an array of arrays to keep our to-do list, in the format of["ITEM", true if done, false if not]
. - Don’t worry, an easy example to illustrate this –
[["Feed doge", true], ["Play with doge", false]]
2B) DRAW LIST
// (B) DRAW TO DO LIST
draw : () => {
// (B1) RESET LIST
todo.hList.innerHTML = "";
// (B2) LOOP & GENERATE ROWS
if (todo.data.length>0) { for (let id in todo.data) {
let row = todo.hTemplate.cloneNode(true),
edit = row.querySelector(".todo-edit"),
item = row.querySelector(".todo-item");
item.value = todo.data[id][0];
item.id = "item" + id;
edit.id = "edit" + id;
edit.onclick = () => todo.edit(id);
row.querySelector(".todo-done").onclick = () => todo.toggle(id);
row.querySelector(".todo-del").onclick = () => todo.del(id);
if (todo.data[id][1]) { row.querySelector(".todo-item").classList.add("todo-ok"); }
todo.hList.appendChild(row);
}}
},
Not much of a mystery here. We are just looping through todo.data
and using the HTML template to quickly generate the rows.
2C) SAVE, EDIT, UPDATE, DELETE
// (C) HELPER - SAVE DATA INTO LOCAL STORAGE
save: () => {
localStorage.todo = JSON.stringify(todo.data);
todo.draw();
},
// (D) ADD A NEW ITEM TO THE LIST
add : () => {
todo.data.push([todo.hAdd.value, false]);
todo.hAdd.value = "";
todo.save();
return false;
},
// (E) TOGGLE EDIT ITEM
edit : id => {
// (E1) GET EDIT BUTTON + ITEM
let edit = document.getElementById("edit" + id),
item = document.getElementById("item" + id);
// (E2) SET EDITABLE
if (item.disabled) {
item.classList.add("editing");
item.disabled = false;
item.select();
edit.value = "\u270F";
}
// (E3) SAVE
else {
item.classList.remove("editing");
item.disabled = true;
edit.value = "\u270E";
todo.data[id][0] = item.value;
todo.save();
}
},
// (F) UPDATE TODO ITEM DONE/NOT YET
toggle: id => {
todo.data[id][1] = !todo.data[id][1];
todo.save();
},
// (G) DELETE ITEM
del: id => { if (confirm("Delete task?")) {
todo.data.splice(id, 1);
todo.save();
}}
Lastly, these series of functions are what drive the data behind the scene. Remember that todo.data
is an array that contains all list data? To update, we simply have to push/pop/splice it. Of course, remember to save it into the localStorage
, so that it can be retrieved later.
DOWNLOAD & NOTES
Here is the download link to the example code, so you don’t have to copy-paste everything.
SORRY FOR THE ADS...
But someone has to pay the bills, and sponsors are paying for it. I insist on not turning Code Boxx into a "paid scripts" business, and I don't "block people with Adblock". Every little bit of support helps.
Buy Me A Coffee Code Boxx eBooks
EXAMPLE CODE DOWNLOAD
Click here to download. I have released it under the MIT license, so feel free to build on top of it or use it in your own project.
EXTRA BITS & LINKS
That’s it for all the code, and here are a few small extras that may be useful to you.
COMPATIBILITY CHECKS
- Local Storage – CanIUse
- Arrow Functions – CanIUse
This to-do list will work on all modern browsers.
LINKS & REFERENCES
- Local Storage – MDN
- JSON – MDN
- Example on CodePen – JS To-Do List
THE END
Thank you for reading, and we have come to the end of this guide. I hope that it has helped you with your project, and if you have anything to share with this guide, please feel free to comment below. Good luck and happy coding!
can you please include the code for todo.data updation also
Sorry, I don’t catch your question.
todo.data
is only an array.todo.add()
Pushes a new item into the array.todo.del()
Removes the selected item from it.todo.list()
Reads the array and constructs the HTML.todo.save()
Takes the array and stores it intolocalStorage
.todo.load()
Takes data fromlocalStorage
and reconstructs the array.