TIL 01|vanillatodoコメント

81925 ワード

Project Overview


todo-list page
todo-list gitHub
ライブラリを使用せずにjavascript言語でプログラミングしたいので、2つのリストを選択しました.
勤務期間
2021.06.28 ~ 2021.07.05
テクノロジースタック
  • HTML/CSS
  • JavaScript(ES6+)
  • Git
  • 実施内容
  • ユーザー登録作業の場合、登録するには少なくとも1文字以上入力する必要があります.
  • に登録されたジョブは、各ジョブを変更または削除できる保留中のリストに表示されます.
  • 登録の件はチェックボックスを押すと完了リストに移動します.
  • で完了したリストの日付は、削除するリストにのみ削除または移動できます.
  • 結果画面


    登録保留事項

    削除

    保留中の事項を修正する

    リストの移動

    Project Review


    JavaScriptはリアルタイムでレンダリングされません。


    JAvascriptはreactのようにスクリーンの変化をリアルタイムでレンダリングしないため、個別にレンダリングする関数を実現する必要があります.
    // render
    const renderTodo = () => {
      let reverse, item, join;
    
      reverse = [...todoList];
      item = reverse.filter(incomplete);
      join = item.map(incompleteTemplate).join('');
      INCOMPLETE.innerHTML = join;
      
      reverse = [...completedList];
      item = reverse.filter(completed);
      join = item.map(completedTemplate).join('');
      COMPLETED.innerHTML = join;
    };

    Node.insertBefore()

    appendChild()と似ているように見えますが、inrestBefore()には2つの伝達因子があります.最初の伝達パラメータnewNodeは挿入するノードであり、2番目の伝達パラメータreferenceNodeは基点ノードである.
    let insertedNode = parentNode.insertBefore(newNode, referenceNode);

    に感銘を与える


  • やるべきことを入力してEnterを押すと登録できるのですが、残念ながら最初から思っていませんでした.

  • 文字から見ると、私はコードを書く過程であまり適切ではないコード部分を使ったので、理解が速いです.例えば、func.bind()node.insertBefore()などである.

  • 石橋も叩いたからといって、コードが完成したからといって油断しないで、再設計して研究しなければならない.
  • HTML Code

    <!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>vanilla todo</title>
      <link rel="stylesheet" href="css/reset.css">
      <link rel="stylesheet" href="css/style.css">
      <script defer src="js/todo.js"></script>
    </head>
    
    <body>
      <main class="todoContent">
        <header>
          <h1 class="title">todo list</h1>
        </header>
        <!-- add item   -->
        <section>
          <h2>add item</h2>
          <form class="add-form">
            <div>
              <label for="addInput" class="a11y-hidden">할 일 추가</label>
              <input type="text" id="addInput" class="add-input" required />
              <button type="submit" class="add-btn">add</button>
            </div>
          </form>
        </section>
        <!-- // add item  -->
        <!-- todo list   -->
        <section class="todo">
          <h2>todo</h2>
          <ul class="incomplete">
          </ul>
        </section>
        <!-- // todo list   -->
        <!-- completed list    -->
        <section class="todo">
          <h2>completed</h2>
          <ul class="completed">
          </ul>
        </section>
        <!-- completed list   -->
      </main>
    </body>
    
    </html>

    css(rest.css) Code

    @charset "utf-8";
    
    /* margin, padding */
    body, 
    main, 
    div, 
    span,
    section, 
    label,
    input,
    form, 
    button,
    ul,
    h1,
    h2,
    h3,
    p,
    i{
      margin: 0;
      padding: 0;
    }
    
    /* label */
    label{
      background: transparent;
    }
    
    /* input */
    input{
      border: none;
      outline:none;
      background: transparent;
    }
    
    input[type="checkbox"]{
      cursor: pointer;
    }
    
    /* button */
    button{
      border: none;
      outline: none;
      text-transform: capitalize;
      background: transparent;
      cursor: pointer;
    }
    
    /* list */
    ul,
    li{
      list-style:none;
    }
    
    /* title  */
    h1,
    h2,
    h3{
    font-weight: normal;
    text-transform: uppercase;
    }
    
    i {
      font-style: normal;
    }
    
    body, 
    input, 
    button, 
    div,
    label,
    span,
    p, 
    h1,
    h2,
    h3,
    ul, 
    li{
      font-family: 'Roboto Condensed', sans-serif;
      font-size: 1rem;
      line-height: 1.5;
      color: #fff;;
    }
    
    .a11y-hidden {
      overflow: hidden;
      position: absolute;
      width: 1px;
      height: 1px;
      margin: -1px;
      clip: rect(0 0 0 0);
      clip: rect(0, 0, 0, 0);
    }

    css(style.css) Code

    @charset "utf-8";
    
    body {
      overflow: scroll;
      background:#f5f3e9 ;
    }
    
    main{
      width: 28.13rem;
      margin: 6.25rem auto;
      padding: 1.25rem;
      box-shadow: -1.25rem -1.25rem 0px 0px rgb(100 100 100 / 10%);
      background: #98c0b7;
      color: #fff;
    }
    
    h1{
      font-size: 1.667rem;
      text-align: center;
    }
    
    h2{
      font-size: 1.375rem;
      margin-top: 0.625rem;
      border-bottom: 1px solid #fff;
    }
    
    /* add-form */
    .add-form > div{
      display: flex;
      justify-content: space-between;
    }
    
    /* add-form input */
    .add-input{
      width: calc(100% - 70px);
      height: 2.5rem;
      margin: 0.625rem 0;
      padding: 0 0.625rem;
      font-size: 1.667rem;
      line-height: 2.5rem;
      background: #fff;
      color: black;
    }
    
    /* add-form button */
    .add-btn{
      font-size: 1.25rem;
    }
    
    /* todo - ul li */
    .todo ul li{
      display: flex;
      justify-content: space-between;
      border-bottom: 1px solid #a2cec4;
    }
    
    /* todo - ul li checkbox  */
    .todo li input[type="checkbox"]{
      width: 1rem;
      height: 1rem;
      margin: 0.8125rem 0.625rem 0 0;
      line-height: 1rem;
    }
    
    /* todo -ul.incomple li label */
    .todo .incomplete li label{
      width: calc(100% - 165px);
      margin : 0.5625rem 0;
      height:1.563rem;
      line-height: 1.563rem;
      font-size: 1.5rem;
    }
    
    /*  todo -ul.incomple li input(edit) */
    .todo .incomplete li input[type="text"]{
      width: calc(100% - 165px);
      height: 1.563rem;
      margin: 0.5rem 0;
      border: 1px solid #91d4c5;
      line-height: 1.563rem;
      font-size: 1.5rem;
    }
    
    /* todo -ul.completed li label */
    .todo .completed li label{
      width: calc(100% - 85px);
      height: 1.563rem;
      margin: 0.5625rem  0;
      line-height: 1.563rem;
      font-size: 1.5rem;
    }
    
    /* todo - li butgrop buttons */
    .todo-btngroup button{
      padding: 0 0.625rem 0 0;
      margin: 0.5rem 0.625rem 0 0;
      font-size: 1.25rem;
    }
    
    /* todo - li btngroup saveBtn(edit) */
    .todo-btngroup .save-btn{
      padding: 0;
    }
    
    .todo-btngroup button:last-child{
      padding: 0;
    }

    JavaScript Code

    (() => {
      let todoList = [];
      let completedList = [];
    
      const LOADED_TODOLIST = localStorage.getItem('TODO');
      const COMPLETED_LIST = localStorage.getItem('COMPLETED');
    
      const TODO_CONTENT = document.querySelector('.todoContent');
      const ADD_INPUT = document.querySelector('.add-input');
      const INCOMPLETE = document.querySelector('.incomplete');
      const COMPLETED = document.querySelector('.completed');
    
      // initialize and execute
      const init = () => {
        addEvent();
        loadTodoList();
        loadCompletedList();
        renderTodo();
      };
    
      // loading todoList
      const loadTodoList = () => {
        if (LOADED_TODOLIST !== null) {
          todoList = JSON.parse(LOADED_TODOLIST);
          return todoList;
        }
      };
    
      // loading compltedList
      const loadCompletedList = () => {
        if (COMPLETED_LIST !== null) {
          completedList = JSON.parse(COMPLETED_LIST);
          return completedList;
        }
      };
    
      // event listener
      const addEvent = () => {
        let li, id, index, todo, list, checkbox, item;
        let label, input, save_btn, edit_btn;
    
        TODO_CONTENT.addEventListener('click', (e) => {
          // add button
          if (e.target.className === 'add-btn') {
            addFormSubmit();
    
            // delete button
          } else if (e.target.className === 'delete-btn') {
            li = e.target.parentNode.parentNode;
            id = Number(li.getAttribute('data-id'));
            checkbox = li.querySelector('input[type="checkbox"]').value;
            list = checkbox === 'true' ? [...completedList] : [...todoList];
            index = list.findIndex(matchingID.bind(todo, id));
    
            list.splice(index, 1);
            list = checkbox === 'true' ? (completedList = list) : (todoList = list);
    
            renderTodo();
            saveTodoList();
            saveCompletedList();
            // edit button
          } else if (e.target.className === 'edit-btn') {
            list = [...todoList];
            li = e.target.parentNode.parentNode;
            id = Number(li.getAttribute('data-id'));
            item = todoList.find(matchingID.bind(todo, id));
    
            label = li.querySelector('label');
            label.classList.add('a11y-hidden');
    
            save_btn = li.querySelector('.save-btn');
            save_btn.classList.remove('a11y-hidden');
    
            edit_btn = li.querySelector('.edit-btn');
            edit_btn.classList.add('a11y-hidden');
    
            input = document.createElement('input');
            input.setAttribute('type', 'text');
            input.setAttribute('id', id);
            input.setAttribute('value', item.contents);
    
            li.insertBefore(input, label.nextSibling);
    
            // save button
          } else if (e.target.className === 'save-btn') {
            list = [...todoList];
            li = e.target.parentNode.parentNode;
            id = Number(li.getAttribute('data-id'));
            item = list.find(matchingID.bind(todo, id));
            index = list.findIndex(matchingID.bind(todo, id));
    
            input = li.querySelector('input[type="text"]');
            item.contents = input.value;
    
            save_btn = li.querySelector('.save-btn');
            save_btn.classList.add('a11y-hidden');
    
            edit_btn = li.querySelector('.edit-btn');
            edit_btn.classList.remove('a11y-hidden');
            list.splice(index, 0);
            todoList = list;
    
            saveTodoList();
            renderTodo();
    
            // incomplete if checkbox value is false
          } else if (e.target.type === 'checkbox' && e.target.value === 'false') {
            list = [...todoList];
            id = Number(e.target.id);
            index = list.findIndex(matchingID.bind(todo, id));
            item = list.find(matchingID.bind(todo, id));
    
            item.isCompleted = !item.isCompleted;
            completedList.push(item);
            list.splice(index, 1);
            todoList = list;
    
            renderTodo();
            saveTodoList();
            saveCompletedList();
    
            // complete if checkbox value is true
          } else if (e.target.type === 'checkbox' && e.target.value === 'true') {
            list = [...completedList];
            id = Number(e.target.id);
            index = list.findIndex(matchingID.bind(todo, id));
            item = list.find(matchingID.bind(todo, id));
    
            item.isCompleted = !item.isCompleted;
            todoList.push(item);
            list.splice(index, 1);
            completedList = list;
    
            renderTodo();
            saveTodoList();
            saveCompletedList();
          }
        });
      };
    
      // add item form validation
      const addFormSubmit = () => {
        let VALUE = ADD_INPUT.value;
    
        if (VALUE === '') {
          return false;
        }
    
        ADD_INPUT.value = '';
        addTodoDate(VALUE);
      };
    
      // add an item to the list
      const addTodoDate = (value) => {
        todoList.push({
          id: Math.floor(Math.random() * 999),
          contents: value,
          isCompleted: false,
        });
    
        renderTodo();
        saveTodoList();
      };
    
      // incompleteTemplete
      const incompleteTemplate = (item) => {
        const INCOMPLETE_ITEM = `
        <li data-id=${item.id}>
        <input id=${item.id} type="checkbox" value=${item.isCompleted} />
        <label for=${item.id}>${item.contents}</label>
        <div class="todo-btngroup">
          <button type="button" class="edit-btn">edit</button>
          <button type="button" class="a11y-hidden save-btn">save</button>
          <button type="button" class="delete-btn">delete</button>
        </div>
      </li>
        `;
    
        return INCOMPLETE_ITEM;
      };
    
      const incomplete = (item) => {
        return !item.isCompleted;
      };
    
      // completed template
      const completedTemplate = (item) => {
        const COMPLETED_ITEM = `
        <li data-id=${item.id}>
        <input id=${item.id} type="checkbox" value=${item.isCompleted} />
        <label for=${item.id}>${item.contents}</label>
        <div class="todo-btngroup">
          <button type="button" class="delete-btn">delete</button>
        </div>
      </li>
        `;
        return COMPLETED_ITEM;
      };
    
      const completed = (item) => {
        return item.isCompleted;
      };
    
      // matching item
      const matchingID = (id, item) => {
        return item.id === id;
      };
    
      // render
      const renderTodo = () => {
        let reverse, item, join;
    
        // todoList
        reverse = [...todoList];
        item = reverse.filter(incomplete);
        join = item.map(incompleteTemplate).join('');
        INCOMPLETE.innerHTML = join;
    
        reverse = [...completedList];
        item = reverse.filter(completed);
        join = item.map(completedTemplate).join('');
        COMPLETED.innerHTML = join;
      };
    
      // save to todoList LocalStorage
      const saveTodoList = () => {
        localStorage.setItem('TODO', JSON.stringify(todoList));
      };
    
      // save to completedList LocalStorage
      const saveCompletedList = () => {
        localStorage.setItem('COMPLETED', JSON.stringify(completedList));
      };
    
      init();
    })();