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>