PR

【初心者】JavaScriptでTODOリスト作り方【サンプル】

HTML/CSS
この記事にはアフィリエイト広告および広告が含まれています。

JavaScriptでTODOリストを作成しました。

シンプルでサンプル・解説ありなので、初心者のJavaScriptの勉強用に良かったら作成してみてください♪

はじめに

まずはTODOリストの機能を考えます。
今回は以下の機能を持たせて実装しました。

簡単な機能しか実装していませんが、好みに応じてカスタマイズしてみてください。

  • タスクを追加、完了、削除
  • タスクをまとめて削除する

作成のイメージ図がこちらです。

実装内容(フロー)

次に箇条書きで処理フローを記述します。

  1. 変数を設定
  2. タスク追加ボタン押下時:
    1. タスク名の入力値チェック
    2. タスクに必要な要素を追加する
  3. チェックしたタスクを一括削除ボタン押下時:
    1. チェックしたタスクをを削除する
  4. 完了ボタン押下時:
    1. ボタンを押下したタスクを完了
  5. 削除ボタン押下時:
    1. ボタンを押下したタスクを削除
みみねこ
みみねこ

シンプルな機能だけ持たせています。
改善点は色々思い当たりますが、完了状態→タスク未完了状態に戻したりがありますね。

HTML

まずはHTMLを作成していきます。
作成しているのは、大きく以下の3つです。

  1. タイトル(TODOリスト)
  2. タスク名登録・タスク複数削除
  3. タスク一覧(完了・削除ボタン)
<body>
  <div class="wrapper">
    <h1 id="header">TODOリスト</h1>
    <div id="input-wrap">
      <input id="task-name" type="text" placeholder="タスク名を入力してください" />
      <button onclick="addTask()">タスクを追加</button>
      <button class="deleteTask-button" onclick="deleteTask()">チェックしたタスクを削除</button>
    </div>
    <div id="main-wrap">
      <form name="task_form">
        <ul id="todo-list"></ul>
      </form>
    </div>
  </div>
</body>

「タスクを追加」ボタンにクリックイベント”addTask()
「チェックしたタスクを削除」ボタンにクリックイベント”deleteTask()

を設定しています。

CSS

次にCSSでスタイルを決定します。
この辺りは好きなようにカスタマイズをしていただいて良いと思います!
※ 先にreset.cssを読み込んでからスタイルを設定していますので、注意してください。

特に記載するところはありませんが、
61行目「line-through」、87行目「disabled」はJavaScriptで「完了」ボタン押下時のイベントで使用するため、設定してください。

@charset "utf-8";

/*全体*/
.wrapper{
  max-width: 600px;
  margin: 0 auto;
  color: #666;
}
#header {
  text-align: center;
  font-size: 24px;
  width: 100%;
  margin: 1.5rem 0;
}
#main-wrap {
  margin-bottom: 1.5rem;
}

/* 入力 */
#input-wrap {
  margin: 0 auto;
  width: 80%;
}
#input-wrap input{
  width: 40%;
  height: 24px;
  margin-right: 1rem;
}

/* リスト */
#main-wrap {
  text-align: center;
  margin: 0 auto;
  width: 70%;
  min-height: 120px;
  border: 1px solid #aaa;
  border-radius: 4px;
  -webkit-border-radius: 4px;
  -moz-border-radius: 4px;
  -ms-border-radius: 4px;
  -o-border-radius: 4px;
  padding: 0.8rem 2rem;
}

#main-wrap ul {
  padding-inline-start: 0
}

#main-wrap li {
  text-align: left;
  list-style-type: none;
  border-bottom: 1px dashed #aaa;
  padding: 0.8rem 0;
  display: flex;
  line-height: 32px;
}

#main-wrap p {
  width: 60%;
}
#main-wrap p.line-through {
  text-decoration: line-through;
}

/*ボタン*/
button{
  height: 32px;

  cursor: pointer;
  background: #B78D4A;
  color: #fff;
  border: 1px solid #B78D4A;
  border-radius: 4px;
  font-size: 1rem;
  padding: 0.2rem 1.5rem;
  margin-bottom: 0.5rem;
  -webkit-border-radius: 4px;
  -moz-border-radius: 4px;
  -ms-border-radius: 4px;
  -o-border-radius: 4px;
}

