CodeBlanks Logo Icon CodeBlanks

Project final - To-do DOM

JavaScript course · Intermediate · Lesson 53/134

Finalize the to-do app and make the UI and interactions work.

Project wrap-up: the last feature

The app can now add, complete, and delete tasks. As a final feature we'll add a "Complete all" button: when clicked, it marks every task with the done class.

We'll create a new button and append it to the app container. In the click listener we'll loop over list.children with a for...of loop and call classList.add("done") on each item.

list.children is a live collection; every task added to the list shows up here automatically.

Iterating with for...of

list.children returns an HTMLCollection; with a for...of loop we take each child in turn. Writing for (const item of list.children) makes item the next li on each pass.

For each item we call item.classList.add("done"). Unlike toggle, add adds the class if missing and does nothing if already there.

We'll define this button separately from addButton, as completeAllButton.

Exercise Add the complete-all button

Continue on top of the previous lesson's solution. Create a new button, set its textContent to "Complete all", and append it to app. In a click listener, loop with for (const item of list.children) and call item.classList.add("done") on each item.

Show example solution
Write const completeAllButton = document.createElement('button'), set textContent, and append with app.appendChild. Then add completeAllButton.addEventListener('click', function() { for (const item of list.children) { item.classList.add('done'); } }).

Example solution:
// Todo application
const app = document.getElementById("app");
const title = document.createElement("h1");
title.textContent = "Todo list";
app.appendChild(title);

const input = document.createElement("input");
input.placeholder = "New task";
const addButton = document.createElement("button");
addButton.textContent = "Add";
const list = document.createElement("ul");

app.appendChild(input);
app.appendChild(addButton);
app.appendChild(list);

function addTask() {
  const text = input.value;
  if (text === "") return;
  const item = document.createElement("li");
  item.textContent = text;
  list.appendChild(item);
  input.value = "";
}

addButton.addEventListener("click", addTask);

list.addEventListener("click", function(event) {
  const target = event.target;
  if (target.tagName === "LI") {
    target.classList.toggle("done");
  }
});

list.addEventListener("dblclick", function(event) {
  const target = event.target;
  if (target.tagName === "LI") {
    list.removeChild(target);
  }
});

const completeAllButton = document.createElement("button");
completeAllButton.textContent = "Complete all";
app.appendChild(completeAllButton);

completeAllButton.addEventListener("click", function() {
  for (const item of list.children) {
    item.classList.add("done");
  }
});

Test yourself

  1. What do we use to complete all tasks?

    for (const item of list.children) {
      item.classList.add("done");
    }
    • forEach on list
    • for...of on list.children
    • while on list.firstChild
    • map on list.children
    Show answer

    for...of on list.children — Correct! for...of iterates the live children collection.

  2. Complete the for...of loop

    for (const item ____) {
      item.classList.add("done");
    }
    Show answer
    for (const item of list.children) {
      item.classList.add("done");
    }
  3. Match lesson to feature

    Lesson 1
    Heading skeleton
    Lesson 2
    Input, button, list
    Lesson 3
    Adding tasks
    Lesson 4
    Complete and delete
    Lesson 5
    Complete all

All lessons in Intermediate