2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

JavaScriptでToDoListを作ってみた

Last updated at Posted at 2021-03-23

JavaScript勉強の一環として,「ToDoList」を作ってみました。
classを勉強したばかりなので使ってみました。
完全独学なので,もし問題点や改善点があれば教えていただけると嬉しいです。

#仕様

  • addボタンを押すと,インプットエリアに入力されたテキストがリストになって追加される。
  • 追加すると,インプットエリアの文字は消える。
  • リスト右の丸を押すと,完了済になる(丸の色と文字色が変わる)。
  • delateを押すと,リストがまるごと削除される。

todoリスト画面.png

#コード

####HTML

index.html
<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <meta http-equiv="X-UA-Compatible" content="IE=edge">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <title>To Do List</title>
   <link rel="stylesheet" href="styles/style.css">
</head>
<body>
   <div class="main-container">
      <div class="wrapper">
         <div class="title">TO DO LIST</div>
         <form class="form">
            <input class="form__text" type="text" name="text" id="form-text" size="30">
            <input class="form__add-btn" type="button" value="add" id="add-btn">
         </form>
         <div class="todo-lists">
            <ul id="ul"> 
               <!-- 追加されるliのhtml構造
                  <li class="list">
                     <div class="list__check"></div>
                     <p class="list__text">インプットエリアに入力されたテキスト</p>
                     <button type="button" class="list__delate">delate</button>
                  </li>
               -->
            </ul>
         </div>
      </div>
   </div>
   <script src="scripts/main.js"></script>
</body>
</html>

####CSS(SCSS)
今回は特に重要ではないと思うので,折り畳んでおきます。

CSS(SCSS)コード
styles/style.scss

$cBlack: #404040;
$cGray: #9d9d9d;
$cLightBlue: #9dcbd3;
$cRed: #ff533c;
$cWhite: #ffffff;

* {
   margin: 0 auto;
}

body {
   background-color: $cLightBlue;
}

.main-container {
   width: 90vw;
   height: auto;
   max-width: 1000px;
   min-height: 90vh;
   margin: 30px auto;
   padding-bottom: 30px;
   background-color: $cWhite;
   border-radius: 30px;
   box-shadow: 0px 2px 7px 0px rgba(0, 0, 0, 0.2);
}

.wrapper {
   width: 80%;
   margin: 0 auto;
}

.title {
   padding: 30px 0;
   color: $cBlack;
   font-size: 40px;
   font-weight: 700;
   text-align: center;
}

.form {
   width: 100%;
   display: flex;
   flex-direction: column;

   &__text {
      outline: none;
      box-sizing: border-box;
      width: 100%;
      height: 45px;
      margin-bottom: 20px;
      padding: 0 15px;
      border: solid 1px $cGray;
      border-radius: 10px;
      font-size: 18px;
      color: $cBlack;
      cursor: text;
      box-shadow: 0px 2px 7px 0px rgba(0, 0, 0, 0.2);
   }
   &__add-btn {
      outline: none;
      border: none;
      width: 100%;
      height: 45px;
      padding: 0;
      margin: 0;
      background-color: $cRed;
      border-radius: 10px;
      font-size: 20px;
      color: $cWhite;
      cursor: pointer;
      box-shadow: 0px 2px 7px 0px rgba(0, 0, 0, 0.2);
   }
}

.todo-lists {
   width: 100%;
   margin-top: 40px;

   & > ul {
      list-style: none;
      padding: 0;
   }
}

.list {
   display: flex;
   align-items: center;
   padding: 15px 10px;
   box-sizing: border-box;
   border-bottom: solid 1px $cGray;

   &__check {
      flex-grow: 0;
      display: inline-block;
      width: 16px;
      height: 16px;
      background-color: $cWhite;
      margin-right: 15px;
      border: solid 1px $cGray;
      border-radius: 50%;
      transition: background-color 0.2s;
      cursor: pointer;

      &:hover {
         background-color: $cRed;
      }
   }
   &__text {
      flex-grow: 1;
      font-size: 18px;
      color: $cBlack;
   }
   &__delate {
      flex-grow: 0;
      font-size: 13px;
      color: $cGray;
      font-weight: 600;
      border: none;
      outline: none;
      cursor: pointer;
      background-color: $cWhite;
      transition: all 0.2s;

      &:hover {
         color: $cBlack;
         transform: scale(1.1);
      }
   }
   &.done {
      & .list__check {
         background-color: $cRed;
      }
      & .list__text {
         color: $cGray;
      }
   }
}

