Chapter 13: Building a Real-World Application - The To-Do List
Bringing It All Together: Your First Complete Project
Now, it's time to apply all the JavaScript knowledge and AI prompting techniques you've acquired to construct a complete, functional To-Do List application. This project will integrate concepts from previous chapters, including DOM manipulation, event handling, data structures, and perhaps even local storage for persistence.
<>This chapter will guide you through building a simple web-based To-Do List application step-by-step, using AI to generate the necessary HTML, CSS, and JavaScript code. We will focus on the core functionalities:- Adding new tasks
- Marking tasks as complete
- Deleting tasks
- (Optional) Persisting tasks using Local Storage
Project Setup: HTML and CSS
Every web application starts with its structure (HTML) and presentation (CSS). We'll prompt the AI to create a basic layout for our To-Do List.
Example 1: Basic HTML Structure
Goal:Create the fundamental HTML for a To-Do List application, including an input field for new tasks, an add button, and an unordered list to display tasks.
Prompt:
Generate the basic HTML structure for a simple To-Do List web application. It should include: * A main heading (h1) with the title "My To-Do List" * An input field for new tasks (id="taskInput") * A button to add tasks (id="addTaskBtn") with the text "Add Task" * An empty unordered list (ul) with the id="taskList" where tasks will be displayed.AI-Generated Code (Expected):
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>My To-Do List</title> <link rel="stylesheet" href="style.css"> <!-- Link to our CSS file --> </head> <body> <h1>My To-Do List</h1> <div> <input type="text" id="taskInput" placeholder="Add a new task..."> <button id="addTaskBtn">Add Task</button> </div> <ul id="taskList"</ul> <script src="script.js"></script> <!-- Link to our JavaScript file --> </body> </html>Analysis: The AI provides a clean, semantic HTML structure, including placeholders for our CSS and JavaScript files.
Example 2: Basic CSS Styling
Goal:Add some basic CSS to make the To-Do List visually appealing.
Prompt:
Provide basic CSS for the To-Do List HTML structure. Make the body have a light background, center the main content, style the input field and button, and add some padding to the list items. Also, style completed tasks with a line-through text decoration.AI-Generated Code (Expected):
body { font-family: Arial, sans-serif; background-color: #f4f4f4; display: flex; justify-content: center; align-items: flex-start; / Align to top / min-height: 100vh; margin: 20px; } h1 { text-align: center; color: #333; } div { margin-bottom: 20px; display: flex; gap: 10px; } input[type="text"] { padding: 10px; border: 1px solid #ddd; border-radius: 4px; flex-grow: 1; } button { padding: 10px 15px; background-color: #007bff; color: white; border: none; border-radius: 4px; cursor: pointer; } button:hover { background-color: #0056b3; } ul { list-style: none; padding: 0; width: 100%; max-width: 500px; / Limit width for better readability / } li { background-color: white; padding: 10px 15px; margin-bottom: 8px; border-radius: 4px; display: flex; justify-content: space-between; align-items: center; box-shadow: 0 2px 4px rgba(0,0,0,0.1); } li.completed { text-decoration: line-through; color: #888; background-color: #e9e9e9; } li button { background-color: #dc3545; / Red for delete button / padding: 5px 10px; font-size: 0.8em; } li button:hover { background-color: #c82333; }Analysis: The AI provides well-structured CSS that makes the application look clean and functional, including a class for completed tasks.
Core Functionality: JavaScript
Now for the main logic. We'll prompt the AI to handle adding, completing, and deleting tasks.
Example 3: Adding New Tasks
Goal:Implement the JavaScript to add a new task when the button is clicked.
Prompt:
Write JavaScript code for the To-Do List application. 1. Get references to the taskInput, addTaskBtn, and taskList elements. 2. Add an event listener to addTaskBtn for a 'click' event. 3. Inside the event listener: a. Get the value from taskInput. b. If the input is not empty, create a new li element. c. Set the textContent of the li to the task input value. d. Append the new li to the taskList. e. Clear the taskInput field.AI-Generated Code (Expected):
// script.js const taskInput = document.getElementById("taskInput"); const addTaskBtn = document.getElementById("addTaskBtn"); const taskList = document.getElementById("taskList"); addTaskBtn.addEventListener("click", function() { const taskText = taskInput.value.trim(); // .trim() removes leading/trailing whitespace if (taskText !== "") { const listItem = document.createElement("li"); listItem.textContent = taskText; taskList.appendChild(listItem); taskInput.value = ""; // Clear input field } });Analysis: The AI correctly implements the logic for adding tasks, including trimming whitespace and clearing the input field.
Example 4: Marking Tasks as Complete and Deleting Tasks
Goal:Add functionality to mark tasks as complete and delete them.
Prompt:
Extend the JavaScript for the To-Do List. For each new task (and existing ones if you were to load them): 1. Add a 'click' event listener to each li element. When clicked, toggle the 'completed' CSS class on that li. 2. Add a 'Delete' button inside each li element. 3. Add a 'click' event listener to the 'Delete' button. When clicked, remove the parent li element from the DOM. Modify the task creation logic to include these features.AI-Generated Code (Expected):
// script.js (updated) const taskInput = document.getElementById("taskInput"); const addTaskBtn = document.getElementById("addTaskBtn"); const taskList = document.getElementById("taskList"); function createTaskElement(taskText) { const listItem = document.createElement("li"); listItem.textContent = taskText; // Add click listener to toggle 'completed' class listItem.addEventListener("click", function() { listItem.classList.toggle("completed"); }); // Create Delete button const deleteBtn = document.createElement("button"); deleteBtn.textContent = "Delete"; deleteBtn.addEventListener("click", function(event) { event.stopPropagation(); // Prevent listItem click event from firing listItem.remove(); // Remove the li element }); listItem.appendChild(deleteBtn); return listItem; } addTaskBtn.addEventListener("click", function() { const taskText = taskInput.value.trim(); if (taskText !== "") { const newListItem = createTaskElement(taskText); taskList.appendChild(newListItem); taskInput.value = ""; } });Analysis: The AI refactors the task creation into a separate function, adds the completed class toggling, and includes a functional delete button. The event.stopPropagation() is a crucial detail to prevent unintended behavior.
Example 5 (Optional): Persisting Tasks with Local Storage
Goal:Make the To-Do List tasks persist even after the browser is closed.
Prompt:
Modify the To-Do List JavaScript to save and load tasks from the browser's Local Storage. 1. When a task is added, completed, or deleted, save the current list of tasks to Local Storage. 2. When the page loads, load tasks from Local Storage and display them. Each task should be stored as an object with text and completed properties.AI-Generated Code (Expected):
// script.js (further updated) const taskInput = document.getElementById("taskInput"); const addTaskBtn = document.getElementById("addTaskBtn"); const taskList = document.getElementById("taskList"); // --- Local Storage Functions --- function saveTasks() { const tasks = []; taskList.querySelectorAll("li").forEach(listItem => { tasks.push({ text: listItem.textContent.replace("Delete", "").trim(), // Remove 'Delete' text completed: listItem.classList.contains("completed") }); }); localStorage.setItem("todoTasks", JSON.stringify(tasks)); } function loadTasks() { const storedTasks = localStorage.getItem("todoTasks"); if (storedTasks) { const tasks = JSON.parse(storedTasks); tasks.forEach(task => { const newListItem = createTaskElement(task.text); if (task.completed) { newListItem.classList.add("completed"); } taskList.appendChild(newListItem); }); } } // --- Task Creation and Event Handling --- function createTaskElement(taskData) { const listItem = document.createElement("li"); // Handle if taskData is just text or an object const taskText = typeof taskData === 'object' ? taskData.text : taskData; listItem.textContent = taskText; // Add click listener to toggle 'completed' class listItem.addEventListener("click", function() { listItem.classList.toggle("completed"); saveTasks(); // Save after status change }); // Create Delete button const deleteBtn = document.createElement("button"); deleteBtn.textContent = "Delete"; deleteBtn.addEventListener("click", function(event) { event.stopPropagation(); listItem.remove(); saveTasks(); // Save after deletion }); listItem.appendChild(deleteBtn); return listItem; } addTaskBtn.addEventListener("click", function() { const taskText = taskInput.value.trim(); if (taskText !== "") { const newListItem = createTaskElement(taskText); taskList.appendChild(newListItem); taskInput.value = ""; saveTasks(); // Save after adding new task } }); // Load tasks when the page first loads document.addEventListener("DOMContentLoaded", loadTasks);
- Analysis: This advanced example demonstrates using localStorage to persist data, JSON.stringify() and JSON.parse() for data serialization, and integrating saving/loading into the existing event handlers. It also shows how to handle the EventListener function.