From 19f988806bb8c078beb0696e18ffe46ae9a6b50e Mon Sep 17 00:00:00 2001 From: Sati Yeghoyan Date: Sun, 9 Feb 2025 22:15:43 +0100 Subject: [PATCH 1/4] fix: rename attributes across HTML, CSS, and JS according to rule X.X in html-and-css.md refactor: apply IDE refactoring tools for better code structure according to rule Y.Y in js-best-practices.md --- app.js | 239 +++++++++++++++-------------------------------------- index.html | 82 ++++++++++++++---- style.css | 101 ++++++++++++---------- 3 files changed, 192 insertions(+), 230 deletions(-) diff --git a/app.js b/app.js index ab737a6002..6ec4d78767 100644 --- a/app.js +++ b/app.js @@ -1,195 +1,92 @@ -//Document is the DOM can be accessed in the console with document.window. -// Tree is from the top, html, body, p etc. +// Refactored JavaScript for Todo App -//Problem: User interaction does not provide the correct results. -//Solution: Add interactivity so the user can manage daily tasks. -//Break things down into smaller steps and take each step at a time. +const taskInput = document.getElementById("new-task"); +const addButton = document.querySelector("button"); +const incompleteTaskHolder = document.getElementById("incompleteTasks"); +const completedTasksHolder = document.getElementById("completed-tasks"); +// Create a new task list item +const createNewTaskElement = (taskString) => { + const listItem = document.createElement("li"); -// Event handling, user interaction is what starts the code execution. + const checkBox = document.createElement("input"); + const label = document.createElement("label"); + const editInput = document.createElement("input"); + const editButton = document.createElement("button"); + const deleteButton = document.createElement("button"); + const deleteButtonImg = document.createElement("img"); -var taskInput=document.getElementById("new-task");//Add a new task. -var addButton=document.getElementsByTagName("button")[0];//first button -var incompleteTaskHolder=document.getElementById("incompleteTasks");//ul of #incompleteTasks -var completedTasksHolder=document.getElementById("completed-tasks");//completed-tasks + label.innerText = taskString; + label.className = "task"; + checkBox.type = "checkbox"; + editInput.type = "text"; + editInput.className = "task"; -//New task list item -var createNewTaskElement=function(taskString){ + editButton.innerText = "Edit"; + editButton.className = "edit"; - var listItem=document.createElement("li"); - - //input (checkbox) - var checkBox=document.createElement("input");//checkbx - //label - var label=document.createElement("label");//label - //input (text) - var editInput=document.createElement("input");//text - //button.edit - var editButton=document.createElement("button");//edit button - - //button.delete - var deleteButton=document.createElement("button");//delete button - var deleteButtonImg=document.createElement("img");//delete button image - - label.innerText=taskString; - label.className='task'; - - //Each elements, needs appending - checkBox.type="checkbox"; - editInput.type="text"; - editInput.className="task"; - - editButton.innerText="Edit"; //innerText encodes special characters, HTML does not. - editButton.className="edit"; - - deleteButton.className="delete"; - deleteButtonImg.src='./remove.svg'; + deleteButton.className = "delete"; + deleteButtonImg.src = "./remove.svg"; deleteButton.appendChild(deleteButtonImg); - - //and appending. - listItem.appendChild(checkBox); - listItem.appendChild(label); - listItem.appendChild(editInput); - listItem.appendChild(editButton); - listItem.appendChild(deleteButton); + listItem.append(checkBox, label, editInput, editButton, deleteButton); return listItem; -} - - - -var addTask=function(){ - console.log("Add Task..."); - //Create a new list item with the text from the #new-task: - if (!taskInput.value) return; - var listItem=createNewTaskElement(taskInput.value); +}; - //Append listItem to incompleteTaskHolder +const addTask = () => { + if (!taskInput.value.trim()) return; + const listItem = createNewTaskElement(taskInput.value); incompleteTaskHolder.appendChild(listItem); bindTaskEvents(listItem, taskCompleted); + taskInput.value = ""; +}; - taskInput.value=""; - -} - -//Edit an existing task. - -var editTask=function(){ - console.log("Edit Task..."); - console.log("Change 'edit' to 'save'"); - - - var listItem=this.parentNode; - - var editInput=listItem.querySelector('input[type=text]'); - var label=listItem.querySelector("label"); - var editBtn=listItem.querySelector(".edit"); - var containsClass=listItem.classList.contains("editMode"); - //If class of the parent is .editmode - if(containsClass){ - - //switch to .editmode - //label becomes the inputs value. - label.innerText=editInput.value; - editBtn.innerText="Edit"; - }else{ - editInput.value=label.innerText; - editBtn.innerText="Save"; +const editTask = function () { + const listItem = this.parentNode; + const editInput = listItem.querySelector("input[type=text]"); + const label = listItem.querySelector("label"); + const editBtn = listItem.querySelector(".edit"); + const isEditMode = listItem.classList.toggle("editMode"); + + if (isEditMode) { + editInput.value = label.innerText; + editBtn.innerText = "Save"; + } else { + label.innerText = editInput.value; + editBtn.innerText = "Edit"; } - - //toggle .editmode on the parent. - listItem.classList.toggle("editMode"); }; +const deleteTask = function () { + this.parentNode.remove(); +}; -//Delete task. -var deleteTask=function(){ - console.log("Delete Task..."); - - var listItem=this.parentNode; - var ul=listItem.parentNode; - //Remove the parent list item from the ul. - ul.removeChild(listItem); - -} - - -//Mark task completed -var taskCompleted=function(){ - console.log("Complete Task..."); - - //Append the task list item to the #completed-tasks - var listItem=this.parentNode; - completedTasksHolder.appendChild(listItem); - bindTaskEvents(listItem, taskIncomplete); - -} - - -var taskIncomplete=function(){ - console.log("Incomplete Task..."); -//Mark task as incomplete. - //When the checkbox is unchecked - //Append the task list item to the #incompleteTasks. - var listItem=this.parentNode; - incompleteTaskHolder.appendChild(listItem); - bindTaskEvents(listItem,taskCompleted); -} - - - -var ajaxRequest=function(){ - console.log("AJAX Request"); -} - -//The glue to hold it all together. - - -//Set the click handler to the addTask function. -addButton.onclick=addTask; -addButton.addEventListener("click",addTask); -addButton.addEventListener("click",ajaxRequest); - - -var bindTaskEvents=function(taskListItem,checkBoxEventHandler){ - console.log("bind list item events"); -//select ListItems children - var checkBox=taskListItem.querySelector("input[type=checkbox]"); - var editButton=taskListItem.querySelector("button.edit"); - var deleteButton=taskListItem.querySelector("button.delete"); - - - //Bind editTask to edit button. - editButton.onclick=editTask; - //Bind deleteTask to delete button. - deleteButton.onclick=deleteTask; - //Bind taskCompleted to checkBoxEventHandler. - checkBox.onchange=checkBoxEventHandler; -} - -//cycle over incompleteTaskHolder ul list items -//for each list item -for (var i=0; i { + const checkBox = taskListItem.querySelector("input[type=checkbox]"); + const editButton = taskListItem.querySelector("button.edit"); + const deleteButton = taskListItem.querySelector("button.delete"); + editButton.addEventListener("click", editTask); + deleteButton.addEventListener("click", deleteTask); + checkBox.addEventListener("change", checkBoxEventHandler); +}; -// Issues with usability don't get seen until they are in front of a human tester. +addButton.addEventListener("click", addTask); -//prevent creation of empty tasks. +taskInput.addEventListener("keypress", (e) => { + if (e.key === "Enter") addTask(); +}); -//Change edit to save when you are in edit mode. \ No newline at end of file +Array.from(incompleteTaskHolder.children).forEach(item => bindTaskEvents(item, taskCompleted)); +Array.from(completedTasksHolder.children).forEach(item => bindTaskEvents(item, taskIncomplete)); diff --git a/index.html b/index.html index ef4aa1f60c..c7de1c4e6a 100644 --- a/index.html +++ b/index.html @@ -1,19 +1,67 @@ - -Todo App - - - + + + + + + Todo App + + + - -

