Joanna Joanna - 27 days ago 19
Javascript Question

To Do List with priorities in JavaScript

I am working on a T- Do list in JavaScript. It adds a new task to the list with delete and complete buttons. When the complete button is clicked, the task will be marked in red. There is also a tasks counter on the top and a remove all tasks button on the bottom. All of these features work fine. But I would like the tasks to be added based on the priority given. Priority should be an integer between 1 and 10, where 10 is top priority and 1 is least. Unfortunately, the code I wrote for that part doesn't seem to be working. I added a new variable called index that stores info where the new item should be added. Can you help me find out which part of the code has to be changed? Here it is:

document.addEventListener("DOMContentLoaded", function () {
var add = document.getElementById("addTaskButton");
var removeFinished = document.getElementById("removeFinishedTasksButton");
var task = document.getElementById("taskInput");
var list = document.getElementById("taskList");
var body = document.querySelector("body");
var prior = document.getElementById("taskPriority");

//To do counter
var toDo = document.createElement("span");
body.insertBefore(toDo, list);
var allTasks = document.querySelectorAll("li");
var counter = allTasks.length;
toDo.innerHTML = "Tasks to do: " + counter;
//Add task
add.addEventListener("click", function () {
if (task.value.length >= 5 &&
task.value.length <= 100 &&
prior.value > 0 &&
prior.value <= 10) {

//Add task to the list
var newTask = document.createElement("li");
newTask.dataset.priority = prior.value;
var all = document.querySelectorAll("li");

for (var i = 0; i < all.length; i++) {
var index = all.length;
if (parseInt(newTask.dataset.priority) < parseInt(all[i].dataset.priority)) {
index = i;
break;
}
}

list.insertBefore(newTask, list[index]);

var taskName = document.createElement("h1");
newTask.appendChild(taskName);
taskName.innerHTML = task.value;

//Add delete button
var delBtn = document.createElement("button");
newTask.appendChild(delBtn);
delBtn.innerHTML = "Delete";
delBtn.classList.add("delete");

//Add complete button
var complBtn = document.createElement("button");
newTask.appendChild(complBtn);
complBtn.innerHTML = "Complete";
complBtn.classList.add("complete");

counter++;
toDo.innerHTML = "Tasks to do: " + counter;

//Mark completed in red and adjust counter
complBtn.addEventListener("click", function () {
if (this.parentElement.style.color === "") {
this.parentElement.style.color = "red";
this.parentElement.setAttribute("done", "yes");
counter--;
toDo.innerHTML = "Tasks to do: " + counter;
} else if (this.parentElement.style.color === "red") {
this.parentElement.style.color = "";
this.parentElement.removeAttribute("done");
counter++;
toDo.innerHTML = "Tasks to do: " + counter;
}
});

//Delete selected item and adjust counter
delBtn.addEventListener("click", function () {
this.parentElement.parentNode.removeChild(this.parentElement);
counter--;
toDo.innerHTML = "Tasks to do: " + counter;
});

task.value = "";
prior.value = "";

} else {
event.preventDefault();
alert("Task should have from 5 to 100 characters. Priority should be an integer between 1 and 10");
}
});

//Remove completed items
removeFinished.addEventListener("click", function () {
var tasks = document.querySelectorAll("li");
for (var i = 0; i < tasks.length; i++) {
if (tasks[i].hasAttribute("done")) {
tasks[i].parentNode.removeChild(tasks[i]);
}
}
});

});


And here is the HTML:

<body>

<input id="taskInput" placeholder="Place your task here"><br>
<input id="taskPriority" placeholder="Place task priority (1-10)"><br>
<button id="addTaskButton">Add task</button>

<ul id="taskList">

</ul>

<button id="removeFinishedTasksButton">Remove finished tasks</button>

</body>

Answer

First thing is that "index" was being declared inside a loop so it could not be used outside of it. You need to declare "index" and the default value for "index" outisde of the loop for your function to work.

Second thing was that the value for list was never getting updating after the document was loaded for the first time. You need to use the "all" array to find the proper element to insert before, not "list". "list" was assigned outside of your event handler so it did not have fresh data, also it is not a collection of li elements which is what you needed in this case.

document.addEventListener("DOMContentLoaded", function () {
     var add = document.getElementById("addTaskButton");
     var removeFinished = document.getElementById("removeFinishedTasksButton");
     var task = document.getElementById("taskInput");
     var list = document.getElementById("taskList");
     var body = document.querySelector("body");
     var prior = document.getElementById("taskPriority");

     //To do counter
     var toDo = document.createElement("span");
     body.insertBefore(toDo, list);
     var allTasks = document.querySelectorAll("li");
     var counter = allTasks.length;
     toDo.innerHTML = "Tasks to do: " + counter;
     //Add task
     add.addEventListener("click", function () {
         if (task.value.length >= 5 &&
         task.value.length <= 100 &&
         prior.value > 0 &&
         prior.value <= 10) {

     //Add task to the list

        var newTask = document.createElement("li");
        newTask.dataset.priority = prior.value;
        var all = document.querySelectorAll("li");
        var index = all.length;
        
        for (var i = 0; i < all.length; i++) {
            if (parseInt(newTask.dataset.priority) < parseInt(all[i].dataset.priority)) {
                index = i;
                break;
            }
        }

        list.insertBefore(newTask, all[index]);
        var taskName = document.createElement("h1");
        newTask.appendChild(taskName);
        taskName.innerHTML = task.value;

        //Add delete button
        var delBtn = document.createElement("button");
        newTask.appendChild(delBtn);
        delBtn.innerHTML = "Delete";
        delBtn.classList.add("delete");

        //Add complete button
        var complBtn = document.createElement("button");
        newTask.appendChild(complBtn);
        complBtn.innerHTML = "Complete";
        complBtn.classList.add("complete");

        counter++;
        toDo.innerHTML = "Tasks to do: " + counter;

        //Mark completed in red and adjust counter
        complBtn.addEventListener("click", function () {
            if (this.parentElement.style.color === "") {
                this.parentElement.style.color = "red";
                this.parentElement.setAttribute("done", "yes");
                counter--;
                toDo.innerHTML = "Tasks to do: " + counter;
            } else if (this.parentElement.style.color === "red") {
                this.parentElement.style.color = "";
                this.parentElement.removeAttribute("done");
                counter++;
                toDo.innerHTML = "Tasks to do: " + counter;
            }
        });

        //Delete selected item and adjust counter
        delBtn.addEventListener("click", function () {
            this.parentElement.parentNode.removeChild(this.parentElement);
            counter--;
            toDo.innerHTML = "Tasks to do: " + counter;
        });

        task.value = "";
        prior.value = "";
         
    } else {

        event.preventDefault();
        alert("Task should have from 5 to 100 characters. Priority should be an integer between 1 and 10");
    }
});
  
//Remove completed items
removeFinished.addEventListener("click", function () {
    var tasks = document.querySelectorAll("li");
    for (var i = 0; i < tasks.length; i++) {
        if (tasks[i].hasAttribute("done")) {
            tasks[i].parentNode.removeChild(tasks[i]);
        }
    }
});

});
<body>

    <input id="taskInput" placeholder="Place your task here"><br>
    <input id="taskPriority" placeholder="Place task priority (1-10)"><br>
    <button id="addTaskButton">Add task</button>

    <ul id="taskList">

    </ul>

    <button id="removeFinishedTasksButton">Remove finished tasks</button>

 </body>

Comments