We’ve come a long way in this JavaScript from Zero journey.
From the very first basics of variables and events, we gradually built up our app step by step.
Now, in this final step, we’ll close the loop: our app becomes a full-featured to-do list, ready to use just like the ones you find on your phone.
What Makes a To-Do List “Complete”?
A real to-do list isn’t just about adding text. It should let you:
- ➕ Add new tasks
- ✅ Mark tasks as completed
- ✏️ Edit tasks if needed
- ❌ Delete tasks that are no longer relevant
- 💾 Save everything automatically with
localStorage
With these features, your project is no longer just an exercise—it’s a useful everyday app.
Adding and Completing Tasks
Let’s start with the core: adding a new item and marking it as completed with a click.
function addTask(text) {
const li = document.createElement("li");
li.textContent = text;
li.addEventListener("click", () => {
li.classList.toggle("done");
saveList();
});
document.querySelector("#todo-list").appendChild(li);
saveList();
}
Here, classList.toggle("done") helps us easily manage the completed/uncompleted state.
Editing and Deleting Tasks
To make the list flexible, we’ll add two buttons to each task:
- ✏️ Edit task text
- ❌ Delete task
function createTaskElement(text) {
const li = document.createElement("li");
const span = document.createElement("span");
span.textContent = text;
const editBtn = document.createElement("button");
editBtn.textContent = "✏️";
editBtn.onclick = () => {
const newText = prompt("Edit your task:", span.textContent);
if (newText) {
span.textContent = newText;
saveList();
}
};
const deleteBtn = document.createElement("button");
deleteBtn.textContent = "❌";
deleteBtn.onclick = () => {
li.remove();
saveList();
};
li.append(span, editBtn, deleteBtn);
return li;
}
Saving with LocalStorage
localStorage is what gives your app memory, so nothing is lost when you close the browser.
function saveList() {
const tasks = [];
document.querySelectorAll("#todo-list li span").forEach(span => {
tasks.push({
text: span.textContent,
done: span.parentElement.classList.contains("done")
});
});
localStorage.setItem("tasks", JSON.stringify(tasks));
}
function loadList() {
const data = localStorage.getItem("tasks");
if (!data) return;
const tasks = JSON.parse(data);
tasks.forEach(task => {
const li = createTaskElement(task.text);
if (task.done) li.classList.add("done");
document.querySelector("#todo-list").appendChild(li);
});
}
Just call loadList() when the page loads, and your tasks will be restored.
Conclusion
🎉 Congratulations! You’ve reached the final step of our JavaScript from Zero series.
You’ve learned how to:
- Manipulate the DOM
- Work with events and functions
- Use arrays and objects for storing data
- Make your app persistent with
localStorage
Your to-do list is now fully functional: simple, practical, and real.
From here, you can go further: customize it with CSS styles, add filters (active/completed), priorities, due dates, or even connect it to a small backend to share tasks with others.
This project proves that with just a few lines of JavaScript, you can build something that makes everyday life easier.
And that’s the true power of JavaScript. 🚀
