こんにちは。KOUKIです。
皆さんは、日常のTaskを何で管理しているでしょうか?
私は、Todoリストを作って、そこでTaskを管理しています。
そんな訳で、今日はJavaScriptで、Todoリストの作成を行いたいと思います。
完成イメージ

JavaScript記事まとめ(初心者向き)
プロジェクト
まずは、プロジェクトを作成してください。
1 2 3 4 5 6 7 8 9 |
mkdir todolist touch todolist/index.html touch todolist/app.js touch todolist/style.css todolist ├── app.js ├── index.html └── style.css |
ひな形
次は、Todoリスト画面のひな形を作成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<!-- index.html --> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <!-- Font Awesome https://fontawesome.com/start --> <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.1/css/all.css" integrity="sha384-50oBUHEmvpQ+1lW4y57PTFmhCaXp0ML5d60M1M7uH2+nqUivzIebhndOJK28anvf" crossorigin="anonymous"> <!-- Bootstrap https://getbootstrap.com/docs/4.3/getting-started/introduction/ --> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous"> <link rel="stylesheet" href="style.css"> <title>Todo List</title> </head> <body> <script src="app.js"></script> </body> </html> |
このひな形には、次の便利ツールが含まれています。
BootstrapはCSSのフレームワークで、画面のデザインを手軽に行えるようなります。
FontAwesomeは、Webアイコンを手軽に導入できる便利ツールです。
画面の作成
Todoリスト画面の作成を行います。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
<!-- index.html --> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <!-- Font Awesome https://fontawesome.com/start --> <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.1/css/all.css" integrity="sha384-50oBUHEmvpQ+1lW4y57PTFmhCaXp0ML5d60M1M7uH2+nqUivzIebhndOJK28anvf" crossorigin="anonymous"> <!-- Bootstrap https://getbootstrap.com/docs/4.3/getting-started/introduction/ --> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous"> <link rel="stylesheet" href="style.css"> <title>Todo List</title> </head> <body> <div class="container"> <header class="text-center text-light my-4"> <h1 class="mb-4">Todo List</h1> <form class="search"> <input type="text" class="form-control m-auto" name="search" placeholder="Search Keyword"> <i class="fas fa-search"></i><!-- font awesome font--> </form> </header> <ul class="list-group todos mx-auto text-light"> </ul> <form class="add text-center my-4"> <label class="text-light">ADDING TASK</label> <input type="text" class="form-control m-auto" name="add" placeholder="New Task"> </form> </div> <script src="app.js"></script> </body> </html> |
以下の部分がFontAwesomeです。検索アイコンを付与しています。
1 |
<i class="fas fa-search"></i><!-- font awesome font--> |
画面を表示させてみましょう。

