My WebDev Notes: A simple TO-DO List application
Tags: html, css, javascript
Published: 2020-04-18 17:55:08

---
title: My WebDev Notes: A simple TO-DO List application
published: true
description: A detailed experiment on creating a simple to-do list application using HTML, CSS, and JavaScript
tags: html, css, javascript
series: My WebDev Notes
---
> <b>Check the application is online: https://ziizium.github.io/my-webdev-notes/todoapp/</b>

We all keep a list of things we'll like to do in the future and conventionally we use pen and paper. Then as technology advances, we use mobile and online applications to keep track of our daily activities.

A _to-do_ list application is a mobile or an online application that allows us to keep track of our activities. There are many _to-do_ list applications online, this experiment is about creating a minimalist _to-do_ list application using HTML, CSS, and JavaScript, and with one addition: __dark mode__.

##__The HTML__

The HTML code consist of `noscript` tag with information that is displayed to users with JavaScript turned off or disabled in their browser. 

The `header` tags consist of the _toggle switch_ used for switching to _night mode_

Then in the `main` tag, we have the _form instruction_, the _form_ itself, the _un-ordered list_ that will contain the generated `li` tags which in turn will contain the names of each _to-do item_.

Then at the bottom of the page, we link to two separate files `polyfill.js` and `tasklist.js`

```html
<body id="body">

	<noscript> <!-- Shown to browsers with JavaScript disabled -->
		<p style="padding: 0.5em; text-align: center; font-size: 1.2em;">This application works best with JavaScript enabled in your browser.</p>
	</noscript>

	<header class="header" id="header">
		<div class="header__inner">
			<h2><a href="index.html">To Do List</a></h2>
			<form>
				<label class="changeTheme" id="changeTheme-js">
					<input type="checkbox" id="changeTheme" class="changeTheme__input">
					<div class="changeTheme__slider round"></div>
				</label>
			</form>
		</div>
	</header>

	<main>

		<div class="row">

			<div class="form-instruction" id="form-instruction">
				<em>The following are allowed: letters, numbers, commas, apostrophes, hyphens, question marks, and spaces</em>
			</div>

			<form class="taskForm">
				<label for="taskForm__input" class="taskForm__label visuallyHidden">Enter TO DO</label>
				<input type="text" id="taskForm__input" placeholder="Enter your task name" class="taskForm__input">
				<input id="taskForm__submitInput" type="submit" name="addTask" value="Add Task" class="taskForm__submitInput">
			</form>

		</div>

		<!-- The tasks will be list items in an un-ordered list-->
		<ul id="taskList" class="taskList"></ul>

	</main>

	<!-- We require a polyfill for the ChildNode.remove() method which is not
	supported in IE -->
	<script src="polyfill.js"></script>

	<script src="tasklist.js"></script>
```

##__The CSS__

The CSS used in styling the application is not explained in detail because it's not the focus of this experiment but you can check styles.css in the GitHub repository.

##__The JavaScript__

