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:
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:
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:
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:
Now, it's your turn to customize and enhance this interactive to-do list! Happy coding! 😃🎉