Styleの適用
TodoリストにStyleを適用させます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
/* style.css */ body { font-family: New Gulim, 'Times New Roman', Times, serif; background: #2D63B5; } .container { max-width: 400px; } input[type=text], input[type=text]:focus { color: #9abca4; border: none; background: rgba(0, 0, 0, 0.2); max-width: 400px; } .search { position: relative; } .search-icon { position:absolute; top: 10px; right: 20px; } |
画面を表示してみましょう。

Taskの追加機能
次は、JavaScriptで、Taskの追加機能を作成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
// app.js let todoApp = { addTask: document.querySelector('.add'), list: document.querySelector('.todos'), createTodoList: function (task) { // HTML テンプレートを生成 const html = ` <li class="list-group-item d-flex justify-content-between align-items-center"> <span>${task}</span> <i class="far fa-trash-alt delete"></i> </li> `; todoApp.list.innerHTML += html; }, } todoApp.addTask.addEventListener('submit', e => { // デフォルトのイベントを無効 e.preventDefault(); // Taskに入力した値を空白を除外して格納 const task = todoApp.addTask.add.value.trim(); if(task.length) { // Todo List の HTML を作成 todoApp.createTodoList(task); // Taskに入力した文字をクリア todoApp.addTask.reset(); } }); |
画面上で動作確認しましょう。New Taskに適当な文字列を打ち込んでEnterキーを押下してください。

問題なくTaskが追加できたようです。
しかし、追加した要素が白く塗りつぶされているので、スタイルを修正しましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
/* style.css */ body { font-family: New Gulim, 'Times New Roman', Times, serif; background: #2D63B5; } .container { max-width: 400px; } input[type=text], input[type=text]:focus { color: #9abca4; border: none; background: rgba(0, 0, 0, 0.2); max-width: 400px; } .search { position: relative; } .search-icon { position:absolute; top: 10px; right: 20px; } /* 追加 */ .todos li { background: #2c4b79; } /* 追加 */ .delete { cursor: pointer; color: orange; } |

削除機能
Taskの削除機能を実装しましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
// app.js let todoApp = { addTask: document.querySelector('.add'), list: document.querySelector('.todos'), createTodoList: function (task) { // HTML テンプレートを生成 const html = ` <li class="list-group-item d-flex justify-content-between align-items-center"> <span>${task}</span> <i class="far fa-trash-alt delete"></i> </li> `; todoApp.list.innerHTML += html; }, } todoApp.addTask.addEventListener('submit', e => { // デフォルトのイベントを無効 e.preventDefault(); // Taskに入力した値を空白を除外して格納 const task = todoApp.addTask.add.value.trim(); if(task.length) { // Todo List の HTML を作成 todoApp.createTodoList(task); // Taskに入力した文字をクリア todoApp.addTask.reset(); } }); // 削除機能 todoApp.list.addEventListener('click', e => { console.log(e.target.classList); if (e.target.classList.contains('delete')) { e.target.parentElement.remove(); } }); |
画面上で、一度Taskを追加します。

Taskにゴミ箱が付与されるようになりました。
ゴミ箱には「.deleteクラス」を設定しており、クリックイベント時にこのクラスがclassList内に含まれている場合、親要素と一緒に削除するように実装しました。
classListは、要素に設定されているクラスをリストで取得できます。
1 2 3 4 5 6 7 8 9 |
// classListの中身 DOMTokenList(3) ["far", "fa-trash-alt", "delete", value: "far fa-trash-alt delete"] 0: "far" 1: "fa-trash-alt" 2: "delete" length: 3 value: "far fa-trash-alt delete" __proto__: DOMTokenList |
サーチ機能の実装
次に、サーチ機能を実装します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
// app.js let todoApp = { addTask: document.querySelector('.add'), list: document.querySelector('.todos'), search: document.querySelector('.search input'), // new createTodoList: function (task) { // HTML テンプレートを生成 const html = ` <li class="list-group-item d-flex justify-content-between align-items-center"> <span>${task}</span> <i class="far fa-trash-alt delete"></i> </li> `; todoApp.list.innerHTML += html; }, // new filterTasks: function (term) { Array.from(todoApp.list.children) // フィルタ条件 .filter((todo) => !todo.textContent.toLowerCase().includes(term)) .forEach((todo) => todo.classList.add('filtered')); Array.from(todoApp.list.children) .filter((todo) => todo.textContent.toLowerCase().includes(term)) .forEach((todo) => todo.classList.remove('filtered')); } } todoApp.addTask.addEventListener('submit', e => { // デフォルトのイベントを無効 e.preventDefault(); // Taskに入力した値を空白を除外して格納 const task = todoApp.addTask.add.value.trim(); if(task.length) { // Todo List の HTML を作成 todoApp.createTodoList(task); // Taskに入力した文字をクリア todoApp.addTask.reset(); } }); // 削除機能 todoApp.list.addEventListener('click', e => { console.log(e.target.classList); if (e.target.classList.contains('delete')) { e.target.parentElement.remove(); } }); // サーチ機能 new todoApp.search.addEventListener('keyup', () => { console.log('test') // 空白削除かつ、小文字に変換(大文字・小文字の区別をなくす) const term = todoApp.search.value.trim().toLowerCase(); todoApp.filterTasks(term); }); |
スタイルも変更します。
1 2 3 4 5 6 |
/* style.css */ /* 見かけ上削除。実際には消してない */ .filtered { display : none !important; } |
スタイルに設定した「display:none」は、HTML要素に付与すると要素そのものが画面から見えなくなります。
複数のTaskを追加して、動作確認をしてみましょう。

この状態でSearch Keywordに「Java」と打ち込んでください。

Taskを絞り込めましたね。
Task保存機能
追加したTaskは、ブラウザをリロードすると削除されてしまうので、ローカルストレージに保存します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
// app.js let todoApp = { addTask: document.querySelector('.add'), list: document.querySelector('.todos'), search: document.querySelector('.search input'), // ########## 追加 ########### init: function() { // 初期化処理 // ローカルストレージに格納されている値を取得し、リストを生成する for (var key in localStorage) { var html = localStorage.getItem(key); if (html) { todoApp.list.innerHTML += localStorage.getItem(key); } } }, createTodoList: function (task) { // HTML テンプレートを生成 const html = ` <li class="list-group-item d-flex justify-content-between align-items-center"> <span>${task}</span> <i class="far fa-trash-alt delete"></i> </li> `; todoApp.list.innerHTML += html; // ########## 追加 ########### todoApp.saveTaskToLocalStorage(task, html); }, filterTasks: function (term) { Array.from(todoApp.list.children) // フィルタ条件 .filter((todo) => !todo.textContent.toLowerCase().includes(term)) .forEach((todo) => todo.classList.add('filtered')); Array.from(todoApp.list.children) .filter((todo) => todo.textContent.toLowerCase().includes(term)) .forEach((todo) => todo.classList.remove('filtered')); }, // ########## 追加 ########### saveTaskToLocalStorage: function (task, html) { // null は、localStorage に保存しない if (html) { // localStorage は、0 から始まる localStorage.setItem(task, html); return; } return; }, // ########## 追加 ########### deleteTaskFromLocalStorage: function(task) { localStorage.removeItem(task); return; }, } // ########## 追加 ########### todoApp.init(); // イベント todoApp.addTask.addEventListener('submit', e => { // デフォルトのイベントを無効 e.preventDefault(); // Taskに入力した値を空白を除外して格納 const task = todoApp.addTask.add.value.trim(); if(task.length) { // Todo List の HTML を作成 todoApp.createTodoList(task); // ########## 追加 ########### // Taskに入力した文字をクリア todoApp.addTask.reset(); } }); // 削除機能 todoApp.list.addEventListener('click', e => { console.log(e.target.classList); if (e.target.classList.contains('delete')) { e.target.parentElement.remove(); // ########## 追加 ########### const task = e.target.parentElement.textContent.trim() todoApp.deleteTaskFromLocalStorage(task); } }); // サーチ機能 todoApp.search.addEventListener('keyup', () => { // 空白削除かつ、小文字に変換(大文字・小文字の区別をなくす) const term = todoApp.search.value.trim().toLowerCase(); todoApp.filterTasks(term); }); |
これで完成です。Taskを追加後、リロードしてもデータが消えなくなっているはずです。
おわりに
JavaScriptでもそこそこのアプリは作成できますね。
これからもJavaScriptで便利なアプリを作成していきたいと思います。
それでは、また!
関連記事
おすすめ書籍
ちょっと古い書籍ですが、この本がオススメです。
実務でも通用する力が身につきます(下手に優しいJS本よりよい)。
コメントを残す
コメントを投稿するにはログインしてください。