diff --git a/Exercise 7/todo.css b/Exercise 7/todo.css new file mode 100644 index 0000000..1384b60 --- /dev/null +++ b/Exercise 7/todo.css @@ -0,0 +1,67 @@ +body { + background-color: #272822; + color: #F8F8F8; + margin: 5% 20%; +} + +#title { + text-align: center; + color: #A6E22E; + font-size: 4em; +} + +#todoField { + display: block; + padding: 1em; + margin: 0 auto; + color: #F8F8F8; + background-color: #494b41; + font-size: 2em; + resize: none; +} + +#todoButton { + display: block; + padding: 1em; + margin: 1em auto; + color: black; + background-color: #FD971F; + font-size: 1.5em; + filter: drop-shadow(0.5em 0.5em 2px #191a16); +} + +#todoSummary { + font-size: 3em; + text-align: center; +} + +#todoList { + list-style-type: none; +} + +input[type=checkbox] { + width: 2em; + height: 2em; + margin-right: 2em; +} + +#todoList>li>span { + font-size: 3em; +} + +#todoList>li { + margin-bottom: 1.5em; +} + +/* Monokai rainbow list :DDD */ +#todoList>li:nth-child(7n+1) {color: #F92672;} +#todoList>li:nth-child(7n+2) {color: #FD971F;} +#todoList>li:nth-child(7n+3) {color: #E69F66;} +#todoList>li:nth-child(7n+4) {color: #E6DB74;} +#todoList>li:nth-child(7n+5) {color: #A6E22E;} +#todoList>li:nth-child(7n+6) {color: #66D9EF;} +#todoList>li:nth-child(7n) {color: #AE81FF;} + +.strikethrough { + text-decoration: line-through; +} diff --git a/Exercise 7/todo.html b/Exercise 7/todo.html new file mode 100644 index 0000000..027545d --- /dev/null +++ b/Exercise 7/todo.html @@ -0,0 +1,19 @@ + + + + + + Todo + + + + + +

Todo-list

+ + +
+ + + + \ No newline at end of file diff --git a/Exercise 7/todo.js b/Exercise 7/todo.js new file mode 100644 index 0000000..462cdfe --- /dev/null +++ b/Exercise 7/todo.js @@ -0,0 +1,83 @@ +const todoField = document.getElementById("todoField"); +const todoButton = document.getElementById("todoButton"); +const todoSummary = document.getElementById("todoSummary"); +const todoList = document.getElementById("todoList"); + +/** + * A task for the todolist + * @typedef {Object} Task + * @property {number} createdAt - Timestamp of the time that the task was created. + * @property {string} description - Description of the task. + * @property {boolean} isCompleted - Whether or not the task is completed. + */ + +const tasks = []; + +/** + * Add task to both tasks and DOM + */ +addTask = () => { + tasks.push({ + createdAt: Date.now(), + description: todoField.value, + completed: false + }); + + const taskElement = createTaskElement(tasks[tasks.length - 1]); + todoList.prepend(taskElement); + + todoField.value = ''; + + updateSummary(); +}; + +/** + * Generate HTML element for a task + * @param {Task} task - The task to be converted into an html element + * @return {HTMLLIElement} The
  • element + */ +createTaskElement = (task) => { + const listItem = document.createElement('li'); + + const checkbox = document.createElement('input'); + checkbox.type = 'checkbox'; + checkbox.name = tasks.length - 1 + checkbox.addEventListener('change', updateCheckbox); + listItem.appendChild(checkbox); + + const description = document.createElement('span'); + description.innerText = task.description; + listItem.appendChild(description); + + return listItem; +} + +/** + * Function to react to change on a checkbox + * @param {Event} event - the event raised by the eventlistener + */ +updateCheckbox = (event) => { + const index = tasks.length - event.target.name - 1; + tasks[index].isCompleted = event.target.checked; + console.log(event); + + const descriptionSpanClasses = todoList + .children[index] + .getElementsByTagName('span')[0] + .classList + + if (event.target.checked) descriptionSpanClasses.add('strikethrough'); + else descriptionSpanClasses.remove('strikethrough'); + + updateSummary(); +} + +/** + * Update the summary span with new task values + */ +updateSummary = () => { + const tasksCompleted = tasks.filter(task => task.isCompleted).length; + todoSummary.innerText = `${tasksCompleted}/${tasks.length} completed.`; +} + +todoButton.addEventListener('click', addTask); \ No newline at end of file