-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.js
More file actions
427 lines (351 loc) · 10.3 KB
/
Copy pathapp.js
File metadata and controls
427 lines (351 loc) · 10.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
/**
* KittyTasker - A cute and useful to-do list app for cat lovers!
*
* This JavaScript file contains the funcationality for the KittyTasker to-do list app!
* It allows users to create, mark complete and delete tasks.
*/
console.log('KittyTasker app intitalises now!');
// Global variables for application state
var tasks = [];
var currentFilter = "all";
// Global variables for DOM elements
var taskForm;
var taskInput;
var taskPriority;
var taskDate;
var taskList;
var itemsLeft;
var filterButtons;
/**
* Gets today's date formatted for HTML date input (YYYY-MM-DD)
*/
function getFormattedToday() {
var today = new Date();
// Get year, month and dy components
var year = today.getFullYear();
var month = today.getMonth() + 1; // Months are 0-based
var day = today.getDate();
// Pad month and day with leading zeros if needed
if(month < 10) {
month = '0' + month;
}
if(day < 10) {
day = '0' + day;
}
// Return formatted string (YYYY-MM-DD)
return year + '-' + month + '-' + day;
}
/**
* Updates the document title with task count
*/
function updateDocumentTitle () {
if(tasks.length === 1){
document.title = "KittyTasker - " + tasks.length + " Task";
} else {
document.title = "KittyTasker - " + tasks.length + " Tasks";
}
}
/**
* Updates the displayed task count
*/
function updateTaskCount() {
itemsLeft.textContent = tasks.length;
updateDocumentTitle();
if(tasks.length === 1) {
itemsLeft.textContent = `${tasks.length} item left`;
} else {
itemsLeft.textContent = `${tasks.length} items left`;
}
}
/**
* Validates a task to ensure it meets requirements
* @param {string} description - The task description
* @param {string} date - The due date
* @returns {Array} - Array of error messages (empty if valid)
*/
function validateTask(description, date) {
var errors = [];
// Description validation
if(!description) {
errors.push('Task description is required');
} else if(description.length < 3) {
errors.push('Task description must be at least 3 characters long');
}
// Date validation
if(!date) {
errors.push('Due date is required');
} else {
var today = getFormattedToday();
if(date < today) {
errors.push('Due date cannot be in the past');
}
}
return errors;
}
/**
* Removes a task
* @param {number} taskId - The ID of the task to remove
*/
function removeTask(taskId) {
// Find all tasks except the one to remove
var newTasks = [];
for(var i = 0; i < tasks.length; i++) {
if(tasks[i].id !== taskId) {
newTasks.push(tasks[i]);
}
}
// Update tasks array
tasks = newTasks;
// Log the change
console.log('Task removed!');
// Re-render tasks to update the UI
renderTasks();
}
/**
* Adds a new task
* @param {string} description - The task description
* @param {string} priority - The task priority
* @param {string} date - The due date
*/
function addTask(description, priority, date) {
// Validate task
var errors = validateTask(description, date);
if(errors.length > 0) {
formError.textContent = errors.join('. ');
formError.style.display = 'block';
return false;
}
// Clear previous errors
formError.textContent = '';
formError.style.display = 'none';
// Create new task object
var newTask = {
id: Date.now(),
description: description,
priority: priority,
date: date,
completed: false
};
// Add to tasks array
tasks.push(newTask);
// Render all tasks
renderTasks();
// Show confirmation
console.log('Task added successfully!');
return true;
}
/**
* Creates a new task object
* @param {string} description - The task description
* @param {string} priority - The task priority
* @param {string} date - The due date for the task
* @returns {Object} - The new task object
*/
function createTaskObject(description, priority, date) {
return {
id: Date.now(),
description: description,
priority: priority,
date: date,
completed: false
};
}
/**
* Renders a single task element
* @param {Object} taskData - The task data object
* @returns {HTMLElement} - The created task list item
*/
function renderTaskElement(taskData) {
// Create the list item element
var li = document.createElement('li');
li.className = 'task-item';
// Add data-id attribute to connect element with task data
li.setAttribute('data-id', taskData.id);
// Add the priority class
li.classList.add('task-item-' + taskData.priority);
// Add completed class if task is completed
if(taskData.completed) {
li.classList.add('task-completed');
}
// Create and add the checkbox with checked status
var checkbox = document.createElement('input');
checkbox.type = 'checkbox';
checkbox.className = 'task-checkbox';
checkbox.checked = taskData.completed;
li.appendChild(checkbox);
// Create and add content container
var content = document.createElement('div');
content.className = 'task-content';
// Add task title
var title = document.createElement('p');
title.className = 'task-text';
title.textContent = taskData.description;
content.appendChild(title);
// Add task details
var details = document.createElement('small');
details.className = 'task-details';
details.textContent = 'Priority: ' + taskData.priority + ' | Due: ' + taskData.date;
content.appendChild(details);
// Add content to the list item
li.appendChild(content);
// Add delete button
var deleteBtn = document.createElement('button');
deleteBtn.className = 'delete-btn';
deleteBtn.textContent = 'Delete';
li.appendChild(deleteBtn);
return li;
}
/**
* Handle task form submission
* @param {Event} e - The form submission event
*/
function handleFormSubmit(e) {
// Prevent the default form submission
e.preventDefault();
// Get form data
var description = taskInput.value.trim();
var priority = taskPriority.value;
var date = taskDate.value;
// Add task
var success = addTask(description, priority, date);
// Reset form if successful
if(success) {
resetFormWithCleanup();
}
}
/**
* Resets the form and clears error messages
*/
function resetFormWithCleanup() {
// Reset the form
taskForm.reset();
// Set the date field back to today's date
taskDate.value = getFormattedToday();
// Clear any errors
formError.textContent = '';
formError.style.display = 'none';
// Focus back on the input
taskInput.focus();
}
/**
* Renders all tasks in the tasks array
*/
function renderTasks() {
// Clear exisiting tasks from the DOM
taskList.innerHTML = '';
// Render each task
for (var i = 0; i < tasks.length; i++) {
var taskElement = renderTaskElement(tasks[i]);
taskList.appendChild(taskElement);
}
// Update task count
updateTaskCount();
}
/**
* Finds a task by its ID
* @param {number} taskId - The ID to search for
* @returns {Object|null} - The found task or null
*/
function findTaskById(taskId) {
for(var i = 0; i < tasks.length; i++) {
if(tasks[i].id === taskId) {
return tasks[i];
}
}
return null;
}
/**
* Toggles a task's completion status
* @param {number} taskId - The ID of the task toggle
*/
function toggleTaskComplete(taskId) {
// Find task by ID
var task = findTaskById(taskId);
if(task) {
// Toggle completion status
task.completed = !task.completed;
// Log the change
console.log(task.completed ? 'Task marked complete!' : 'Task marked incomplete!');
// Re-render tasks to update the UI
renderTasks();
}
}
/**
* Handle task list interactions
* @param {Event} e - The click event
*/
function handleTaskListClick(e) {
console.log('Task list clicked:', e.target);
// Find the closest task item
var taskItem = e.target;
while(taskItem && !taskItem.classList.contains('task-item')) {
taskItem = taskItem.parentElement;
}
// Return if no task item found
if(!taskItem) return;
// Get task ID
var taskId = parseInt(taskItem.getAttribute('data-id'));
console.log('Clicked task ID:', taskId);
// Check which element was clicked
if(e.target.classList.contains('task-checkbox')) {
// Checkbox clicked
toggleTaskComplete(taskId);
} else if(e.target.classList.contains('delete-btn')) {
// Delete button clicked
if(confirm('Are you sure you want to delete this task?')) {
removeTask(taskId);
}
}
}
/**
* Handle filter button clicks
* @param {Event} e - The click event
*/
function handleFilterClick(e) {
// Check if a fliter button was clicked
if(e.target.classList.contains('filter-btn')) {
// Get the filter type from the data-filter attribute
var filterType = e.target.getAttribute('data-filter');
// Update the current filter
currentFilter = filterType;
// Update the active class on filter buttons
for (var i = 0; i < filterButtons.length; i++) {
filterButtons[i].classList.remove('active');
}
e.target.classList.add('active');
console.log('Filter changed to: ', filterType);
// Actual filtering coming soon
}
}
/**
* Initialise the application
*/
function initApp() {
console.log('Intialising KittyTasker app.');
// Select form elements
taskForm = document.getElementById('task-form');
taskInput = document.getElementById('task-input');
taskPriority = document.getElementById('task-priority');
taskDate = document.getElementById('task-date');
formError = document.getElementById('form-error');
// Hide the form error box initially
formError.style.display = 'none';
// Select task list elements
taskList = document.getElementById('task-list');
itemsLeft = document.getElementById('items-left');
// Select all filter buttons
filterButtons = document.querySelectorAll('.filter-btn');
// Set default date to today
taskDate.value = getFormattedToday();
// Add event listeners
taskForm.addEventListener('submit', handleFormSubmit);
document.querySelector('nav').addEventListener('click', handleFilterClick);
taskList.addEventListener('click', handleTaskListClick);
// Render tasks (will be empty intially)
renderTasks();
// Update the document title
updateDocumentTitle();
console.log('KittyTasker app intialised');
}
// Intialise when DOM is loaded
document.addEventListener('DOMContentLoaded', initApp);