Simple TODO app in javascript

Project Layout

tp-git-lint/
    app.js
    button.js
    index.html
    img/
        img files for button displays

app.js

"use strict";

/**
 * This script manages a task list with favorites functionality.
 */

// Selecting DOM elements
const taskInput = document.querySelector('input.task');
const lists = document.querySelector('.lists');

const favsSection = document.querySelector('.favs');
const favTitle = document.querySelector('.favs h3');
const favs = document.querySelector('.favs ul');
const favsItems = favs.children;

const tasksSection = document.querySelector('.tasks');
const tasksTitle = document.querySelector('.tasks h3');
const tasks = document.querySelector('.tasks ul');
const taskItems = tasks.children;

// Hide favorites section if no favorites
if ( favsItems.length === 0 ) {
  favsSection.style.display = 'none';
}

// Hide tasks section if no tasks
if ( taskItems.length === 0 ) {
  tasksSection.style.display = "none";
}

// Event listener for adding tasks
taskInput.addEventListener('keyup', (e) => {
  if (e.keyCode === 13) {
    let li = document.createElement('li');
    if (taskInput.value === "") {
      alert("Please add a task");
    } else {
      li.textContent = taskInput.value;
      attachButton(li);
      tasks.appendChild(li);
      tasksTitle.style.display = '';
      taskInput.value = '';

      tasksTitle.textContent = "Inbox";
      tasksSection.style.display = "";
    }
  }
});

// Event listener for click events on task/favorites list
lists.addEventListener('click', (event) => {

  const tag = event.target.tagName;
  const basevalue = event.target.className.baseVal;

  const clickArea1 = event.target.parentNode.parentNode.parentNode.parentNode.className;
  const clickArea2 = event.target.parentNode.parentNode.parentNode.parentNode.parentNode.className;
  const clickArea3 = event.target.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode.className;

  // Checking if buttons inside tasks section is clicked
  if ( clickArea1 === 'tasks' || clickArea2 === 'tasks' || clickArea3 === 'tasks' ) {
    if (tag === 'svg') {
      if (basevalue  === 'delete' || basevalue  === 'can' || basevalue  === 'cap' || basevalue  === 'bin') {
        let li = event.target.parentNode.parentNode;
        let ul = li.parentNode;
        ul.removeChild(li);
      } else if ( basevalue === 'fav') {
        let li = event.target.parentNode.parentNode;
        let ul = li.parentNode;
        favsSection.style.display = '';
        favs.appendChild(li);
        favTitle.textContent = "Favorites";
      }

      if ( taskItems.length === 0 ) {
        tasksSection.style.display = "none";
      }

    } else if (tag === 'path') {
      if (basevalue  === 'delete' || basevalue  === 'can' || basevalue  === 'cap' || basevalue  === 'bin') {
        let li = event.target.parentNode.parentNode.parentNode.parentNode;
        let ul = li.parentNode;
        ul.removeChild(li);
      } else if ( basevalue === 'favPath') {
        let li = event.target.parentNode.parentNode.parentNode;
        let ul = li.parentNode;
        favsSection.style.display = '';
        favs.appendChild(li);
        favTitle.textContent = "Favorites";
      }

      if ( taskItems.length === 0 ) {
        tasksSection.style.display = "none";
      }
    }

    // Checking if buttons inside favs section is clicked
  } else if ( clickArea1 === 'favs' || clickArea2 === 'favs' || clickArea3 === 'favs' ) {
    if (tag === 'svg') {
      if (basevalue  === 'delete' || basevalue  === 'can' || basevalue  === 'cap' || basevalue  === 'bin') {
        let li = event.target.parentNode.parentNode;
        let ul = li.parentNode;
        ul.removeChild(li);
      } else if ( basevalue === 'fav') {
        let li = event.target.parentNode.parentNode;
        let ul = li.parentNode;
        tasksSection.style.display = '';
        tasks.appendChild(li);
        tasksTitle.textContent = "Inbox";
      }

      if ( favsItems.length === 0 ) {
        favsSection.style.display = 'none';
      }

    } else if (tag === 'path') {
      if (basevalue  === 'delete' || basevalue  === 'can' || basevalue  === 'cap' || basevalue  === 'bin') {
        let li = event.target.parentNode.parentNode.parentNode.parentNode;
        let ul = li.parentNode;
        ul.removeChild(li);
      } else if ( basevalue === 'favPath') {
        let li = event.target.parentNode.parentNode.parentNode;
        let ul = li.parentNode;
        tasksSection.style.display = '';
        tasks.appendChild(li);
        tasksTitle.textContent = "Inbox";
      }

      if ( favsItems.length === 0 ) {
        favsSection.style.display = 'none';
      }
    }
  }
});

button.js

/**
 * Attaches buttons to a given list item (li) for interaction.
 * @param {HTMLElement} li - The list item to which buttons will be attached.
 */
