📅 note公開日:2025-08-24 22:17
🔁 この記事はnoteで公開していた内容をQiitaへ移行・再掲したものです。(必要に応じて加筆修正しています)
始めに与えられるコードと、課題を段階的に実装していった備忘録です。
始めに与えられるコード
index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Todo</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div class="todo-app">
<h1>Todoリスト</h1>
<form id="text-form">
<input type="text" id="todo-input" placeholder="新しいタスクを入力" />
<button type="submit" id="add-button">タスクを追加する</button>
</form>
<ul id="todo-list">
<!-- タスクはここに追加される。下記のようなタグを追加する -->
<!-- <li class="todo-item"><input type="checkbox"><span>TODO</span><button class="delete-button">削除</button></li> -->
</ul>
</div>
<script src="todo.js"></script>
</body>
</html>
style.css
body {
background-color: #F4F4F4;
}
.todo-app {
width: 400px;
margin: 0 auto;
background-color: #fff;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
padding: 20px;
border-radius: 8px;
}
h1 {
text-align: center;
}
form {
display: flex;
margin-bottom: 20px;
}
#todo-input {
flex-grow: 1;
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
}
#add-button {
padding: 10px 20px;
border: none;
background-color: #007BFF;
color: #fff;
cursor: pointer;
margin-left: 10px;
border-radius: 4px;
}
#add-button:hover {
background-color: #0056b3;
}
#todo-list {
list-style-type: none;
padding: 0;
}
.todo-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px;
margin-bottom: 10px;
background-color: #f2f2f2;
border-radius: 4px;
}
.delete-button {
padding: 5px 10px;
border: none;
background-color: #ff4d4d;
color: #fff;
cursor: pointer;
border-radius: 4px;
}
.delete-button:hover {
background-color: #cc0000;
}
1. タスク追加機能
① まずは入力内容が取得できるか、console.logで確認
要件
- テキストボックスに入力 → 追加ボタン押下 → 入力内容をコンソールに出す
//①要素の取得
const form = document.getElementById('text-form');
const textInput = document.getElementById('todo-input');
const todolist = document.getElementById('todo-list');
const addButton = document.getElementById('add-button');
//②イベント
form.addEventListener('submit', (e) => {
e.preventDefault();
});
addButton.addEventListener('click', () => {
const todoInput = textInput.value.trim();
console.log(todoInput);
});
② UIに追加して、入力欄を空にする
要件
- タスクが追加され表示される
- テキストボックスは空になる
- 入力が空なら何もしない
//①要素の取得
const form = document.getElementById('text-form');
const textInput = document.getElementById('todo-input');
const todolist = document.getElementById('todo-list');
const addButton = document.getElementById('add-button');
//②イベント
form.addEventListener('submit', (e) => {
e.preventDefault();
});
addButton.addEventListener('click', handleClick);
//③関数(動詞で命名)
function handleClick() {
const todoinput = textInput.value.trim();
if (todoinput === "") return; //空入力を無視
const li = document.createElement('li');
li.textContent = todoinput;
todolist.appendChild(li);
//フォームの中を消す
form.reset();
//textInputにカーソルを戻す
textInput.focus();
}
2. 削除ボタン機能
要件
- 各タスクに削除ボタンが付く
- 押すと、そのタスクが削除される
① delete-buttonの要素取得について
-
id="delete-button"は 1つしか持てない(ユニーク) - タスクごとに増やすので classで管理する
取得するならこんなイメージ(ただし今回は「追加時に作る」ので、最初にまとめ取りは必須ではない)
const deletebtn = document.querySelectorAll('.delete-button');
②
の中に と を入れるように変更//①要素の取得
const form = document.getElementById('text-form');
const textInput = document.getElementById('todo-input');
const todolist = document.getElementById('todo-list');
const addButton = document.getElementById('add-button');
//②イベント
form.addEventListener('submit', (e) => {
e.preventDefault();
});
addButton.addEventListener('click', handleClick);
//③関数(動詞で命名)
function handleClick() {
const todoinput = textInput.value.trim();
if (todoinput === "") return; //空入力を無視
const li = document.createElement('li');
todolist.appendChild(li);
const span = document.createElement('span');
span.textContent = todoinput;
const delBtn = document.createElement('button');
delBtn.className = 'delete-button';
delBtn.textContent = '削除';
li.appendChild(span);
li.appendChild(delBtn);
//フォームの中を消す
form.reset();
textInput.focus();
}
ポイント
-
li.textContent = todoinput;を残すと spanと二重表示になるので削除する
③ 削除イベントを追加
delBtn.addEventListener('click', () => {
li.remove();
});
完成形(ここまで反映):
//①要素の取得
const form = document.getElementById('text-form');
const textInput = document.getElementById('todo-input');
const todolist = document.getElementById('todo-list');
const addButton = document.getElementById('add-button');
//②イベント
form.addEventListener('submit', (e) => {
e.preventDefault();
});
addButton.addEventListener('click', handleClick);
//③関数(動詞で命名)
function handleClick() {
const todoinput = textInput.value.trim();
if (todoinput === "") return; //空入力を無視
const li = document.createElement('li');
li.classList.add('todo-item');
const checkbox = document.createElement('input');
checkbox.type = 'checkbox';
const span = document.createElement('span');
span.textContent = todoinput;
const delBtn = document.createElement('button');
delBtn.className = 'delete-button';
delBtn.textContent = '削除';
delBtn.addEventListener('click', () => {
li.remove();
});
checkbox.addEventListener('change', () => {
span.style.textDecoration = checkbox.checked ? 'line-through' : 'none';
});
li.appendChild(checkbox);
li.appendChild(span);
li.appendChild(delBtn);
todolist.appendChild(li);
//フォームの中を消す
form.reset();
textInput.focus();
}
3. チェックボックス(完了)機能
要件
- チェックボックスにチェック → 取り消し線
- 外す → 取り消し線が消える
まとめ(Conclusion)
- 最初は console.logで入力値が取れるか確認してから、UI追加へ進むと迷いにくい
-
each的にその場で処理を書くより、**関数化(handleClick)**すると管理しやすい - タスクごとに増える要素(削除ボタン等)は idではなくclass を使う
- 取り消し線は
checkbox.checkedを見て切り替えるとシンプル - 小さなtypo(
adddなど)でも動かないので、まずそこを疑うの大事