Todo App using JavaScript

Hello, learner today In this blog post, We will be creating a Todo App using JavaScript.  In the past post, we have created many projects one of them is the Typing Test App. Without wasting time Now it is time to create a Todo App.

Todo Lists are the lists that we generally use to plan our day-to-day tasks or list of everything that we have to do in the day, with the most important tasks at the top of the list, and the least important tasks at the bottom. 

As you see in the above output image of the ToDo App. At the top of the Todo app, there is a text input option where you have to input your task of the day. There are 3 different sections first there is the All section Where you will see all the tasks you have written. In the second option, there is pending where it shows the pending task of the day. And at the last, there is a completed section where you can see the completed task from the list of the task

You can modify or delete the task by clicking on the 3 dots on the side of the task you input. You can delete all the tasks at once by clicking on clear all. You can copy all the code from the below section and modify it yourself.

If you’re having difficulty understanding what I’m saying or what thisTodo App using javascript then You can ask me in the comment.

Code ByCoding thai
Language UsedHTML, CSS and JS
ResponsiveYes
External Link / DependenciesNo

There are 3 types of styles to connect CSS with HTML files. Inline CSS, Internal CSS, External CSS. For Inline CSS in this, we have to write the CSS code inside the HTML code using style Attribute elements. For internal CSS we have to use the Style tag in the Head section on HTML File. We have used this Internal CSS in The below section. Last is External CSS for this we have to create another CSS File in the same folder this

Table of Contents

Preview of Todo App

In this preview, we have used internal CSS in the code. In the internal CSS, we have to write the code in the head section using the Style tag. We have to write the code in <Style> CSS code </style> in the Head section in the HTML file. This code is run in Codepen.io

See the Pen Todo App using javascript by Coding thai (@Codingthai) on CodePen.

You might like this

Todo App using javaScript [Source code]

For Creating A Todo App using HTML, CSS, and JSFirst, you have to create Three files (HTML, CSS, and JS) files with the named index.html, style.css, and Script.js in the same folder and you have to link the CSS and JS files to HTML. after that paste the below code, the HTML code in index.html, and paste the CSS code in style.css Again paste the Js code in script.js that’s all after pasting the code.

First, you have to create an HTML file with the named index.html paste the below HTML code on it, and save it. Remember to give a .html extension to the HTML file.

<!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">
    <link rel="stylesheet" href="https://unicons.iconscout.com/release/v4.0.0/css/line.css">
    <link rel="stylesheet" href="style.css">
    <title>Day #15 - ToDo App | AsmrProg</title>
</head>
<body>
    <div class="wrapper">
        <div class="task-input">
            <img src="bars-icon.svg">
            <input type="text" placeholder="Add a new task">
        </div>
        <div class="controls">
            <div class="filters">
                <span id="all" class="active">
                    All
                </span>
                <span id="pending">Pending</span>
                <span id="completed">Completed</span>
            </div>
            <button class="clear-btn">Clear All</button>
        </div>
        <ul class="task-box"></ul>
    </div>
    <script src="index.js"></script>
</body>
</html>

After pasting the HTML code, Now have to create a second CSS file with the named style.css. Paste the below code on it and save it. Again remember to give a .css extension to the CSS file.

@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap');

*{
    margin: 0;
    padding: 0;
    box-sizing: border-box;
    font-family: 'Poppins', sans-serif;
}

body{
    width: 100%;
    height: 100vh;
    overflow: hidden;
    background: #1e293b;
}

::selection{
    color: #fff;
    background: #1e293b;
}

.wrapper{
    max-width: 405px;
    background: #fff;
    margin: 137px auto;
    padding: 28px 0 30px;
    border-radius: 7px;
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
}

.task-input{
    height: 52px;
    padding: 0 25px;
    position: relative;
}

.task-input img{
    top: 50%;
    position: absolute;
    transform: translate(17px, -50%);
}