@media(min-width: 768px) {
   .title {
      font-size: 44px;
   }
   .form {
      flex-direction: row;
      justify-content: space-between;

      &__text {
         height: 60px;
         width: calc(100% - 150px);
         margin: 0;
         font-size: 24px;
      }
      &__add-btn {
         height: 60px;
         width: 100px;
         font-size: 26px;
      }
   }

   .list {
      &__check {
         width: 20px;
         height: 20px;
      }
      &__text {
         font-size: 24px;
      }
      &__delate {
         font-size: 20px;
      }
   }
   
}

@media(min-width: 1000px) {
   .wrapper {
      width: 70%;
   }
   .title {
      padding: 40px 0;
      font-size: 64px;
   }
   .list {
      &__check {
         width: 27px;
         height: 27px;
      }
   }
}

####Java Script

scripts/main.js
document.addEventListener('DOMContentLoaded', function() {
   const ul = document.getElementById('ul');
   const addBtn = document.getElementById('add-btn');
   
   addBtn.addEventListener('click', function() {
      const todo = new ToDoList(ul);
   });
});

class ToDoList {
   constructor(ul) {
      this.ul = ul;
      const li = document.createElement('li');
      const check = document.createElement('div');
      const text = document.createElement('p');
      const button = document.createElement('button');
      this.li = li;
      this.check = check;
      this.text = text;
      this.delBtn = button;
      this._setAttr(this._getValue());
      this._addEl(this.ul);
      this._ListEvents();
   }
   _getValue() {
      this.formText = document.getElementById('form-text');
      return this.formText.value;
   }
   _setAttr(txt) {
      this.li.classList.add('list');
      this.check.classList.add('list__check');
      this.text.classList.add('list__text');
      this.text.textContent = txt;
      this.delBtn.classList.add('list__delate');
      this.delBtn.type = 'button';
      this.delBtn.textContent = 'delate';
   }
   _addEl(ul) {
      this.li.appendChild(this.check);
      this.li.appendChild(this.text);
      this.li.appendChild(this.delBtn);
      ul.appendChild(this.li);
      this.formText.value = '';
   }
   _ListEvents() {
      this.delBtn.addEventListener('click', function() {
         this.parentElement.remove();
      });
      this.check.addEventListener('click', function() {
         this.parentElement.classList.add('done');
      });
   }
}

#解説

scripts/main.js
document.addEventListener('DOMContentLoaded', function() {
   const ul = document.getElementById('ul');
   const addBtn = document.getElementById('add-btn');
   
   addBtn.addEventListener('click', function() {
      const todo = new ToDoList(ul);
   });
});

挿入したいulの取得。
addボタン#add-btnの取得。
addボタンが押されたら,ToDoListをインスタンス化し処理を実行する。

scripts/main.js
_getValue() {
      this.formText = document.getElementById('form-text');
      return this.formText.value;
}

インプットエリア#form-textに入力されたテキストを取得する関数。
取得したテキストを_setAttr();で使うため,returnで返す。

scripts/main.js
constructor(){
//
      this._setAttr(this._getValue());
//
}
 
_setAttr(txt) {
      this.li.classList.add('list');
      this.check.classList.add('list__check');
      this.text.classList.add('list__text');
      this.text.textContent = txt;
      this.delBtn.classList.add('list__delate');
      this.delBtn.type = 'button';
      this.delBtn.textContent = 'delate';
}

各要素に属性等を付ける関数。
引数txt_getValue()の結果を渡すことで,入力されたテキストを取得し代入出来る様に。

scripts/main.js
constructor(){
//
      this._addEl(this.ul);
//
}
 _addEl(ul) {
      this.li.appendChild(this.check);
      this.li.appendChild(this.text);
      this.li.appendChild(this.delBtn);
      ul.appendChild(this.li);
      this.formText.value = '';
}

HTMLを組み立て,ulに挿入する関数。
最後にインプットエリアの中を空にする。

scripts/main.js
_ListEvents() {
      this.delBtn.addEventListener('click', function() {
         this.parentElement.remove();
      });
      this.check.addEventListener('click', function() {
         this.parentElement.classList.add('done');
      });
}

delateをclickされた時と,リスト右の丸をclickされた時の処理をまとめた関数。

delateがclickされた時→押されたdelateの親要素を削除。
丸をclickされた時→classにdoneを追加し表示を変える。

#反省点,改善点

  • インプットエリアが空でもリストが作成出来てしまう。(文字数制限が出来ていない。)
  • インプットエリアにテキストを入力しそのままenterを押すと,それまでのリストも含めて全部どこかに飛んで消えてしまう。

分かり次第更新したいと思います。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?