Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 89 additions & 0 deletions css/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,95 @@ button {
button:hover {
color: #333;
}

/* Filter Panel */
.filter-panel {
margin: 20px 0;
padding: 10px;
border-bottom: 1px solid #eee;
display: flex;
justify-content: center;
gap: 10px;
}

.filter-btn {
padding: 8px 16px;
border: 1px solid #ddd;
border-radius: 4px;
background: #fff;
color: #888;
font-size: 14px;
cursor: pointer;
transition: all 0.2s ease;
}

.filter-btn:hover {
border-color: #0FC57C;
color: #0FC57C;
}

.filter-btn.active {
background: #0FC57C;
color: #fff;
border-color: #0FC57C;
}

/* Stats Panel */
.stats-panel {
margin: 20px 0;
padding: 10px;
border-bottom: 1px solid #eee;
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
gap: 10px;
}

.stats-panel span {
color: #888;
font-size: 14px;
}

.clear-completed {
padding: 8px 16px;
border: 1px solid #CF2323;
border-radius: 4px;
background: #fff;
color: #CF2323;
font-size: 14px;
cursor: pointer;
transition: all 0.2s ease;
}

.clear-completed:hover {
background: #CF2323;
color: #fff;
}

/* Responsive Design */
@media (max-width: 480px) {
.container {
width: 90%;
}

.filter-panel {
flex-direction: column;
}

.filter-btn {
width: 100%;
}

.stats-panel {
flex-direction: column;
align-items: flex-start;
}

.clear-completed {
width: 100%;
}
}
/* Heading */
h3,
label[for='new-task'] {
Expand Down
14 changes: 14 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,20 @@
<label for="new-task">Add Item</label><input id="new-task" type="text"><button>Add</button>
</p>

<!-- 过滤面板 -->
<div class="filter-panel">
<button class="filter-btn active" data-filter="all">全部</button>
<button class="filter-btn" data-filter="active">进行中</button>
<button class="filter-btn" data-filter="completed">已完成</button>
</div>

<!-- 统计区域 -->
<div class="stats-panel">
<span class="total-tasks">0 tasks</span>
<span class="completed-tasks">0 completed</span>
<button class="clear-completed">清除已完成</button>
</div>

<h3>Todo</h3>
<ul id="incomplete-tasks">
<li><input type="checkbox"><label>Pay Bills</label><input type="text"><button class="edit">Edit</button><button class="delete">Delete</button></li>
Expand Down
157 changes: 156 additions & 1 deletion js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,69 @@ var addButton = document.getElementsByTagName("button")[0]; // Fir
var incompleteTasksHolder = document.getElementById("incomplete-tasks"); // Incomplete-tasks
var completedTasksHolder = document.getElementById("completed-tasks"); // Completed-tasks

// Filter and Stats Elements
var filterButtons, totalTasksElement, completedTasksElement, clearCompletedButton, currentFilter;

// Initialize elements after DOM is loaded
document.addEventListener('DOMContentLoaded', function() {
filterButtons = document.querySelectorAll(".filter-btn");
totalTasksElement = document.querySelector(".total-tasks");
completedTasksElement = document.querySelector(".completed-tasks");
clearCompletedButton = document.querySelector(".clear-completed");
currentFilter = "all"; // Default filter
});

// localStorage data structure
var STORAGE_KEY = "todo-list-data";

// Save data to localStorage
var saveData = function() {
var data = {
incompleteTasks: [],
completedTasks: []
};

// Save incomplete tasks
for(var i = 0; i < incompleteTasksHolder.children.length; i++) {
var li = incompleteTasksHolder.children[i];
var label = li.querySelector("label");
data.incompleteTasks.push(label.innerText);
}

// Save completed tasks
for(var i = 0; i < completedTasksHolder.children.length; i++) {
var li = completedTasksHolder.children[i];
var label = li.querySelector("label");
data.completedTasks.push(label.innerText);
}

localStorage.setItem(STORAGE_KEY, JSON.stringify(data));
};

// Load data from localStorage
var loadData = function() {
var data = localStorage.getItem(STORAGE_KEY);
if(data) {
data = JSON.parse(data);

// Load incomplete tasks
data.incompleteTasks.forEach(function(taskText) {
var listItem = createNewTaskElement(taskText);
incompleteTasksHolder.appendChild(listItem);
bindTaskEvents(listItem, taskCompleted);
});

// Load completed tasks
data.completedTasks.forEach(function(taskText) {
var listItem = createNewTaskElement(taskText);
var checkBox = listItem.querySelector("input[type=checkbox]");
checkBox.checked = true;
completedTasksHolder.appendChild(listItem);
bindTaskEvents(listItem, taskIncomplete);
});
}
};

var createNewTaskElement = function(taskString) { // New Task List Item
var listItem = document.createElement("li"); // Create List Item
var checkBox = document.createElement("input"); // Input (checkbox)
Expand Down Expand Up @@ -47,6 +110,7 @@ var editTask = function() { // Edit an exist
if(containsClass) { // Switch from .editMode
label.innerText = editInput.value; // Label text become the input's value
button.innerText = "Edit"; // Buttons name modified to Edit
saveData(); // Save after editing
} else { // Switch to .editMode
editInput.value = label.innerText; // Input value becomes the label's text
button.innerText = "Save"; // Button name modified to Save
Expand Down Expand Up @@ -94,4 +158,95 @@ for(var i = 0; i < incompleteTasksHolder.children.length; i++) { // Cycle ov

for(var i = 0; i < completedTasksHolder.children.length; i++) { // Cycle over completedTasksHolder ul list items
bindTaskEvents(completedTasksHolder.children[i], taskIncomplete); // Bind events to list item's children (taskIncomplete)
}
}

// Update stats
var updateStats = function() {
var total = incompleteTasksHolder.children.length + completedTasksHolder.children.length;
var completed = completedTasksHolder.children.length;
var active = incompleteTasksHolder.children.length;

totalTasksElement.textContent = total + " tasks";
completedTasksElement.textContent = completed + " completed";
};

// Filter tasks
var filterTasks = function(filter) {
currentFilter = filter;

// Update button active state
filterButtons.forEach(function(button) {
button.classList.remove("active");
if(button.getAttribute("data-filter") === filter) {
button.classList.add("active");
}
});

// Show/hide task lists based on filter
if(filter === "all") {
incompleteTasksHolder.style.display = "block";
completedTasksHolder.style.display = "block";
} else if(filter === "active") {
incompleteTasksHolder.style.display = "block";
completedTasksHolder.style.display = "none";
} else if(filter === "completed") {
incompleteTasksHolder.style.display = "none";
completedTasksHolder.style.display = "block";
}
};

// Clear completed tasks
var clearCompleted = function() {
while(completedTasksHolder.firstChild) {
completedTasksHolder.removeChild(completedTasksHolder.firstChild);
}
updateStats();
saveData();
};

// Event listeners
document.addEventListener('DOMContentLoaded', function() {
filterButtons.forEach(function(button) {
button.addEventListener("click", function() {
var filter = this.getAttribute("data-filter");
filterTasks(filter);
});
});

clearCompletedButton.addEventListener("click", clearCompleted);
});

// Update stats when tasks are added, removed, or completed
var originalAddTask = addTask;
addTask = function() {
originalAddTask();
updateStats();
saveData();
};

var originalDeleteTask = deleteTask;
deleteTask = function() {
originalDeleteTask.apply(this, arguments);
updateStats();
saveData();
};

var originalTaskCompleted = taskCompleted;
taskCompleted = function() {
originalTaskCompleted.apply(this, arguments);
updateStats();
saveData();
};

var originalTaskIncomplete = taskIncomplete;
taskIncomplete = function() {
originalTaskIncomplete.apply(this, arguments);
updateStats();
saveData();
};

// Load data from localStorage and update stats on page load
document.addEventListener('DOMContentLoaded', function() {
loadData();
updateStats();
});