JavaScript is the essential part of the application (_excluding the code that's used for switching to dark mode_) therefore, we'll dissect it together.

Tha pseudocode for creating the _to-do_ item is as follows:

* Get the user input
* Verify it's in the right format
* Create the task item

We'll be selecting a lot of HTML elements via their _attributes_ so it is best if we have a single function for doing this instead of typing multiple API methods every time we need one.

```js
let $ = function (selector) {
	return document.querySelector(selector);
};
```

Next, we'll be validating the user input to prevent them from entering unwanted data in the form input. We'll use _regular expression_ for this. The _regular expression_ will only allow _letters_, _numbers_, _spaces_, _hyphens_, _apostrophe_, and _question marks_. You can make the _regular expression_ better and adapt it to your needs.

```js
let validateInput = function (strValue)  {
	var objRegExp = /^[0-9a-zA-z\s\-\.\'\?]+$/; // specify allowed characters
	return objRegExp.test(strValue); // test the string against the specified pattern
};
```

We use the `remove()` method to delete a task when it's no longer needed. There is a tendency that you'll create many _to-do's_ therefore, we create a function that is attached to all _to-do_ items.


```js
let removeParent = function (classname) {
	let div = this.parentElement;
	div.remove();
};
```

Next, we need to get the name of the _to-do_ task via the _form input_ and we'll use this name to create the _to-do_ item.

The _to-do_ item will be created when the user submits the form. All we have to do is check when the user clicks on the _submit_ button then we create the _to-do_ task.

We'll make use of an _anonymous function_ to create the _to-do_ task. Inside the _function_, we perform the following steps:

* Trim white-spaces from the beginning and the end of the input
* Validate the input
* Create a new `li` tag
* Create a new variable named `newTask` and set it to `false`
* If the input validation passes
    - The input is passed to the `createTextNode()` method and assigned to the `newTask` variable
* Else the _form input_ is cleared and we alert the user
* If the `newTask` is not _empty_ and not `false`:
   - The _form input_ is cleared
   - The `li` is appended to the `ul`
   - The _to-do_ task is appended to the `li`
   - Create an element that will be used to delete the task
   - Add a class name to the created element
   - Append this element to the `li`
   - Attach an _event handler_ and set it to `removeParent`
* Prevent the _form_ from submitting

The resulting JavaScript Code:

```js
$('.taskForm').onsubmit =  function() {

	let taskName = $("#taskForm__input").value.trim();
	let validatedData = validateInput(taskName);
	
	let taskItem = document.createElement('li');
	let newTask = false;

	if (validatedData && validatedData !== "") {
		newTask = document.createTextNode(taskName); // create the name of the task
	} else {
		taskForm__input.value = ""; // clear the form input
		alert("Your task name contains invalid characters");
	}

	if (newTask !== "" && newTask !== false) {

		taskForm__input.value = ""; // Clear the form input

		taskList.appendChild(taskItem);

		taskItem.appendChild(newTask);

		let deleteTask = document.createElement("SPAN");

		let deleteIcon = document.createTextNode("\u00D7");

		deleteTask.className = "delete-task";

		deleteTask.appendChild(deleteIcon);

		taskItem.appendChild(deleteTask);

	}

	let getDeleteTask = $("#taskList").getElementsByClassName('delete-task');

	for (let i = 0; i < getDeleteTask.length; i++) {
		getDeleteTask[i].onclick = removeParent;
	}

	// Prevent the form from submitting
	return false;

}
```
When you mark a _to-do_ item as _done_, a little _check mark_ as added before it, a _strike-through_ `text-decoration` is applied to the text and the background color is changed. All this possible thanks to JavaScript. Let's explain how it works.

The JavaScript code has to listen for an _event_, in this case, it will listen for the _click_ event i.e when the user clicks on the _unordered list_ (`ul`) that contains the _to-do_ tasks (`li`). When this happens we write a _function_ that accepts an event as a _parameter_ and ensures that a `li` tag was actually clicked. How can we do this?

Well, events have a `target` attribute associated with it, here the `target` is the HTML `li` tags. The name of `li` tags is available in its capitalized form i.e <code><b>LI</b></code> to the `target` attribute via the `tagName` attribute. 

After checking that the `li` tag was actually clicked, we use the `classList` which has a `toggle` attribute to add the CSS `checked` class to the `li` tag.

```js
// We get the unordered list which contains the list
// items
let taskList = $('#taskList');

// Attach an event
taskList.addEventListener('click', function(event) {
	if (event.target.tagName === 'LI') {
		event.target.classList.toggle('checked')
	}
}, false);
```

Here is the CSS that gets added to the `li` tags:

```css
.taskList li.checked {
	background: #888888;
	color: #ffffff;
	text-decoration: line-through;
}
```

The remaining JavaScript code is for adding _dark mode_ functionality.

The Github repo:

{% github ziizium/my-webdev-notes %}

_Have fun!_