.task-input input{
    height: 100%;
    width: 100%;
    outline: none;
    font-size: 18px;
    border-radius: 5px;
    padding: 0 20px 0 53px;
    border: 1px solid #999;
}

.task-input input:focus, .task-input input.active{
    padding-left: 52px;
    border: 2px solid #1e293b;
}

.task-input input::placeholder{
    color: #bfbfbf;
}

.controls, li{
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.controls{
    padding: 18px 25px;
    border-bottom: 1px solid #ccc;
}

.filters span{
    margin: 0 8px;
    font-size: 17px;
    color: #444;
    cursor: pointer;
}

.filters span:first-child{
    margin-left: 0;
}

.filters span.active{
    color: #1e293b;
}

.controls .clear-btn{
    border: none;
    opacity: 0.6;
    outline: none;
    color: #fff;
    cursor: pointer;
    font-size: 13px;
    padding: 7px 13px;
    border-radius: 4px;
    background: #1e293b;
    letter-spacing: 0.3px;
    pointer-events: none;
    transition: transform 0.25s ease;
}

.clear-btn.active{
    opacity: 0.9;
    pointer-events: auto;
}

.clear-btn:active{
    transform: scale(0.93);
}

.task-box{
    margin-top: 20px;
    margin-right: 5px;
    padding: 0 20px 10px 25px;
}

.task-box.overflow{
    overflow-y: auto;
    max-height: 300px;
}

.task-box::-webkit-scrollbar{
    width: 5px;
}

.task-box::-webkit-scrollbar-track{
    background: #f1f1f1;
    border-radius: 25px;
}

.task-box::-webkit-scrollbar-thumb{
    background: #e6e6e6;
    border-radius: 25px;
}

.task-box .task{
    list-style: none;
    font-size: 17px;
    margin-bottom: 18px;
    padding-bottom: 16px;
    align-items: flex-start;
    border-bottom: 1px solid #ccc;
}

.task-box .task:last-child{
    margin-bottom: 0;
    border-bottom: 0;
    padding-bottom: 0;
}

.task-box .task label{
    display: flex;
    align-items: flex-start;
}

.task-box label input{
    margin-top: 7px;
    accent-color: #1e293b;
}

.task-box label p{
    user-select: none;
    margin-left: 12px;
    word-wrap: break-word;
}

.task label p.checked{
    text-decoration: line-through;
}

.task-box .settings{
    position: relative;
}

.settings :where(i, li){
    cursor: pointer;
}

.settings .task-menu{
    z-index: 10;
    right: -5px;
    bottom: -65px;
    padding: 5px 0;
    background: #fff;
    position: absolute;
    border-radius: 4px;
    transform: scale(0);
    transform-origin: top right;
    box-shadow: 0 0 6px rgba(0, 0, 0, 0.15);
    transition: transform 0.2s ease;
}

.task-box .task:last-child .task-menu{
    bottom: 0;
    transform-origin: bottom right;
}

.task-box .task:first-child .task-menu{
    bottom: -65px;
    transform-origin: top right;
}

.task-menu.show{
    transform: scale(1);
}

.task-menu li{
    height: 25px;
    font-size: 16px;
    margin-bottom: 2px;
    padding: 17px 15px;
    cursor: pointer;
    justify-content: flex-start;
}

.task-menu li:last-child{
    margin-bottom: 0;
}

.settings li:hover{
    background: #f5f5f5;
}

.settings li i{
    padding-right: 8px;
}

@media (max-width: 400px){
    body{
        padding: 0 10px;
    }

    .wrapper{
        padding: 20px 0;
    }

    .filters span{
        margin: 0 5px;
    }

    .task-input{
        padding: 0 20px;
    }

    .controls{
        padding: 18px 20px;
    }

    .task-box{
        margin-top: 20px;
        margin-right: 5px;
        padding: 0 15px 10px 20px;
    }

    .task label input{
        margin-top: 4px;
    }

}

After pasting the HTML and CSS code, Now have to create a third Javascript file with the named script.js. Paste the below code on it and save it. Again remember to give a .js extension to the javascript file.

const taskInput = document.querySelector(".task-input input"),
    filters = document.querySelectorAll(".filters span"),
    clearAll = document.querySelector(".clear-btn"),
    taskBox = document.querySelector(".task-box");

let editId,
    isEditTask = false,
    todos = JSON.parse(localStorage.getItem("todo-list"));

filters.forEach(btn => {
    btn.addEventListener("click", () => {
        document.querySelector("span.active").classList.remove("active");
        btn.classList.add("active");
        showTodo(btn.id);
    });
});

function showTodo(filter) {
    let liTag = "";
    if (todos) {
        todos.forEach((todo, id) => {
            let completed = todo.status == "completed" ? "checked" : "";
            if (filter == todo.status || filter == "all") {
                liTag += `<li class="task">
                    <label for="${id}">
                        <input onclick="updateStatus(this)" type="checkbox" id="${id}" ${completed}>
                        <p class="${completed}">${todo.name}</p>
                    </label>
                    <div class="settings">
                        <i onclick="showMenu(this)" class="uil uil-ellipsis-h"></i>
                        <ul class="task-menu">
                            <li onclick='editTask(${id}, "${todo.name}")'><i class="uil uil-pen"></i>Edit</li>
                            <li onclick='deleteTask(${id}, "${filter}")'><i class="uil uil-trash"></i>Delete</li>
                        </ul>
                    </div>
                </li>`;
            }
        });
    }

    taskBox.innerHTML = liTag || `<span>You don't have any task here</span>`;
    let checkTask = taskBox.querySelectorAll(".task");
    !checkTask.length ? clearAll.classList.remove("active") : clearAll.classList.add("active");
    taskBox.offsetHeight >= 300 ? taskBox.classList.add("overflow") : taskBox.classList.remove("overflow");

}
showTodo("all");

//i have added a task before tutorial so that shows here for test
// if you don't have any tasks no problem it isn't bug

function showMenu(selectedTask) {
    let menuDiv = selectedTask.parentElement.lastElementChild;
    menuDiv.classList.add("show");
    document.addEventListener("click", e => {
        if (e.target.tagName != "I" || e.target != selectedTask) {
            menuDiv.classList.remove("show");
        }
    });
}

function updateStatus(selectedTask) {
    let taskName = selectedTask.parentElement.lastElementChild;
    if (selectedTask.checked) {
        taskName.classList.add("checked");
        todos[selectedTask.id].status = "completed";
    } else {
        taskName.classList.remove("checked");
        todos[selectedTask.id].status = "pending";
    }
    localStorage.setItem("todo-list", JSON.stringify(todos))
}

function editTask(taskId, textName) {
    editId = taskId;
    isEditTask = true;
    taskInput.value = textName;
    taskInput.focus();
    taskInput.classList.add("active");
}

function deleteTask(deleteId, filter) {
    isEditTask = false;
    todos.splice(deleteId, 1);
    localStorage.setItem("todo-list", JSON.stringify(todos));
    showTodo(filter);
}

clearAll.addEventListener("click", () => {
    isEditTask = false;
    todos.splice(0, todos.length);
    localStorage.setItem("todo-list", JSON.stringify(todos));
    showTodo();
});

taskInput.addEventListener("keyup", e => {
    let userTask = taskInput.value.trim();
    if (e.key == "Enter" && userTask) {
        if (!isEditTask) {
            todos = !todos ? [] : todos;
            let taskInfo = { name: userTask, status: "pending" };
            todos.push(taskInfo);
        } else {
            isEditTask = false;
            todos[editId].name = userTask;
        }
        taskInput.value = "";
        localStorage.setItem("todo-list", JSON.stringify(todos));
        showTodo(document.querySelector("span.active").id);
    }
});

That’s all after pasting the code your code will be successfully run. If you get any kind of error/problem in the code just comment or contact me on social media

Output Result

Written By@narendra-chand
Code By Coding thai
Code idea@AsmrProg

Leave a Comment