button:hover{
  background-color: #D4BB92;
  border-color: #D4BB92;
}
button.disabled {
  background-color: #D4BB92;
  border-color: #D4BB92;
  cursor: not-allowed;
  pointer-events: none;
}

button.deleteTask-button {
  margin-bottom: 1.5rem;
}

.end-button, .delete-button {
  margin-bottom: 0;
  padding: 0.2rem 1rem;
}

.end-button {
  margin-right: 0.4rem;
}

JavaScript

JavaScriptのコードと解説をしていきます。

コード

次項で詳しく解説していますが、コメントでも多少記述しています。
コピペも可能です!

var todoList;
window.onload = function () {
  todoList = document.getElementById('todo-list');
}

// タスク追加
function addTask() {
  var taskName = document.getElementById('task-name');

  // タスク名の入力がなければ処理を終了
  if(taskName.value.Trim() == "") return;

  // liに要素を追加
  var li = document.createElement('li');

  // liにinputを追加
  var input = document.createElement('input');
  input.setAttribute('type', 'checkbox');
  input.setAttribute('name', 'task');
  li.appendChild(input);

  // liにpを追加
  var p = document.createElement('p');
  p.innerHTML = taskName.value;
  li.appendChild(p);

  // liにbuttonを追加
  var endButton = createTaskButton('end-button', '完了');
  li.appendChild(endButton);

  // liにbuttonを追加
  var deleteButton = createTaskButton('delete-button', '削除');
  li.appendChild(deleteButton);

  // ulにliを追加
  todoList.appendChild(li);

  taskName.value = "";

  // イベント処理
  // 完了ボタンクリック
  endButton.addEventListener('click', function(e){
    e.preventDefault();
    this.setAttribute('class', 'end-button disabled');
    this.previousElementSibling.setAttribute('class', 'line-through');
  });
  // 削除ボタンクリック
  deleteButton.addEventListener('click', function(e){
    e.preventDefault();
    todoList.removeChild(this.closest('li'));
  });
}

// チェックしたタスクを一括削除
function deleteTask() {
  var inputList = document.task_form.task;
  for(var i=inputList.length-1;i>=0;i--) {
    if(inputList[i].checked){
      todoList.removeChild(inputList[i].closest('li'));
    }
  }
}

// タスク内にあるボタンを作成
function createTaskButton(className, name) {
  var btn = document.createElement('button');
  btn.setAttribute('class', className);
  btn.innerHTML = name;
  return btn;
}

解説

先述したコードに対して細かく解説していきます!

・グローバル変数の定義・ページ読み込み後、変数にHTML要素を設定

var todoList;
window.onload = function () {
  todoList = document.getElementById('todo-list');
}

ページ読み込み後に<ul>のid’todo-list’を取得し、変数todoListに設定しています。

・タスク追加

function addTask() {
  var taskName = document.getElementById('task-name');

  // タスク名の入力がなければ処理を終了
  if(taskName.value.Trim() == "") return;

  // liに要素を追加
  var li = document.createElement('li');

  // liにinputを追加
  var input = document.createElement('input');
  input.setAttribute('type', 'checkbox');
  input.setAttribute('name', 'task');
  li.appendChild(input);

  // liにpを追加
  var p = document.createElement('p');
  p.innerHTML = taskName.value;
  li.appendChild(p);

  // liにbuttonを追加
  var endButton = createTaskButton('end-button', '完了');
  li.appendChild(endButton);

  // liにbuttonを追加
  var deleteButton = createTaskButton('delete-button', '削除');
  li.appendChild(deleteButton);

  // ulにliを追加
  todoList.appendChild(li);

  taskName.value = "";

  // イベント処理
  // のちほど説明のため省略
}

「タスクを追加」ボタン押下時のイベントを実装します。

var taskName = document.getElementById('task-name');

タスク名を入力する<input>のid’task-name’を取得し、変数taskNameに設定しています。

// タスク名の入力がなければ処理を終了
if(taskName.value.Trim() == "") return;

タスク名の入力値が空であれば処理を終了する。
Trim()は入力値の前後の空白を除きます

// liに要素を追加
var li = document.createElement('li');

// liにinputを追加
var input = document.createElement('input');
input.setAttribute('type', 'checkbox');
input.setAttribute('name', 'task');
li.appendChild(input);