-

Todo

-
    -
  • -
  • -

Completed

  • -
  • -
-
- + + +
+
+ +
+ + +
+
+ +
+

Todo

+
    +
  • + + + + + +
  • +
  • + + + + + +
  • +
+
+ +
+

Completed

+
    +
  • + + + + + +
  • +
+
+
+ + - \ No newline at end of file + diff --git a/style.css b/style.css index ab36227705..bc9c056b7b 100644 --- a/style.css +++ b/style.css @@ -1,64 +1,75 @@ -/* Basic Style */ +/* Basic Styles */ body { background-color: #f8f8f8; color: #333; - font-family: Lato, sans-serif; + font-family: "Lato", sans-serif; + margin: 0; + padding: 0; } -.aaa { + +.matrix-container { width: 500px; margin: 0 auto; - display: block; text-align: right; } -.aaa img { +.matrix-container img { width: 100%; } -.aaa .more_inf { +.matrix-container .more-info { font-family: fantasy, cursive; } -@media (max-width:768px) { -.aaa { text-align: center; +@media (max-width: 768px) { + .matrix-container { + text-align: center; + } } -} -.centered-main-page-element { - display: block; + +.main-content { width: 500px; - margin: 0 auto 0; + margin: 0 auto; } + +.task-input-wrapper { + display: flex; + align-items: center; +} + .task { width: 56%; display: inline-block; - flex-grow: 1 -} -.task-row-wrapper { - display: flex; + flex-grow: 1; } + ul { - margin:0; - padding: 0px; + margin: 0; + padding: 0; } + li, h3 { - list-style:none; + list-style: none; } -input,button{ - outline:none; + +input, button { + outline: none; } + button { background: none; - border: 0px; + border: none; color: #888; font-size: 15px; width: 60px; - font-family: Lato, sans-serif; + font-family: "Lato", sans-serif; cursor: pointer; } + button:hover { - color: #3a3A3a; + color: #3a3a3a; } -/* Heading */ -h3, -label[for='new-task'] { + +/* Headings */ +h3, label[for='new-task'] { color: #333; font-weight: 700; font-size: 15px; @@ -67,18 +78,20 @@ label[for='new-task'] { margin: 0; text-transform: uppercase; } + input[type="text"] { margin: 0; font-size: 18px; line-height: 18px; height: 21px; padding: 0 9px; - border: 1px solid #dDd; - background: #FFF; + border: 1px solid #ddd; + background: #fff; border-radius: 6px; - font-family: Lato, sans-serif; + font-family: "Lato", sans-serif; color: #888; } + input[type="text"]:focus { color: #333; } @@ -86,22 +99,23 @@ input[type="text"]:focus { /* New Task */ label[for='new-task'] { display: block; - margin: 0 0 20px; + margin-bottom: 20px; } + input#new-task { width: 318px; } -/* Task list */ +/* Task List */ li { overflow: hidden; padding: 20px 0; border-bottom: 1px solid #eee; - display: flex; justify-content: space-between; align-items: center; } + li > * { vertical-align: middle; } @@ -109,40 +123,43 @@ li > * { li > input[type="checkbox"] { margin: 0 10px; } + li > label { padding-left: 10px; - box-sizing: border-box; font-size: 18px; width: 226px; } -li > input[type="text"] { - width: 226px + +li > input[type="text"] { + width: 226px; } + button.delete img { height: 2em; transform: rotateZ(45deg); transition: transform 200ms ease-in; } + button.delete img:hover { transform: rotateZ(0); } /* Completed */ ul#completed-tasks label { - text-decoration: line-through + text-decoration: line-through; color: #888; } /* Edit Task */ ul li input[type=text] { - display:none + display: none; } ul li.editMode input[type=text] { - display:inline-block; - width:224px + display: inline-block; + width: 224px; } ul li.editMode label { - display:none; -} \ No newline at end of file + display: none; +} From f042295b261c78d696d91fe543dec691a5ecbc6e Mon Sep 17 00:00:00 2001 From: Sati Yeghoyan Date: Sun, 16 Feb 2025 21:07:23 +0100 Subject: [PATCH 2/4] refactor: clean code --- app.js | 4 ++-- index.html | 17 ++++++++++------- style.css | 15 ++++++--------- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/app.js b/app.js index 6ec4d78767..a2ad4fb3a7 100644 --- a/app.js +++ b/app.js @@ -2,7 +2,7 @@ const taskInput = document.getElementById("new-task"); const addButton = document.querySelector("button"); -const incompleteTaskHolder = document.getElementById("incompleteTasks"); +const incompleteTaskHolder = document.getElementById("incomplete-tasks"); const completedTasksHolder = document.getElementById("completed-tasks"); // Create a new task list item @@ -47,7 +47,7 @@ const editTask = function () { const editInput = listItem.querySelector("input[type=text]"); const label = listItem.querySelector("label"); const editBtn = listItem.querySelector(".edit"); - const isEditMode = listItem.classList.toggle("editMode"); + const isEditMode = listItem.classList.toggle("edit-mode"); if (isEditMode) { editInput.value = label.innerText; diff --git a/index.html b/index.html index c7de1c4e6a..4d9d972a7c 100644 --- a/index.html +++ b/index.html @@ -1,5 +1,6 @@ + @@ -7,12 +8,13 @@ + - +
@@ -21,10 +23,10 @@
- +

Todo

-
    +
    • @@ -34,7 +36,7 @@

      Todo

      Delete
    • -
    • +
    • @@ -45,7 +47,7 @@

      Todo

- +

Completed

    @@ -61,7 +63,8 @@

    Completed

- + - + + \ No newline at end of file diff --git a/style.css b/style.css index bc9c056b7b..77a9c0f8fc 100644 --- a/style.css +++ b/style.css @@ -1,4 +1,4 @@ -/* Basic Styles */ +/* Ensure each selector and property is on its own line */ body { background-color: #f8f8f8; color: #333; @@ -12,9 +12,11 @@ body { margin: 0 auto; text-align: right; } + .matrix-container img { width: 100%; } + .matrix-container .more-info { font-family: fantasy, cursive; } @@ -68,8 +70,7 @@ button:hover { color: #3a3a3a; } -/* Headings */ -h3, label[for='new-task'] { +h3, label[for="new-task"] { color: #333; font-weight: 700; font-size: 15px; @@ -96,8 +97,7 @@ input[type="text"]:focus { color: #333; } -/* New Task */ -label[for='new-task'] { +label[for="new-task"] { display: block; margin-bottom: 20px; } @@ -106,7 +106,6 @@ input#new-task { width: 318px; } -/* Task List */ li { overflow: hidden; padding: 20px 0; @@ -144,13 +143,11 @@ button.delete img:hover { transform: rotateZ(0); } -/* Completed */ ul#completed-tasks label { text-decoration: line-through; color: #888; } -/* Edit Task */ ul li input[type=text] { display: none; } @@ -162,4 +159,4 @@ ul li.editMode input[type=text] { ul li.editMode label { display: none; -} +} \ No newline at end of file From 21984d18ce7c5e10974bfd3d682416c956ee0203 Mon Sep 17 00:00:00 2001 From: Sati Yeghoyan Date: Wed, 19 Feb 2025 21:59:08 +0100 Subject: [PATCH 3/4] fix: Marking as completed (toggleComplete), - The deleteTask function is already handling task deletion, whether it's in the todoList or completedList -The editTask function works for both TODO and Competed task --- app.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app.js b/app.js index a2ad4fb3a7..6ea087760e 100644 --- a/app.js +++ b/app.js @@ -50,11 +50,17 @@ const editTask = function () { const isEditMode = listItem.classList.toggle("edit-mode"); if (isEditMode) { + // Switch to edit mode editInput.value = label.innerText; editBtn.innerText = "Save"; + editInput.style.display = "inline-block"; + label.style.display = "none"; } else { + // Switch to view mode label.innerText = editInput.value; editBtn.innerText = "Edit"; + editInput.style.display = "none"; + label.style.display = "inline-block"; } }; From c2caf48ad5f30ab93cd3656b6c8a7024950e00ac Mon Sep 17 00:00:00 2001 From: Sati Yeghoyan Date: Wed, 19 Feb 2025 22:33:26 +0100 Subject: [PATCH 4/4] fix: use two spaces for indentation according to rule 1.1 in beginner-guidelines.md refactor: rename attributes across HTML, CSS, and JS for consistency - Renamed all IDs and class names in HTML to follow a structured convention - Updated CSS selectors to match new naming - Refactored JavaScript variables and function names accordingly - Ensured all event listeners and DOM manipulations work correctly after renaming style: improve code formatting and readability - Used `const` and `let` instead of `var` in JavaScript - Applied consistent indentation and spacing across all files - Improved HTML structure with proper nesting - Optimized CSS rules for better readability feat: optimize addTask function and improve performance - Prevented creation of empty tasks - Used `Array.from()` for iterating instead of `for` loops - Removed redundant DOM manipulations fix: simplify and optimize task editing logic - Improved `editTask` function with cleaner toggle logic - Ensured correct text updates and button state switching - Maintained proper task state handling --- index.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/index.html b/index.html index 4d9d972a7c..a3bd59aac9 100644 --- a/index.html +++ b/index.html @@ -23,8 +23,8 @@ - -
+ +

Todo