This particular snippet is a simple to-do app that allows the user to add new items to the list, mark them as done, delete a single item, or delete all items.
What I would be looking for advice on are my use of a function constructor. It may be overkill for something like this, but it is more of a learning exercise to become familar with the process. Could the building up of each list item be done in a better way?
On the use of an IIFE, my understanding of these is that it can help self-contain code snippets and ensure they keep their scope. Would this be a good practice going forward, or do they have their best use cases?
If there are other areas of improvement I would welcome input regarding those. Thanks.
(function(){
"use strict"
let form, listArea, formInput, clearList;
// Function constructor
// Will build up each list item
// With associated functions
const Task = function (taskName) {
this.taskName = taskName;
this.buildTask = function () {
let newListItem = document.createElement('li');
newListItem.innerHTML = `<span></span>${this.taskName}<button class="remove-item">Bin It</button>`;
newListItem.querySelector('.remove-item').addEventListener('click', removeItem);
newListItem.querySelector('span').addEventListener('click', markDone);
listArea.appendChild(newListItem);
}
}
function markDone(e) {
e.currentTarget.parentNode.classList.toggle('done');
}
function removeItem(e) {
e.currentTarget.parentNode.remove();
}
function clearAllItems() {
let listAreaItem = listArea.querySelectorAll('li');
listAreaItem.forEach((item) => {
item.remove();
})
}
// On form submit
// Create new instance of Task
function formValidate(e) {
e.preventDefault();
const value = formInput.value
if(!value) {
formInput.dataset.state = 'invalid';
return;
}
// Trim whitespace from the input
const trimValue = formInput.value.trim();
if(trimValue) {
formInput.dataset.state = 'valid';
new Task(trimValue).buildTask();
formInput.value = '';
}
}
function startup() {
form = document.getElementById('form');
listArea = document.getElementById('listArea');
formInput = document.getElementById('addToField');
clearList = document.getElementById('clearList');
// Check for an submit on the form field
form.addEventListener('submit', formValidate);
clearList.addEventListener('click', clearAllItems);
}
window.addEventListener('DOMContentLoaded', startup);
})();
* {
box-sizing: border-box;
}
body,
button,
form input,
form button {
font-family: 'Space Mono', monospace;
}
button {
color: #fff;
border: none;
background: #7e7e7e;
height: 60px;
padding: 0 25px;
}
button:hover,
ul li span:hover {
cursor: pointer;
}
.input-area {
max-width: 600px;
margin-left: auto;
margin-right: auto;
padding: 50px;
}
#form {
display: flex;
}
form input {
border: none;
border-bottom: 2px solid rgba(0,0,0,0.25);
height: 60px;
flex-grow: 1;
font-size: 20px;
}
form input[data-state="invalid"] {
border-color: red;
}
form input[data-state="valid"] {
border-color: green;
}
form button {
height: 60px;
border: 2px solid rgba(0,0,0,0.25);
flex-basis: 175px;
flex-grow: 0;
flex-shrink: 0;
border: none;
color: #fff;
}
ul {
list-style: none;
padding-left: 0;
}
ul li {
display: flex;
line-height: 60px;
background-color: #e3e3e3;
margin: 5px 0;
}
ul li.done {
background-color: limegreen;
}
ul li span {
display: inline-block;
width: 60px;
height: 60px;
background-color: rgba(0,255,0,0.2);
margin-right: 20px;
}
ul li.done span {
background-color: green;
}
ul li button {
height: 60px;
padding: 0 20px;
margin-left: auto;
background-color: #db4646;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>To Do App</title>
<link rel="stylesheet" href="style.css">
<link href="https://fonts.googleapis.com/css2?family=Space+Mono&display=swap" rel="stylesheet">
</head>
<body>
<main>
<div class="input-area">
<h1>Do it.</h1>
<form id="form">
<input id="addToField" type="text">
<button id="submitToList" type="submit">Add to List</button>
</form>
<ul id="listArea"></ul>
<button id="clearList">Clear List</button>
</div>
</main>
</body>
<script src="script-2.js"></script>
</html>