// liにpを追加
var p = document.createElement('p');
p.innerHTML = taskName.value;
li.appendChild(p);

// liにbuttonを追加
var endButton = createTaskButton('end-button', '完了');
li.appendChild(endButton);

// liにbuttonを追加
var deleteButton = createTaskButton('delete-button', '削除');
li.appendChild(deleteButton);

<li>の要素を作成します。<li>の中には以下の要素を作ります。

・チェックボックス
・タスク名
・完了ボタン
・削除ボタン

// ulにliを追加
todoList.appendChild(li);

作成した<li>を<ul>に追加します。

taskName.value = "";

入力欄をリセットするため、空文字(””)を設定します。

・完了ボタンクリック
endButton.addEventListener('click', function(e){
  e.preventDefault();
  this.setAttribute('class', 'end-button disabled');
  this.previousElementSibling.setAttribute('class', 'line-through');
});

各タスクの「完了」ボタンを実装します。

e.preventDefault();

こちらの関数はイベントのデフォルト動作をキャンセルします。

this.setAttribute('class', 'end-button disabled');

end_button[完了ボタン]にclass属性’end-button disabled‘を設定します。
disabledクラスはボタンを非活性するスタイルを設定します。

thisはendButtonを指します。

this.previousElementSibling.setAttribute('class', 'line-through');

タスク名<p>に取消線のクラス‘line-through’を設定します。

previousElementSibling一つ前の要素。endButton[完了ボタン]の一つ前の要素<p>を指します。

・削除ボタンクリック
deleteButton.addEventListener('click', function(e){
  e.preventDefault();
  todoList.removeChild(this.closest('li'));
});

各タスクの「削除」ボタンを実装します。
※ e.preventDefault();は先ほど出てきたので省略

todo_list.removeChild(this.closest('li'));

タスクを削除します。

removeChild():<ul>(todoList)の子要素を削除します。
this.closest(‘li’):クリックしたボタンthis(deleteButton)の直近に存在する親要素、もしくは要素自身を返します。

・チェックしたタスクを一括削除:deleteTask()

function deleteTask() {
  var inputList = document.task_form.task;
  for(var i=inputList.length-1;i>=0;i--) {
    if(inputList[i].checked){
      todoList.removeChild(inputList[i].closest('li'));
    }
  }
}

「チェックしたタスクを削除」ボタン押下時に呼ばれる関数“deleteTask()”を作成します。
チェックしたタスクを一度に削除する処理を行います。

var inputList = document.task_form.task;

<form name=”task_form”>の中の<input name=”task”>を一覧で取得して変数inputListに設定しています。

“task_form”と”task”はname属性で指定した値です。

みみねこ
みみねこ

htmlファイルと見比べながら確認すると分かりやすいです。

// ①
for(var i=inputList.length-1;i>=0;i--) {
  // ②
  if(inputList[i].checked){
    // ③
    todo_list.removeChild(inputList[i].closest('li'));
  }
}

チェックしたタスク<li>を削除していきます。

①for文でinputListを後ろから一つずつ<input>を回し
②if文でチェックボックスでチェックしているか確認
※ チェックされているときはcheckedがtrue
③trueであればリスト(todoList)からliを削除
※ removeChildは「削除ボタンクリック」で開設済み

みみねこ
みみねこ

①で後ろからfor文を回している理由は、回しながらliを削除しているので
添字が変わってしまうことにより、チェックしているタスクが全て削除されなくなるというのを防いでいます。
※ ★このあたりは文章だと分かりずらいので、今後時間があれば図にするかもしれません…。

・タスク内にあるボタンを作成:createTaskButton(class_name, name)

function createTaskButton(className, name) {
  var btn = document.createElement('button');
  btn.setAttribute('class', className);
  btn.innerHTML = name;
  return btn;
}

タスクの「完了」「削除」ボタンを作成する関数です。

var btn = document.createElement('button');

<botton>の要素を作成します。

btn.setAttribute('class', className);
btn.innerHTML = name;

ボタンに属性classを設定、innerHTMLにボタンに表示する内容を設定します。

最後にボタン(要素)を返します。

デモ

こちらがデモページになります。

良かったら試してみてください♪

タイトルとURLをコピーしました