Chapter 5 · The web page

A page of your own

You are reading the whole lesson on one page. Back to one step at a time

Step 1 of 17 · Concept

Your to-do tool, as a page

By the end of this lesson, lesson 20's to-do list is a web page. In it you can:

  • add a task with a form,
  • click a task to mark it done,
  • show only the open tasks,
  • see how many are left.

The class that keeps the tasks is the one you wrote in lesson 20.

import { Task, TaskList } from "./tasks.js";

const list = new TaskList([
  new Task("Buy milk", ["home"], true),
  new Task("Write report", ["work"]),
  new Task("Call Bo", ["phone"]),
]);
let filter = "all";

const form = document.querySelector("#add-form");
const input = document.querySelector("#title");
const tasks = document.querySelector("#tasks");
const allButton = document.querySelector("#all");
const openButton = document.querySelector("#open");

function render() {
  // step 1: an li per task, class done if done
}

console.log(`Loaded ${list.tasks.length} tasks`);
render();
import { Task, TaskList } from "./tasks.js";

const list = new TaskList([
  new Task("Buy milk", ["home"], true),
  new Task("Write report", ["work"]),
  new Task("Call Bo", ["phone"]),
]);
let filter = "all";

const form = document.querySelector("#add-form");
const input = document.querySelector("#title");
const tasks = document.querySelector("#tasks");
const allButton = document.querySelector("#all");
const openButton = document.querySelector("#open");

function render() {
  // step 1: an li per task, class done if done
}

console.log(`Loaded ${list.tasks.length} tasks`);
render();
import { Task, TaskList } from "./tasks.js";

const list = new TaskList([
  new Task("Buy milk", ["home"], true),
  new Task("Write report", ["work"]),
  new Task("Call Bo", ["phone"]),
]);
let filter = "all";

const form = document.querySelector("#add-form");
const input = document.querySelector("#title");
const tasks = document.querySelector("#tasks");
const allButton = document.querySelector("#all");
const openButton = document.querySelector("#open");

function render() {
  tasks.replaceChildren();
  for (const task of list.tasks) {
    const li = document.createElement("li");
    li.textContent = task.title;
    if (task.done) {
      li.classList.add("done");
    }
    tasks.append(li);
  }
}

form.addEventListener("submit", (event) => {
  // step 2: no reload, add the trimmed title,
  // empty the field, then render
});

console.log(`Loaded ${list.tasks.length} tasks`);
render();
import { Task, TaskList } from "./tasks.js";

const list = new TaskList([
  new Task("Buy milk", ["home"], true),
  new Task("Write report", ["work"]),
  new Task("Call Bo", ["phone"]),
]);
let filter = "all";

const form = document.querySelector("#add-form");
const input = document.querySelector("#title");
const tasks = document.querySelector("#tasks");
const allButton = document.querySelector("#all");
const openButton = document.querySelector("#open");

function render() {
  tasks.replaceChildren();
  for (const task of list.tasks) {
    const li = document.createElement("li");
    li.textContent = task.title;
    if (task.done) {
      li.classList.add("done");
    }
    // step 3: an open task's title in a button,
    // whose click marks that task done

    tasks.append(li);
  }
}

form.addEventListener("submit", (event) => {
  event.preventDefault();
  list.add(input.value.trim());
  input.value = "";
  render();
});

console.log(`Loaded ${list.tasks.length} tasks`);
render();
import { Task, TaskList } from "./tasks.js";

const list = new TaskList([
  new Task("Buy milk", ["home"], true),
  new Task("Write report", ["work"]),
  new Task("Call Bo", ["phone"]),
]);
let filter = "all";

const form = document.querySelector("#add-form");
const input = document.querySelector("#title");
const tasks = document.querySelector("#tasks");
const allButton = document.querySelector("#all");
const openButton = document.querySelector("#open");

function render() {
  tasks.replaceChildren();
  for (const task of list.tasks) {
    const li = document.createElement("li");
    if (task.done) {
      li.textContent = task.title;
      li.classList.add("done");
    } else {
      const button = document.createElement("button");
      button.textContent = task.title;
      button.addEventListener("click", () => {
        task.done = true;
        render();
      });
      li.append(button);
    }
    tasks.append(li);
  }
}

form.addEventListener("submit", (event) => {
  event.preventDefault();
  list.add(input.value.trim());
  input.value = "";
  render();
});

// step 4: allButton and openButton set filter,
// then render

