-
Notifications
You must be signed in to change notification settings - Fork 1
/
app.js
163 lines (154 loc) · 5.16 KB
/
app.js
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
// Todo object
/*
{
id: new Date().getTime(),
task: '',
done: false,
}
*/
class ToDoList {
constructor(submitForm, userInput, todoList, todoListNotDone, todoListDone) {
this._toDoList = [];
this._submitForm = document.getElementById(submitForm);
this._userInput = document.getElementById(userInput);
this._todoListElement = document.getElementById(todoList);
this._todoListNotDone = document.getElementById(todoListNotDone);
this._todoListDone = document.getElementById(todoListDone);
this.init();
}
init = () => {
// Listen the submit button of input field
this._submitForm.addEventListener('submit', this.createTodoHandle);
// Listen todo list
this._todoListElement.addEventListener('click', (e) => {
if (e.target.nodeName === 'P') this.editTodoHandle(e);
if (e.target.parentNode.nodeName === 'BUTTON') this.deleteTodoHandle(e);
if (e.target.parentNode.nodeName === 'DIV') this.markDoneTaskHandle(e);
});
};
// Create a new todo
createTodoHandle = (e) => {
e.preventDefault();
// Store the user input
const userInputValue = this._userInput.value;
// Guard for the user input
if (!userInputValue) return;
// Create todo
const todo = {
id: new Date().getTime(),
task: userInputValue,
done: false,
};
// Store the todo in the todos list
this._toDoList.push(todo);
// Clean the form
document.forms[0].reset();
// Display todo list
this.displayTodoList();
};
// Display (Read) todo list
displayTodoList = () => {
// Clear the previous lists
this._todoListNotDone.innerHTML = '';
this._todoListDone.innerHTML = '';
this._toDoList.length > 0
? this._todoListElement.classList.add('todolist')
: this._todoListElement.classList.remove('todolist');
// Create the li for each todo in the object
this._toDoList.forEach((todo) => {
let liElement;
if (todo.done) {
// Template for todo done
liElement = `
<li id="${todo.id}" class="d-flex justify-content-between align-items-center">
<div><i class="fas fa-check-circle"></i></div>
<p class="mb-0 w-100 mx-2 text-decoration-line-through">${todo.task}</p>
<button class="btn btn-danger btn-sm"><i class="fas fa-trash"></i></button>
</li>
`;
this._todoListDone.insertAdjacentHTML('beforeend', liElement);
// Create the title if it is the first todo done
if (this._todoListDone.children.length === 1) {
const titleElement =
'<div class="todolist-title d-flex justify-content-start align-items-center"><i class="fas fa-tasks"></i><h3>Completed</h3></div>';
this._todoListDone.insertAdjacentHTML('afterbegin', titleElement);
}
} else {
// Template for todo not done
liElement = `
<li id="${todo.id}" class="d-flex justify-content-between align-items-center">
<div><i class="far fa-circle"></i></div>
<p class="mb-0 w-100 mx-2">${todo.task}</p>
<button class="btn btn-danger btn-sm"><i class="fas fa-trash"></i></button>
</li>
`;
this._todoListNotDone.insertAdjacentHTML('beforeend', liElement);
}
});
};
// Edit (Update) a todo
editTodoHandle = (e) => {
// Target the todo to update
const todoEditableElement = e.target;
// Turn on to edit the content
todoEditableElement.setAttribute('contenteditable', 'true');
// Listen when user press enter or blur the target
todoEditableElement.addEventListener('blur', this.saveUpdateTodoHandle);
todoEditableElement.addEventListener('keydown', (e) => {
if (e.key === 'Enter') {
// Avoid run two times the callback function
todoEditableElement.removeEventListener(
'blur',
this.saveUpdateTodoHandle
);
this.saveUpdateTodoHandle(e);
}
});
};
// Save (Update) the todo updated
saveUpdateTodoHandle = (e) => {
// Target the todo to update
const todoEditableElement = e.target;
// Turn off to edit the content
todoEditableElement.removeAttribute('contenteditable', 'false');
// Store user input value updated
const toDoListUpdated = this._toDoList.map(
(todo) =>
todo.id === parseInt(e.target.parentNode.id)
? {...todo, task: todoEditableElement.innerText}
: {...todo }
);
this._toDoList = toDoListUpdated;
};
// Delete todo
deleteTodoHandle = (e) => {
// Filter todo in the todo list
const todoFiltered = this._toDoList.filter(
(todo) => todo.id !== parseInt(e.target.parentNode.parentNode.id)
);
// Update todo list
this._toDoList = todoFiltered;
// Update UI
this.displayTodoList();
};
// Mark done the task
markDoneTaskHandle = (e) => {
// Retrieve todo ID
const todoDone = this._toDoList.map((todo) =>
todo.id === parseInt(e.target.parentNode.parentNode.id)
? { ...todo, done: !todo.done }
: { ...todo }
);
// Update todo list
this._toDoList = todoDone;
// Update UI
this.displayTodoList();
};
}
new ToDoList(
'taskInputForm',
'taskInput',
'todoList',
'todoListNotDone',
'todoListDone'
);