function attachButton(li) {
  // Creating a container for buttons
  let btns = document.createElement('div');
  btns.className = 'btns';
  li.appendChild(btns);

  // SVG namespace
  const xmlns = "http://www.w3.org/2000/svg";

  // Dimensions for favorite button
  let boxWidth = 36;
  let boxHeight = 36;

  // Creating favorite button
  const favoriteButton = document.createElementNS(xmlns, "svg");
  favoriteButton.setAttributeNS(null, "viewBox", "0 0" + " " + boxWidth + " "+ boxHeight);
  favoriteButton.setAttributeNS(null, "width", boxWidth);
  favoriteButton.setAttributeNS(null, "height", boxHeight);
  favoriteButton.setAttributeNS(null, 'class', "fav");
  favoriteButton.setAttributeNS(null, 'preserveAspectRatio', 'xMidYMid');

  // Creating path for favorite button
  let favPath = document.createElementNS (xmlns, "path");
  favPath.setAttributeNS (null, 'd', "M23 11L18 0l-5 11c-.4.5-1 1-1.6 1L0 13.8l8.3 8.4c.4.5.6 1.2.5 2L6.8 36 17 30.4l1-.3c.4 0 .7.4 1 .6L29 36l-1.8-12c0-.6 0-1.3.5-1.8l8.3-8.4L24.6 12c-.7 0-1.2-.5-1.5-1z");
  favPath.setAttributeNS(null, 'class', "favPath");

  // Appending path to favorite button
  favoriteButton.appendChild(favPath);
  btns.appendChild(favoriteButton);

  // Dimensions for delete button
  boxWidth = 36;
  boxHeight = 24;

  // Creating delete button
  const deleteButton = document.createElementNS(xmlns, "svg");
  deleteButton.setAttributeNS(null, "viewBox", "0 0" + " " + boxWidth + " "+ boxHeight);
  deleteButton.setAttributeNS(null, "width", boxWidth);
  deleteButton.setAttributeNS(null, "height", boxHeight);
  deleteButton.setAttributeNS(null, 'class', "delete");
  deleteButton.setAttributeNS(null, 'preserveAspectRatio', 'xMidYMid');

  // Creating group for delete button
  let bin = document.createElementNS(xmlns, "g");
  bin.setAttributeNS(null, "class", "bin");

  // Creating paths for delete button
  let cap = document.createElementNS (xmlns, "path");
  cap.setAttributeNS(null, "class", "cap");
  cap.setAttributeNS (null, 'd', "M23.7252648,1.75191502 L16.5206374,1.75191502 L16.5206374,0.358408695 C16.5206374,0.160513813 16.3638258,0 16.1703135,0 L8.60470208,0 C8.41127124,0 8.25445962,0.160513813 8.25445962,0.358408695 L8.25445962,1.75183177 L1.04975087,1.75183177 C0.46994661,1.75183177 0,2.23270718 0,2.8258923 L0,6.19992928 L24.7750156,6.19992928 L24.7750156,2.82597555 C24.7750156,2.23279043 24.305069,1.75191502 23.7252648,1.75191502 Z");
  let can = document.createElementNS (xmlns, "path");
  can.setAttributeNS(null, "class", "can");
  can.setAttributeNS (null, 'd', "M3.11525858,32.2713554 C3.15277293,33.1879825 3.89003982,33.911377 4.78664099,33.911377 L20.4035975,33.911377 C21.3001987,33.911377 22.0374655,33.1879825 22.0749799,32.2713554 L23.1902385,8.18462596 L2,8.18462596 L3.11525858,32.2713554 Z M16.1278564,14.1673454 C16.1278564,13.7835442 16.43204,13.4722573 16.8073463,13.4722573 L17.8941233,13.4722573 C18.2691854,13.4722573 18.5736132,13.783461 18.5736132,14.1673454 L18.5736132,27.9286575 C18.5736132,28.3125419 18.2694296,28.6237456 17.8941233,28.6237456 L16.8073463,28.6237456 C16.4322028,28.6237456 16.1278564,28.3127084 16.1278564,27.9286575 L16.1278564,14.1673454 Z M11.3723222,14.1673454 C11.3723222,13.7835442 11.6765059,13.4722573 12.0517308,13.4722573 L13.1385077,13.4722573 C13.5135699,13.4722573 13.8179162,13.783461 13.8179162,14.1673454 L13.8179162,27.9286575 C13.8179162,28.3125419 13.513814,28.6237456 13.1385077,28.6237456 L12.0517308,28.6237456 C11.6765872,28.6237456 11.3723222,28.3127084 11.3723222,27.9286575 L11.3723222,14.1673454 L11.3723222,14.1673454 Z M6.61662529,14.1673454 C6.61662529,13.7835442 6.92080891,13.4722573 7.29603382,13.4722573 L8.38289216,13.4722573 C8.75803569,13.4722573 9.06230069,13.783461 9

index.html

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>ToDo - App by Dhanish Gajjar</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <meta name="apple-mobile-web-app-capable" content="yes">
  <link href="img/apple-touch-icon.png" rel="apple-touch-icon" />
  <link href="img/apple-touch-icon-152x152.png" rel="apple-touch-icon" sizes="152x152" />
  <link href="img/apple-touch-icon-167x167.png" rel="apple-touch-icon" sizes="167x167" />
  <link href="img/apple-touch-icon-180x180.png" rel="apple-touch-icon" sizes="180x180" />
  <link href="img/icon-hires.png" rel="icon" sizes="192x192" />
  <link href="img/icon-normal.png" rel="icon" sizes="128x128" />
  <link href="https://cdnjs.cloudflare.com/ajax/libs/normalize/6.0.0/normalize.min.css" rel="stylesheet">
  <link href="https://fonts.googleapis.com/css?family=Roboto:400,700" rel="stylesheet">
  <link href="style.css" rel="stylesheet">
</head>
<body>
  <div class="wrapper">
    <div class="app">
      <!-- Input field for adding tasks -->
      <input type="text" id="task" placeholder="Add Your Task Here" class="task">
      <!-- Container for lists -->
      <div class="lists">
        <!-- Favorites section -->
        <section class="favs">
          <h3></h3>
          <ul></ul>
        </section>
        <!-- Tasks section -->
        <section class="tasks">
          <h3></h3>
          <ul></ul>
        </section>
        <!-- Done section -->
        <section class="done">
          <h3></h3>
          <ul></ul>
        </section>
      </div>
    </div>
    <!-- Footer section -->
    <footer>
      <p>&copy;2017 Dhanish Gajjar. All Rights Reserved</p>
      <p>Made using HTML, CSS and JavaScript</p>
    </footer>
  </div>
  <!-- Script for attaching buttons to tasks -->
  <script src="buttons.js"></script>
  <!-- Main application script -->
  <script src="app.js"></script>
</body>
</html>

style.css

/**
 * Global styles
 */

* {
  box-sizing: border-box;
}

body {
  font-family: 'Roboto', sans-serif;
  margin: 0;
  padding: 0;
  background: rgb(187, 222, 240);
}

ul {
  list-style: none;
  margin: 0;
  padding: 0;
}

h3 {
  font-size: 1em;
  font-weight: 700;
  color: rgba(0, 0, 0, 0.3);
}

/**
 * Wrapper styles
 */

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

/**
 * App styles
 */

.app {
  margin-top: 2em;
  width: 100%;
}

.app input {
  padding-left: .65em;
  font-size: 1em;
  font-weight: 400;
  color: rgba(0, 0, 0, 0.4);
  width: 100%;
  line-height: 3em;
  border-radius: 0;
  background: none;
  border: none;
  border-bottom: 2px solid rgba(0, 0, 0, 0.1);
}

.app input::placeholder {
  font-weight: 400;
  color: inherit;
}

.app input:focus {
  outline: none;
}

/**
 * Lists styles
 */

.favs,
.tasks,
.favs ul li,
.tasks ul li,
.btns,
footer {
  display: flex;
}

.favs {
  margin-bottom: 1em;
}

.favs,
.tasks {
  margin-top: 1em;
  flex-direction: column;
  text-align: center;
}

.btns {
  flex-direction: row;
  margin-right: -18px;
}

ul li {
  color: #666;
  font-size: 1em;
  font-weight: 400;
  background: white;
  padding: .75em 1.2em;
  border-radius: .3em;
  margin: .5em 0;
  flex-direction: row;
  justify-content: space-between;
  align-items: center;
  line-height: 1.5;
}

.favs ul li svg,
.tasks ul li svg {
  height: 36px;
  margin-left: 1.2em;
}

.favs .fav {
  fill: #FFD842;
}

.bin {
  fill: tomato;
  transform: scale(0.75);
}

.cap {
  transition: transform 0.2s;
}

.fav {
  fill: lightgray;
  transition: transform 0.2s, fill 0.5s;
  transform: scale(0.75);
}

/**
 * Footer styles
 */

footer {
  flex-direction: column;
  align-items: center;
  margin: 3em 0;
}

footer p {
  margin: 0;
  padding: 0;
  height: 1.5em;
  font-size: .75em;
  color: rgba(0, 0, 0, 0.4);
}

/**
 * Media queries
 */

@media (min-width: 768px) {
  .app input {
    font-size: 1.2em;
  }

  .delete {
    height: 1.2em;
  }

  .favs,
  .tasks {
    text-align: left;
  }

  .favs li,
  .tasks li {
    font-size: 1.25em;
  }

  li svg:hover {
    cursor: pointer;
  }

  .fav,
  .bin {
    transform: scale(0.85);
  }

  .fav:hover {
    transform: scale(0.9);
  }

  .bin:hover .cap {
    transform: rotate(-9deg);
  }
}