console.log(`Loaded ${list.tasks.length} tasks`);
render();
import { Task, TaskList } from "./tasks.js";

const list = new TaskList([
  new Task("Buy milk", ["home"], true),
  new Task("Write report", ["work"]),
  new Task("Call Bo", ["phone"]),
]);
let filter = "all";

const form = document.querySelector("#add-form");
const input = document.querySelector("#title");
const tasks = document.querySelector("#tasks");
const allButton = document.querySelector("#all");
const openButton = document.querySelector("#open");

function render() {
  tasks.replaceChildren();
  let shown = list.tasks;
  if (filter === "open") {
    shown = list.open();
  }
  for (const task of shown) {
    const li = document.createElement("li");
    if (task.done) {
      li.textContent = task.title;
      li.classList.add("done");
    } else {
      const button = document.createElement("button");
      button.textContent = task.title;
      button.addEventListener("click", () => {
        task.done = true;
        render();
      });
      li.append(button);
    }
    tasks.append(li);
  }
}

form.addEventListener("submit", (event) => {
  event.preventDefault();
  list.add(input.value.trim());
  input.value = "";
  render();
});

allButton.addEventListener("click", () => {
  filter = "all";
  render();
});
openButton.addEventListener("click", () => {
  filter = "open";
  render();
});

console.log(`Loaded ${list.tasks.length} tasks`);
render();
import { Task, TaskList } from "./tasks.js";

const list = new TaskList([
  new Task("Buy milk", ["home"], true),
  new Task("Write report", ["work"]),
  new Task("Call Bo", ["phone"]),
]);
let filter = "all";

const form = document.querySelector("#add-form");
const input = document.querySelector("#title");
const tasks = document.querySelector("#tasks");
const allButton = document.querySelector("#all");
const openButton = document.querySelector("#open");
const count = document.querySelector("#count");

function render() {
  tasks.replaceChildren();
  let shown = list.tasks;
  if (filter === "open") {
    shown = list.open();
  }
  for (const task of shown) {
    const li = document.createElement("li");
    if (task.done) {
      li.textContent = task.title;
      li.classList.add("done");
    } else {
      const button = document.createElement("button");
      button.textContent = task.title;
      button.addEventListener("click", () => {
        task.done = true;
        render();
      });
      li.append(button);
    }
    tasks.append(li);
  }
  count.textContent =
    `${list.open().length} open of ${list.tasks.length}`;
}

form.addEventListener("submit", (event) => {
  event.preventDefault();
  list.add(input.value.trim());
  input.value = "";
  render();
});

allButton.addEventListener("click", () => {
  filter = "all";
  render();
});
openButton.addEventListener("click", () => {
  filter = "open";
  render();
});

console.log(`Loaded ${list.tasks.length} tasks`);
render();
Terminal
Step 1 of 7Run the starter

Keyboard shortcuts

The step

ContinueEnter
Previous / next stepAlt+[ · Alt+]
Move along the steps bar← → Home End, then Enter
From a quiz's title to its answers↓
Skip to the stepTab, then Enter (first on the page)
Course outlineAlt+O
These shortcuts?

The workspace

Run the stepCtrl+Enter (⌘↵ on a Mac)
Lesson → editor → consoleF6 (Shift+F6 back)
Output ↔ TerminalCtrl+`
Focus the editorCtrl+. (⌘. on a Mac)
Hide or show the lessonAlt+L
Restore, close a messageEsc (outside the editor and the terminal)

The editor

Leave the editorF6 (Shift+F6 back); or Ctrl+M (⌃⇧M on a Mac), then Tab moves the focus (not in the vim mode)
Open a file by nameCtrl+P (⌘P on a Mac)
All commandsCtrl+Shift+P (⌘⇧P on a Mac) or F1
Go to a lineCtrl+G (⌃G on a Mac)
Show or hide the filesCtrl+B (⌘B on a Mac)
Previous / next file tabCtrl+Shift+[ · Ctrl+Shift+] (⌘⇧[ · ⌘⇧] on a Mac)
The file tabs← → Home End on a tab; Delete closes it
Save the files nowCtrl+S (⌘S on a Mac)
Go to a symbol in the fileCtrl+Shift+O (⌘⇧O on a Mac)
Go to the definitionF12
Format the fileCtrl+Shift+F (⌘⇧F on a Mac), or Shift+Alt+F
Go back / forward after a jumpAlt+← · Alt+→ (⌃- · ⌃⇧- on a Mac)