Building an Advanced To-Do List with Drag & Drop, Task Deletion, Completion Toggle, and Dark Mode

Building an Advanced To-Do List with Drag & Drop, Task Deletion, Completion Toggle, and Dark Mode

We’ve built a solid to-do list application, but let’s take it up a notch! 🚀
In this updated version, we are adding:

Task Deletion (Remove tasks with a delete button)
Task Completion Toggle (Mark tasks as completed with a strike-through effect)
Dark Mode (Enhance UI for a better user experience)

Let’s dive into the new features and see how they improve our to-do list.


🛠️ Full Updated Code

Here’s the enhanced to-do list with all the new features:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Advanced To-Do List</title>
<style>
body { font-family: Arial, sans-serif; margin: 30px; background: #ffffff; color: #333; transition: 0.3s; }
.dark-mode { background: #222; color: #fff; }
#todoList { list-style: none; padding: 0; }
#todoList li {
padding: 10px;
margin: 5px;
background: #f0f0f0;
border: 1px solid #ccc;
display: flex;
justify-content: space-between;
align-items: center;
cursor: grab;
transition: 0.3s;
}
.dark-mode #todoList li { background: #444; border-color: #666; }
.dragging { opacity: 0.5; }
.completed { text-decoration: line-through; opacity: 0.6; }
.delete-btn { background: red; color: white; border: none; padding: 5px; cursor: pointer; }
.toggle-dark { background: #333; color: white; border: none; padding: 8px; margin: 10px 0; cursor: pointer; }
</style>
</head>
<body>
<h1>Advanced To-Do List</h1>
<button id="toggleDarkMode" class="toggle-dark">Toggle Dark Mode</button>
<input type="text" id="newTask" placeholder="New Task">
<button id="addTask">Add Task</button>
<ul id="todoList"></ul>

<script>
const todoList = document.getElementById('todoList');
const newTaskInput = document.getElementById('newTask');
const addTaskButton = document.getElementById('addTask');
const toggleDarkModeButton = document.getElementById('toggleDarkMode');

// Retrieve saved tasks or initialize an empty array.
let tasks = JSON.parse(localStorage.getItem('tasks')) || [];

// Render tasks on the page.
function renderTasks() {
todoList.innerHTML = '';
tasks.forEach((task, index) => {
const li = document.createElement('li');
li.textContent = task.text;
li.draggable = true;
li.dataset.index = index;
if (task.completed) li.classList.add('completed');

// Toggle completion on click
li.addEventListener('click', () => {
tasks[index].completed = !tasks[index].completed;
renderTasks();
});

// Drag & Drop Event Listeners
li.addEventListener('dragstart', dragStart);
li.addEventListener('dragover', dragOver);
li.addEventListener('drop', drop);

// Delete Button
const deleteBtn = document.createElement('button');
deleteBtn.textContent = 'X';
deleteBtn.classList.add('delete-btn');
deleteBtn.addEventListener('click', (e) => {
e.stopPropagation(); // Prevents triggering task completion
tasks.splice(index, 1);
renderTasks();
});

li.appendChild(deleteBtn);
todoList.appendChild(li);
});

localStorage.setItem('tasks', JSON.stringify(tasks));
}

// Add a new task
function addTask() {
const taskText = newTaskInput.value.trim();
if (taskText) {
tasks.push({ text: taskText, completed: false });
newTaskInput.value = '';
renderTasks();
}
}
addTaskButton.addEventListener('click', addTask);

// Drag & drop functions
let draggedIndex;
function dragStart(e) {
draggedIndex = e.target.dataset.index;
e.target.classList.add('dragging');
}
function dragOver(e) {
e.preventDefault(); // Necessary to allow dropping.
}
function drop(e) {
e.preventDefault();
const targetIndex = e.target.dataset.index;
if (draggedIndex !== targetIndex) {
// Swap tasks
[tasks[draggedIndex], tasks[targetIndex]] = [tasks[targetIndex], tasks[draggedIndex]];
renderTasks();
}
}

// Toggle Dark Mode
function toggleDarkMode() {
document.body.classList.toggle('dark-mode');
localStorage.setItem('darkMode', document.body.classList.contains('dark-mode'));
}
toggleDarkModeButton.addEventListener('click', toggleDarkMode);

// Load Dark Mode preference
if (JSON.parse(localStorage.getItem('darkMode'))) {
document.body.classList.add('dark-mode');
}

renderTasks();
</script>
</body>
</html>

🎯 New Features Breakdown

Here’s what we added and how each feature works.

1. Task Deletion

Each task now has a small delete button (X) that allows users to remove it from the list.

How it works:

  • A delete button (<button>X</button>) is created for each task.
  • Clicking the button removes the task from the tasks array.
  • The list is re-rendered, and local storage is updated.
const deleteBtn = document.createElement('button');
deleteBtn.textContent = 'X';
deleteBtn.classList.add('delete-btn');
deleteBtn.addEventListener('click', (e) => {
e.stopPropagation(); // Prevents triggering task completion
tasks.splice(index, 1);
renderTasks();
});

2. Task Completion Toggle

Users can now mark tasks as completed by clicking on them.

How it works:

  • Each task has a completed property (boolean).
  • Clicking a task toggles its completed state.
  • The completed task is displayed with a strikethrough effect.
li.addEventListener('click', () => {
tasks[index].completed = !tasks[index].completed;
renderTasks();
});

And in CSS:

.completed {
text-decoration: line-through;
opacity: 0.6;
}

3. Dark Mode Toggle

A dark mode toggle button switches the app’s theme.

How it works:

  • Clicking the “Toggle Dark Mode” button toggles the dark-mode class on <body>.
  • The dark mode preference is saved in local storage.
function toggleDarkMode() {
document.body.classList.toggle('dark-mode');
localStorage.setItem('darkMode', document.body.classList.contains('dark-mode'));
}
toggleDarkModeButton.addEventListener('click', toggleDarkMode);

On page load, dark mode is restored if previously enabled:

if (JSON.parse(localStorage.getItem('darkMode'))) {
document.body.classList.add('dark-mode');
}

💡 Final Thoughts

With these new features, our advanced to-do list is even better! 🚀

🔹 Added task deletion
🔹 Implemented task completion toggle
🔹 Introduced a sleek dark mode

🎯 Next steps? You can:

  • Add animations for smoother drag & drop.
  • Enable due dates for tasks.
  • Sync tasks across devices using a database.

Now, it’s your turn to customize and enhance this interactive to-do list! Happy coding! 😃🎉