From a3bdf48c6a90646d4f0d3ddf00c568db8f49e969 Mon Sep 17 00:00:00 2001 From: sedazam Date: Sat, 2 Aug 2025 07:58:55 +0100 Subject: [PATCH 01/58] Fix input types in book library form and add launch configuration for debugging --- .vscode/launch.json | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 .vscode/launch.json diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 00000000..7c93bc0a --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,14 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "name": "Run Current File", + "request": "launch", + "program": "${workspaceFolder}/debugging/book-library/index.html" + } + ] +} \ No newline at end of file From ae05097c4fc126819696ae81680e8ec5173a80f4 Mon Sep 17 00:00:00 2001 From: sedazam Date: Sat, 2 Aug 2025 07:59:59 +0100 Subject: [PATCH 02/58] Fix input types for title and author fields in book library form --- debugging/book-library/index.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/debugging/book-library/index.html b/debugging/book-library/index.html index 23acfa71..2628651d 100644 --- a/debugging/book-library/index.html +++ b/debugging/book-library/index.html @@ -31,7 +31,7 @@

Library

Library /> Date: Sat, 2 Aug 2025 08:06:15 +0100 Subject: [PATCH 03/58] Fix syntax error in render function loop --- debugging/book-library/script.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debugging/book-library/script.js b/debugging/book-library/script.js index 75ce6c1d..eed706fd 100644 --- a/debugging/book-library/script.js +++ b/debugging/book-library/script.js @@ -54,7 +54,7 @@ function render() { let table = document.getElementById("display"); let rowsNumber = table.rows.length; //delete old table - for (let n = rowsNumber - 1; n > 0; n-- { + for (let n = rowsNumber - 1; n > 0; n--) { table.deleteRow(n); } //insert updated row and cells From 1573031b4a3405f0728deaeccbb80390b2131b99 Mon Sep 17 00:00:00 2001 From: sedazam Date: Sat, 2 Aug 2025 08:09:14 +0100 Subject: [PATCH 04/58] Fix read status logic in render function --- debugging/book-library/script.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debugging/book-library/script.js b/debugging/book-library/script.js index eed706fd..3c7fb929 100644 --- a/debugging/book-library/script.js +++ b/debugging/book-library/script.js @@ -76,7 +76,7 @@ function render() { changeBut.className = "btn btn-success"; wasReadCell.appendChild(changeBut); let readStatus = ""; - if (myLibrary[i].check == false) { + if (myLibrary[i].check == true) { readStatus = "Yes"; } else { readStatus = "No"; From 9440f6504b1b2c295770ee96d7dd130dc3b89905 Mon Sep 17 00:00:00 2001 From: sedazam Date: Sat, 2 Aug 2025 08:24:51 +0100 Subject: [PATCH 05/58] Fix reference to myLibrary in submit function --- debugging/book-library/script.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debugging/book-library/script.js b/debugging/book-library/script.js index 3c7fb929..0512c646 100644 --- a/debugging/book-library/script.js +++ b/debugging/book-library/script.js @@ -38,7 +38,7 @@ function submit() { return false; } else { let book = new Book(title.value, title.value, pages.value, check.checked); - library.push(book); + myLibrary.push(book); render(); } } From 51aa2073167f8b4ab64df1cd73a3092a460fd115 Mon Sep 17 00:00:00 2001 From: sedazam Date: Sat, 2 Aug 2025 08:27:54 +0100 Subject: [PATCH 06/58] Fix delete button functionality in render function --- debugging/book-library/script.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/debugging/book-library/script.js b/debugging/book-library/script.js index 0512c646..199c3537 100644 --- a/debugging/book-library/script.js +++ b/debugging/book-library/script.js @@ -90,11 +90,11 @@ function render() { //add delete button to every row and render again let delButton = document.createElement("button"); - delBut.id = i + 5; - deleteCell.appendChild(delBut); - delBut.className = "btn btn-warning"; - delBut.innerHTML = "Delete"; - delBut.addEventListener("clicks", function () { + delButton.id = i + 5; + deleteCell.appendChild(delButton); + delButton.className = "btn btn-warning"; + delButton.innerHTML = "Delete"; + delButton.addEventListener("click", function () { alert(`You've deleted title: ${myLibrary[i].title}`); myLibrary.splice(i, 1); render(); From ed8d683e9e9538314eb14a0921f8bdd9ab8c062d Mon Sep 17 00:00:00 2001 From: sedazam Date: Sat, 2 Aug 2025 08:30:29 +0100 Subject: [PATCH 07/58] Fix book constructor parameters in submit function --- debugging/book-library/script.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debugging/book-library/script.js b/debugging/book-library/script.js index 199c3537..47050eab 100644 --- a/debugging/book-library/script.js +++ b/debugging/book-library/script.js @@ -37,7 +37,7 @@ function submit() { alert("Please fill all fields!"); return false; } else { - let book = new Book(title.value, title.value, pages.value, check.checked); + let book = new Book(title.value, pages.value, check.checked); myLibrary.push(book); render(); } From 2d6fdc2f9217ee0a6c597f399d295f6a4f86f3cc Mon Sep 17 00:00:00 2001 From: sedazam Date: Sat, 2 Aug 2025 08:31:52 +0100 Subject: [PATCH 08/58] Fix author parameter in book constructor in submit function --- debugging/book-library/script.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debugging/book-library/script.js b/debugging/book-library/script.js index 47050eab..7e845516 100644 --- a/debugging/book-library/script.js +++ b/debugging/book-library/script.js @@ -37,7 +37,7 @@ function submit() { alert("Please fill all fields!"); return false; } else { - let book = new Book(title.value, pages.value, check.checked); + let book = new Book(title.value, author.value, pages.value, check.checked); myLibrary.push(book); render(); } From 3b0639ae45994f6d1e5c9d16da21d31b308dc61c Mon Sep 17 00:00:00 2001 From: sedazam Date: Sat, 2 Aug 2025 08:36:25 +0100 Subject: [PATCH 09/58] Fix validation logic in submit function to check author field --- debugging/book-library/script.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/debugging/book-library/script.js b/debugging/book-library/script.js index 7e845516..fdd18c18 100644 --- a/debugging/book-library/script.js +++ b/debugging/book-library/script.js @@ -32,7 +32,9 @@ function submit() { title.value == null || title.value == "" || pages.value == null || - pages.value == "" + pages.value == "" || + author.value == null || + author.value == "" || ) { alert("Please fill all fields!"); return false; From 75eea9cd41cbcb79e91f2a2b683fcd9f8d336f55 Mon Sep 17 00:00:00 2001 From: sedazam Date: Sat, 2 Aug 2025 08:49:02 +0100 Subject: [PATCH 10/58] Add buttons for viewing read books and all books; fix author validation in submit function --- debugging/book-library/index.html | 6 ++++++ debugging/book-library/script.js | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/debugging/book-library/index.html b/debugging/book-library/index.html index 2628651d..1f02a5d9 100644 --- a/debugging/book-library/index.html +++ b/debugging/book-library/index.html @@ -26,6 +26,12 @@

Library

+ +
diff --git a/debugging/book-library/script.js b/debugging/book-library/script.js index fdd18c18..65130706 100644 --- a/debugging/book-library/script.js +++ b/debugging/book-library/script.js @@ -34,7 +34,7 @@ function submit() { pages.value == null || pages.value == "" || author.value == null || - author.value == "" || + author.value == "" ) { alert("Please fill all fields!"); return false; From a1e10b50cae7fb7e11274b1e3bb6fb130407c65a Mon Sep 17 00:00:00 2001 From: sedazam Date: Sat, 2 Aug 2025 08:49:29 +0100 Subject: [PATCH 11/58] Add viewReadBooks function to filter and display read books in the library --- debugging/book-library/script.js | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/debugging/book-library/script.js b/debugging/book-library/script.js index 65130706..7166c1d7 100644 --- a/debugging/book-library/script.js +++ b/debugging/book-library/script.js @@ -59,6 +59,34 @@ function render() { for (let n = rowsNumber - 1; n > 0; n--) { table.deleteRow(n); } + + function viewReadBooks() { + let table = document.getElementById("display"); + let rowsNumber = table.rows.length; + + // Clear existing rows (except header) + for (let n = rowsNumber - 1; n > 0; n--) { + table.deleteRow(n); + } + + // Filter only read books + const readBooks = myLibrary.filter(book => book.check === true); + + for (let i = 0; i < readBooks.length; i++) { + let row = table.insertRow(1); + let titleCell = row.insertCell(0); + let authorCell = row.insertCell(1); + let pagesCell = row.insertCell(2); + let wasReadCell = row.insertCell(3); + let deleteCell = row.insertCell(4); + + titleCell.innerHTML = readBooks[i].title; + authorCell.innerHTML = readBooks[i].author; + pagesCell.innerHTML = readBooks[i].pages; + wasReadCell.innerText = "Yes"; + deleteCell.innerHTML = "-"; + } +} //insert updated row and cells let length = myLibrary.length; for (let i = 0; i < length; i++) { From 5a823b12589f4b7ee3ce065807bc2c4ea19a154e Mon Sep 17 00:00:00 2001 From: sedazam Date: Sat, 2 Aug 2025 08:54:16 +0100 Subject: [PATCH 12/58] Refactor button layout for better structure and styling in the library interface --- debugging/book-library/index.html | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/debugging/book-library/index.html b/debugging/book-library/index.html index 1f02a5d9..d06e7510 100644 --- a/debugging/book-library/index.html +++ b/debugging/book-library/index.html @@ -23,15 +23,25 @@

Library

Add books to your virtual library

- - - +
+
+
+ +
+
+ +
+
+ +
+
+
From e4ab05eaa46c2e68377d2760ab91cb3799013c9a Mon Sep 17 00:00:00 2001 From: sedazam Date: Sat, 2 Aug 2025 09:01:04 +0100 Subject: [PATCH 13/58] Refactor button layout for improved accessibility and styling in the library interface; update CSS for better button alignment --- debugging/book-library/index.html | 22 ++++------------------ debugging/book-library/style.css | 14 ++++++++------ 2 files changed, 12 insertions(+), 24 deletions(-) diff --git a/debugging/book-library/index.html b/debugging/book-library/index.html index d06e7510..5130f106 100644 --- a/debugging/book-library/index.html +++ b/debugging/book-library/index.html @@ -23,24 +23,10 @@

Library

Add books to your virtual library

-
-
-
- -
-
- -
-
- -
-
+
+ + +
diff --git a/debugging/book-library/style.css b/debugging/book-library/style.css index 302950cb..1f8a84ee 100644 --- a/debugging/book-library/style.css +++ b/debugging/book-library/style.css @@ -1,12 +1,14 @@ .form-group { - width: 400px; - height: 300px; - align-self: left; - padding-left: 20px; + max-width: 400px; + padding: 20px; + margin: auto; } -.btn { - display: block; +button.btn { + margin: 10px; +} +.row .btn { + margin-right: 10px; } .form-check-label { From 7f237b13ef698ea3097d57e78eb71cbaedd37731 Mon Sep 17 00:00:00 2001 From: sedazam Date: Sat, 2 Aug 2025 09:06:43 +0100 Subject: [PATCH 14/58] Update render function to simplify cell insertion for read books and improve readability --- debugging/book-library/script.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/debugging/book-library/script.js b/debugging/book-library/script.js index 7166c1d7..f4d4a649 100644 --- a/debugging/book-library/script.js +++ b/debugging/book-library/script.js @@ -74,11 +74,11 @@ function render() { for (let i = 0; i < readBooks.length; i++) { let row = table.insertRow(1); - let titleCell = row.insertCell(0); - let authorCell = row.insertCell(1); - let pagesCell = row.insertCell(2); - let wasReadCell = row.insertCell(3); - let deleteCell = row.insertCell(4); + row.insertCell(0).innerText = readBooks[i].title; + row.insertCell(1).innerText = readBooks[i].author; + row.insertCell(2).innerText = readBooks[i].pages; + row.insertCell(3).innerText = "Yes"; + row.insertCell(4).innerHTML = "-"; titleCell.innerHTML = readBooks[i].title; authorCell.innerHTML = readBooks[i].author; From 2ce428b1cca28152aac9a30fa792be0bb09b2d44 Mon Sep 17 00:00:00 2001 From: sedazam Date: Sat, 2 Aug 2025 09:09:44 +0100 Subject: [PATCH 15/58] Fix submit function to ensure viewReadBooks is called only when the book is marked as read --- debugging/book-library/script.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/debugging/book-library/script.js b/debugging/book-library/script.js index f4d4a649..3f1950f2 100644 --- a/debugging/book-library/script.js +++ b/debugging/book-library/script.js @@ -43,6 +43,11 @@ function submit() { myLibrary.push(book); render(); } + if (check.checked) { + viewReadBooks(); + } else { + render(); + } } function Book(title, author, pages, check) { From cb725642bb5a924ef8232efb11a392b715efbdea Mon Sep 17 00:00:00 2001 From: sedazam Date: Sat, 2 Aug 2025 09:10:46 +0100 Subject: [PATCH 16/58] Clear input fields after submitting a new book --- debugging/book-library/script.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/debugging/book-library/script.js b/debugging/book-library/script.js index 3f1950f2..9dffb701 100644 --- a/debugging/book-library/script.js +++ b/debugging/book-library/script.js @@ -48,6 +48,11 @@ function submit() { } else { render(); } + title.value = ""; + author.value = ""; + pages.value = ""; + check.checked = false; + return false; } function Book(title, author, pages, check) { From 9dd36cb79f9dd9cb477c9807b471be4864cfa613 Mon Sep 17 00:00:00 2001 From: sedazam Date: Sat, 2 Aug 2025 09:14:22 +0100 Subject: [PATCH 17/58] Refactor button group for consistent styling and alignment in the library interface --- debugging/book-library/index.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/debugging/book-library/index.html b/debugging/book-library/index.html index 5130f106..82085ed3 100644 --- a/debugging/book-library/index.html +++ b/debugging/book-library/index.html @@ -23,8 +23,8 @@

Library

Add books to your virtual library

-
- +
+
From 4858f47fb88f27c6228708fc8ad2f522f188bcd3 Mon Sep 17 00:00:00 2001 From: sedazam Date: Sat, 2 Aug 2025 09:18:52 +0100 Subject: [PATCH 18/58] Refactor viewReadBooks function to utilize clearTable for improved readability and efficiency --- debugging/book-library/script.js | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/debugging/book-library/script.js b/debugging/book-library/script.js index 9dffb701..1319f2e0 100644 --- a/debugging/book-library/script.js +++ b/debugging/book-library/script.js @@ -72,16 +72,12 @@ function render() { function viewReadBooks() { let table = document.getElementById("display"); - let rowsNumber = table.rows.length; + clearTable(table); - // Clear existing rows (except header) - for (let n = rowsNumber - 1; n > 0; n--) { - table.deleteRow(n); + const readBooks = myLibrary.filter(book => book.check === true); } // Filter only read books - const readBooks = myLibrary.filter(book => book.check === true); - for (let i = 0; i < readBooks.length; i++) { let row = table.insertRow(1); row.insertCell(0).innerText = readBooks[i].title; @@ -89,12 +85,13 @@ function render() { row.insertCell(2).innerText = readBooks[i].pages; row.insertCell(3).innerText = "Yes"; row.insertCell(4).innerHTML = "-"; - - titleCell.innerHTML = readBooks[i].title; - authorCell.innerHTML = readBooks[i].author; - pagesCell.innerHTML = readBooks[i].pages; - wasReadCell.innerText = "Yes"; - deleteCell.innerHTML = "-"; + } +} +function clearTable(table) { + let rowsNumber = table.rows.length; + //delete old table + for (let n = rowsNumber - 1; n > 0; n--) { + table.deleteRow(n); } } //insert updated row and cells From a4d5f61209b6f6f9d8e2a72146b951570db28cb4 Mon Sep 17 00:00:00 2001 From: sedazam Date: Sat, 2 Aug 2025 09:23:14 +0100 Subject: [PATCH 19/58] Refactor submit and render functions for improved clarity and efficiency --- debugging/book-library/script.js | 133 ++++++++++++------------------- 1 file changed, 49 insertions(+), 84 deletions(-) diff --git a/debugging/book-library/script.js b/debugging/book-library/script.js index 1319f2e0..a57e5713 100644 --- a/debugging/book-library/script.js +++ b/debugging/book-library/script.js @@ -1,6 +1,6 @@ let myLibrary = []; -window.addEventListener("load", function (e) { +window.addEventListener("load", function () { populateStorage(); render(); }); @@ -8,15 +8,8 @@ window.addEventListener("load", function (e) { function populateStorage() { if (myLibrary.length == 0) { let book1 = new Book("Robison Crusoe", "Daniel Defoe", "252", true); - let book2 = new Book( - "The Old Man and the Sea", - "Ernest Hemingway", - "127", - true - ); - myLibrary.push(book1); - myLibrary.push(book2); - render(); + let book2 = new Book("The Old Man and the Sea", "Ernest Hemingway", "127", true); + myLibrary.push(book1, book2); } } @@ -25,33 +18,22 @@ const author = document.getElementById("author"); const pages = document.getElementById("pages"); const check = document.getElementById("check"); -//check the right input from forms and if its ok -> add the new book (object in array) -//via Book function and start render function function submit() { - if ( - title.value == null || - title.value == "" || - pages.value == null || - pages.value == "" || - author.value == null || - author.value == "" - ) { + if (!title.value || !author.value || !pages.value) { alert("Please fill all fields!"); return false; - } else { - let book = new Book(title.value, author.value, pages.value, check.checked); - myLibrary.push(book); - render(); - } - if (check.checked) { - viewReadBooks(); - } else { - render(); } + + let book = new Book(title.value, author.value, pages.value, check.checked); + myLibrary.push(book); + render(); + + // Reset form title.value = ""; author.value = ""; pages.value = ""; check.checked = false; + return false; } @@ -62,79 +44,62 @@ function Book(title, author, pages, check) { this.check = check; } -function render() { +function clearTable() { let table = document.getElementById("display"); - let rowsNumber = table.rows.length; - //delete old table - for (let n = rowsNumber - 1; n > 0; n--) { - table.deleteRow(n); + while (table.rows.length > 1) { + table.deleteRow(1); } +} - function viewReadBooks() { +function render() { + clearTable(); let table = document.getElementById("display"); - clearTable(table); - - const readBooks = myLibrary.filter(book => book.check === true); - } - // Filter only read books - for (let i = 0; i < readBooks.length; i++) { - let row = table.insertRow(1); - row.insertCell(0).innerText = readBooks[i].title; - row.insertCell(1).innerText = readBooks[i].author; - row.insertCell(2).innerText = readBooks[i].pages; - row.insertCell(3).innerText = "Yes"; - row.insertCell(4).innerHTML = "-"; - } -} -function clearTable(table) { - let rowsNumber = table.rows.length; - //delete old table - for (let n = rowsNumber - 1; n > 0; n--) { - table.deleteRow(n); - } -} - //insert updated row and cells - let length = myLibrary.length; - for (let i = 0; i < length; i++) { + myLibrary.forEach((book, i) => { let row = table.insertRow(1); let titleCell = row.insertCell(0); let authorCell = row.insertCell(1); let pagesCell = row.insertCell(2); let wasReadCell = row.insertCell(3); let deleteCell = row.insertCell(4); - titleCell.innerHTML = myLibrary[i].title; - authorCell.innerHTML = myLibrary[i].author; - pagesCell.innerHTML = myLibrary[i].pages; - //add and wait for action for read/unread button + titleCell.innerText = book.title; + authorCell.innerText = book.author; + pagesCell.innerText = book.pages; + let changeBut = document.createElement("button"); - changeBut.id = i; changeBut.className = "btn btn-success"; - wasReadCell.appendChild(changeBut); - let readStatus = ""; - if (myLibrary[i].check == true) { - readStatus = "Yes"; - } else { - readStatus = "No"; - } - changeBut.innerText = readStatus; - - changeBut.addEventListener("click", function () { - myLibrary[i].check = !myLibrary[i].check; + changeBut.innerText = book.check ? "Yes" : "No"; + changeBut.onclick = () => { + book.check = !book.check; render(); - }); + }; + wasReadCell.appendChild(changeBut); - //add delete button to every row and render again let delButton = document.createElement("button"); - delButton.id = i + 5; - deleteCell.appendChild(delButton); delButton.className = "btn btn-warning"; - delButton.innerHTML = "Delete"; - delButton.addEventListener("click", function () { - alert(`You've deleted title: ${myLibrary[i].title}`); + delButton.innerText = "Delete"; + delButton.onclick = () => { + alert(`You've deleted title: ${book.title}`); myLibrary.splice(i, 1); render(); - }); - } + }; + deleteCell.appendChild(delButton); + }); } + +function viewReadBooks() { + clearTable(); + let table = document.getElementById("display"); + + myLibrary + .filter(book => book.check) + .forEach(book => { + let row = table.insertRow(1); + row.insertCell(0).innerText = book.title; + row.insertCell(1).innerText = book.author; + row.insertCell(2).innerText = book.pages; + row.insertCell(3).innerText = "Yes"; + row.insertCell(4).innerText = "-"; + }); +} \ No newline at end of file From fa3eb54d21f40e0c5ebb28e3a452cac84e7b93e2 Mon Sep 17 00:00:00 2001 From: sedazam Date: Sat, 2 Aug 2025 09:27:14 +0100 Subject: [PATCH 20/58] Refactor submit function to improve input validation and clarity --- debugging/book-library/script.js | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/debugging/book-library/script.js b/debugging/book-library/script.js index a57e5713..31993adf 100644 --- a/debugging/book-library/script.js +++ b/debugging/book-library/script.js @@ -19,16 +19,21 @@ const pages = document.getElementById("pages"); const check = document.getElementById("check"); function submit() { - if (!title.value || !author.value || !pages.value) { - alert("Please fill all fields!"); + const titleValue = title.value.trim(); + const authorValue = author.value.trim(); + const pagesValue = pages.value.trim(); + + if (!titleValue || !authorValue || !pagesValue) { + alert("Please fill in all fields before submitting!"); return false; } - let book = new Book(title.value, author.value, pages.value, check.checked); + const book = new Book(titleValue, authorValue, pagesValue, check.checked); myLibrary.push(book); + render(); - // Reset form + // Clear the form title.value = ""; author.value = ""; pages.value = ""; From 8b385086a7111a7739ac146c479801dbd15abfa9 Mon Sep 17 00:00:00 2001 From: sedazam Date: Sun, 3 Aug 2025 10:14:07 +0100 Subject: [PATCH 21/58] Refactor button creation in render function for consistency and clarity --- debugging/book-library/script.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/debugging/book-library/script.js b/debugging/book-library/script.js index 31993adf..e10ffc45 100644 --- a/debugging/book-library/script.js +++ b/debugging/book-library/script.js @@ -72,24 +72,24 @@ function render() { authorCell.innerText = book.author; pagesCell.innerText = book.pages; - let changeBut = document.createElement("button"); - changeBut.className = "btn btn-success"; - changeBut.innerText = book.check ? "Yes" : "No"; - changeBut.onclick = () => { + let changeBtn = document.createElement("button"); + changeBtn.className = "btn btn-success"; + changeBtn.innerText = book.check ? "Yes" : "No"; + changeBtn.onclick = () => { book.check = !book.check; render(); }; - wasReadCell.appendChild(changeBut); + wasReadCell.appendChild(changeBtn); - let delButton = document.createElement("button"); - delButton.className = "btn btn-warning"; - delButton.innerText = "Delete"; - delButton.onclick = () => { + let delBtn = document.createElement("button"); + delBtn.className = "btn btn-warning"; + delBtn.innerText = "Delete"; + delBtn.onclick = () => { alert(`You've deleted title: ${book.title}`); myLibrary.splice(i, 1); render(); }; - deleteCell.appendChild(delButton); + deleteCell.appendChild(delBtn); }); } From 2747277e3ead8197e5c23de036ab0f57925e8da9 Mon Sep 17 00:00:00 2001 From: sedazam Date: Sun, 3 Aug 2025 10:21:40 +0100 Subject: [PATCH 22/58] Fix typo in book title in populateStorage function --- debugging/book-library/script.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debugging/book-library/script.js b/debugging/book-library/script.js index e10ffc45..30ba0c67 100644 --- a/debugging/book-library/script.js +++ b/debugging/book-library/script.js @@ -7,7 +7,7 @@ window.addEventListener("load", function () { function populateStorage() { if (myLibrary.length == 0) { - let book1 = new Book("Robison Crusoe", "Daniel Defoe", "252", true); + let book1 = new Book("Robinson Crusoe", "Daniel Defoe", "252", true); let book2 = new Book("The Old Man and the Sea", "Ernest Hemingway", "127", true); myLibrary.push(book1, book2); } From 9ec60d1a8cb5017e2e59c00096d7e835aa51458f Mon Sep 17 00:00:00 2001 From: sedazam Date: Sun, 3 Aug 2025 10:23:37 +0100 Subject: [PATCH 23/58] Fix pages property assignment in Book constructor to ensure it is always an integer --- debugging/book-library/script.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debugging/book-library/script.js b/debugging/book-library/script.js index 30ba0c67..4b447f06 100644 --- a/debugging/book-library/script.js +++ b/debugging/book-library/script.js @@ -45,7 +45,7 @@ function submit() { function Book(title, author, pages, check) { this.title = title; this.author = author; - this.pages = pages; + this.pages = parseInt(pages) || 0; this.check = check; } From 4996041e8b89a25daedbf25513b26ede3eaf0345 Mon Sep 17 00:00:00 2001 From: sedazam Date: Sun, 3 Aug 2025 10:25:11 +0100 Subject: [PATCH 24/58] Enhance input validation in submit function to ensure pages value is a valid number --- debugging/book-library/script.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/debugging/book-library/script.js b/debugging/book-library/script.js index 4b447f06..4e3b1fa8 100644 --- a/debugging/book-library/script.js +++ b/debugging/book-library/script.js @@ -27,6 +27,10 @@ function submit() { alert("Please fill in all fields before submitting!"); return false; } + if (isNaN(pagesValue) || parseInt(pagesValue) <= 0) { + alert("Please enter a valid number of pages!"); + return false; + } const book = new Book(titleValue, authorValue, pagesValue, check.checked); myLibrary.push(book); From dd0296b1f83cae03c9f2e0ffb2ec13d49dc49b73 Mon Sep 17 00:00:00 2001 From: Seddiq Azam Date: Sun, 3 Aug 2025 15:21:32 +0100 Subject: [PATCH 25/58] Delete .vscode/launch.json --- .vscode/launch.json | 14 -------------- 1 file changed, 14 deletions(-) delete mode 100644 .vscode/launch.json diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index 7c93bc0a..00000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "type": "node", - "name": "Run Current File", - "request": "launch", - "program": "${workspaceFolder}/debugging/book-library/index.html" - } - ] -} \ No newline at end of file From dee27d1a3bc15b3d54c9b9efc82ca50a4eb72ed1 Mon Sep 17 00:00:00 2001 From: sedazam Date: Mon, 11 Aug 2025 21:23:20 +0100 Subject: [PATCH 26/58] Refactor variable names for input elements in script.js for clarity and consistency --- debugging/book-library/script.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/debugging/book-library/script.js b/debugging/book-library/script.js index 4e3b1fa8..2c714314 100644 --- a/debugging/book-library/script.js +++ b/debugging/book-library/script.js @@ -13,15 +13,15 @@ function populateStorage() { } } -const title = document.getElementById("title"); -const author = document.getElementById("author"); -const pages = document.getElementById("pages"); -const check = document.getElementById("check"); +const titleInput = document.getElementById("title"); +const authorInput = document.getElementById("author"); +const pagesInput = document.getElementById("pages"); +const readCheckBox = document.getElementById("check"); function submit() { - const titleValue = title.value.trim(); - const authorValue = author.value.trim(); - const pagesValue = pages.value.trim(); + const titleValue = titleInput.value.trim(); + const authorValue = authorInput.value.trim(); + const pagesValue = pagesInput.value.trim(); if (!titleValue || !authorValue || !pagesValue) { alert("Please fill in all fields before submitting!"); From f9af2c5f8b82a500635f0e72215f582aee26e90a Mon Sep 17 00:00:00 2001 From: sedazam Date: Mon, 11 Aug 2025 21:26:46 +0100 Subject: [PATCH 27/58] Fix reference to read checkbox in Book instantiation in submit function --- debugging/book-library/script.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debugging/book-library/script.js b/debugging/book-library/script.js index 2c714314..90cd62d4 100644 --- a/debugging/book-library/script.js +++ b/debugging/book-library/script.js @@ -32,7 +32,7 @@ function submit() { return false; } - const book = new Book(titleValue, authorValue, pagesValue, check.checked); + const book = new Book(titleValue, authorValue, pagesValue, readCheckBox.checked); myLibrary.push(book); render(); From 04087c0d5280c3ebdc78fba7ba0cd9ba78d80c9e Mon Sep 17 00:00:00 2001 From: sedazam Date: Mon, 11 Aug 2025 21:27:34 +0100 Subject: [PATCH 28/58] Fix variable references for form input clearing in submit function --- debugging/book-library/script.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/debugging/book-library/script.js b/debugging/book-library/script.js index 90cd62d4..1f3f9497 100644 --- a/debugging/book-library/script.js +++ b/debugging/book-library/script.js @@ -38,10 +38,10 @@ function submit() { render(); // Clear the form - title.value = ""; - author.value = ""; - pages.value = ""; - check.checked = false; + titleInput.value = ""; + authorInput.value = ""; + pagesInput.value = ""; + readCheckBox.checked = false; return false; } From e63d74f3c15e0771fe485c8a138ad05d9a6a5468 Mon Sep 17 00:00:00 2001 From: sedazam Date: Mon, 11 Aug 2025 21:28:36 +0100 Subject: [PATCH 29/58] Fix pages argument type in Book instantiation in populateStorage function --- debugging/book-library/script.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/debugging/book-library/script.js b/debugging/book-library/script.js index 1f3f9497..5196506d 100644 --- a/debugging/book-library/script.js +++ b/debugging/book-library/script.js @@ -7,8 +7,8 @@ window.addEventListener("load", function () { function populateStorage() { if (myLibrary.length == 0) { - let book1 = new Book("Robinson Crusoe", "Daniel Defoe", "252", true); - let book2 = new Book("The Old Man and the Sea", "Ernest Hemingway", "127", true); + let book1 = new Book("Robinson Crusoe", "Daniel Defoe", 252, true); + let book2 = new Book("The Old Man and the Sea", "Ernest Hemingway", 127, true); myLibrary.push(book1, book2); } } From 8fe3b51c6b855546bc43665186f83d4727d7cd41 Mon Sep 17 00:00:00 2001 From: sedazam Date: Mon, 11 Aug 2025 21:30:58 +0100 Subject: [PATCH 30/58] Add confirmation dialog before deleting a book from the library --- debugging/book-library/script.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/debugging/book-library/script.js b/debugging/book-library/script.js index 5196506d..4a17ddf0 100644 --- a/debugging/book-library/script.js +++ b/debugging/book-library/script.js @@ -89,9 +89,11 @@ function render() { delBtn.className = "btn btn-warning"; delBtn.innerText = "Delete"; delBtn.onclick = () => { - alert(`You've deleted title: ${book.title}`); - myLibrary.splice(i, 1); - render(); + if (confirm(`Are you sure you want to delete the book titled: ${book.title}?`)) { + alert(`You've deleted title: ${book.title}`); + myLibrary.splice(i, 1); + render(); + } }; deleteCell.appendChild(delBtn); }); From b2a3c2cf69d4a5726645df2ce392a119bf77ac6c Mon Sep 17 00:00:00 2001 From: sedazam Date: Mon, 11 Aug 2025 21:34:09 +0100 Subject: [PATCH 31/58] Refactor render function to use textContent for setting cell values and add confirmation dialog for book deletion --- debugging/book-library/script.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/debugging/book-library/script.js b/debugging/book-library/script.js index 4a17ddf0..2fffa85c 100644 --- a/debugging/book-library/script.js +++ b/debugging/book-library/script.js @@ -72,13 +72,13 @@ function render() { let wasReadCell = row.insertCell(3); let deleteCell = row.insertCell(4); - titleCell.innerText = book.title; - authorCell.innerText = book.author; - pagesCell.innerText = book.pages; + titleCell.textContent = book.title; + authorCell.textContent = book.author; + pagesCell.textContent = book.pages; let changeBtn = document.createElement("button"); changeBtn.className = "btn btn-success"; - changeBtn.innerText = book.check ? "Yes" : "No"; + changeBtn.textContent = book.check ? "Yes" : "No"; changeBtn.onclick = () => { book.check = !book.check; render(); @@ -87,7 +87,7 @@ function render() { let delBtn = document.createElement("button"); delBtn.className = "btn btn-warning"; - delBtn.innerText = "Delete"; + delBtn.textContent = "Delete"; delBtn.onclick = () => { if (confirm(`Are you sure you want to delete the book titled: ${book.title}?`)) { alert(`You've deleted title: ${book.title}`); From ee0bf368c40b1b28aa1cc9e20f08ed795b4c9e86 Mon Sep 17 00:00:00 2001 From: sedazam Date: Mon, 11 Aug 2025 21:35:48 +0100 Subject: [PATCH 32/58] Use const instead of let for table variable in clearTable function --- debugging/book-library/script.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debugging/book-library/script.js b/debugging/book-library/script.js index 2fffa85c..e92e496c 100644 --- a/debugging/book-library/script.js +++ b/debugging/book-library/script.js @@ -54,7 +54,7 @@ function Book(title, author, pages, check) { } function clearTable() { - let table = document.getElementById("display"); + const table = document.getElementById("display"); while (table.rows.length > 1) { table.deleteRow(1); } From db33ada35cd1940cce65defdbe7af1a1d27c8064 Mon Sep 17 00:00:00 2001 From: sedazam Date: Mon, 11 Aug 2025 21:37:40 +0100 Subject: [PATCH 33/58] Refactor clearTable function to improve row deletion logic using tbody --- debugging/book-library/script.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/debugging/book-library/script.js b/debugging/book-library/script.js index e92e496c..db5c1d9d 100644 --- a/debugging/book-library/script.js +++ b/debugging/book-library/script.js @@ -55,8 +55,9 @@ function Book(title, author, pages, check) { function clearTable() { const table = document.getElementById("display"); - while (table.rows.length > 1) { - table.deleteRow(1); + const tbody = table.querySelector("tbody") || table; + while (tbody.children.length > 0) { + tbody.removeChild(tbody.lastChild); } } From 446915cbc744274cedd05fda5b1b19b6c73cbefd Mon Sep 17 00:00:00 2001 From: sedazam Date: Mon, 11 Aug 2025 22:01:46 +0100 Subject: [PATCH 34/58] Fix clearTable function to use lastElementChild and update delete confirmation alert; refactor viewReadBooks to use textContent for consistency --- debugging/book-library/script.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/debugging/book-library/script.js b/debugging/book-library/script.js index db5c1d9d..3cf49be8 100644 --- a/debugging/book-library/script.js +++ b/debugging/book-library/script.js @@ -57,7 +57,7 @@ function clearTable() { const table = document.getElementById("display"); const tbody = table.querySelector("tbody") || table; while (tbody.children.length > 0) { - tbody.removeChild(tbody.lastChild); + tbody.removeChild(tbody.lastElementChild); } } @@ -91,9 +91,9 @@ function render() { delBtn.textContent = "Delete"; delBtn.onclick = () => { if (confirm(`Are you sure you want to delete the book titled: ${book.title}?`)) { - alert(`You've deleted title: ${book.title}`); myLibrary.splice(i, 1); render(); + alert(`You've deleted title: ${book.title}`); } }; deleteCell.appendChild(delBtn); @@ -108,10 +108,10 @@ function viewReadBooks() { .filter(book => book.check) .forEach(book => { let row = table.insertRow(1); - row.insertCell(0).innerText = book.title; - row.insertCell(1).innerText = book.author; - row.insertCell(2).innerText = book.pages; - row.insertCell(3).innerText = "Yes"; - row.insertCell(4).innerText = "-"; + row.insertCell(0).textContent = book.title; + row.insertCell(1).textContent = book.author; + row.insertCell(2).textContent = book.pages; + row.insertCell(3).textContent = "Yes"; + row.insertCell(4).textContent = "-"; }); } \ No newline at end of file From 468764866832852ea62dc4b508a760d8cc9ebd0f Mon Sep 17 00:00:00 2001 From: sedazam Date: Mon, 11 Aug 2025 22:05:11 +0100 Subject: [PATCH 35/58] Refactor submit function to move clearForm definition inside and improve readability --- debugging/book-library/script.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/debugging/book-library/script.js b/debugging/book-library/script.js index 3cf49be8..a7fd7655 100644 --- a/debugging/book-library/script.js +++ b/debugging/book-library/script.js @@ -36,15 +36,17 @@ function submit() { myLibrary.push(book); render(); - - // Clear the form - titleInput.value = ""; - authorInput.value = ""; - pagesInput.value = ""; - readCheckBox.checked = false; + clearForm(); return false; -} + + // Clear the form + function clearForm() { + titleInput.value = ""; + authorInput.value = ""; + pagesInput.value = ""; + readCheckBox.checked = false; + } function Book(title, author, pages, check) { this.title = title; From 62b75cf412df929940ebe60e593138d4cb70f08f Mon Sep 17 00:00:00 2001 From: sedazam Date: Mon, 11 Aug 2025 22:12:27 +0100 Subject: [PATCH 36/58] Refactor clearForm function to improve structure and readability --- debugging/book-library/script.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/debugging/book-library/script.js b/debugging/book-library/script.js index a7fd7655..f3e698a8 100644 --- a/debugging/book-library/script.js +++ b/debugging/book-library/script.js @@ -39,12 +39,13 @@ function submit() { clearForm(); return false; +} - // Clear the form - function clearForm() { - titleInput.value = ""; - authorInput.value = ""; - pagesInput.value = ""; +// Clear the form +function clearForm() { + titleInput.value = ""; + authorInput.value = ""; + pagesInput.value = ""; readCheckBox.checked = false; } From 9fbf9f9ef0a632e0009d24c7560e0cb181eb9d51 Mon Sep 17 00:00:00 2001 From: sedazam Date: Mon, 11 Aug 2025 22:19:41 +0100 Subject: [PATCH 37/58] Fix indentation in clearForm function for consistency --- debugging/book-library/script.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debugging/book-library/script.js b/debugging/book-library/script.js index f3e698a8..1c918c87 100644 --- a/debugging/book-library/script.js +++ b/debugging/book-library/script.js @@ -46,7 +46,7 @@ function clearForm() { titleInput.value = ""; authorInput.value = ""; pagesInput.value = ""; - readCheckBox.checked = false; + readCheckBox.checked = false; } function Book(title, author, pages, check) { From a3af05a069f21f362b12503281dba128b3c5ed68 Mon Sep 17 00:00:00 2001 From: sedazam Date: Tue, 12 Aug 2025 12:24:05 +0100 Subject: [PATCH 38/58] Add title to HTML document for better context --- debugging/book-library/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debugging/book-library/index.html b/debugging/book-library/index.html index 82085ed3..89884dc4 100644 --- a/debugging/book-library/index.html +++ b/debugging/book-library/index.html @@ -1,7 +1,7 @@ - + My Book Library Date: Tue, 12 Aug 2025 12:25:03 +0100 Subject: [PATCH 39/58] Fix formatting of meta tags in HTML for consistency --- debugging/book-library/index.html | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/debugging/book-library/index.html b/debugging/book-library/index.html index 89884dc4..55531f31 100644 --- a/debugging/book-library/index.html +++ b/debugging/book-library/index.html @@ -2,11 +2,8 @@ My Book Library - + + From 0232a7cadf96d37921c6eef9fe98acd2330062a4 Mon Sep 17 00:00:00 2001 From: sedazam Date: Tue, 12 Aug 2025 12:26:10 +0100 Subject: [PATCH 40/58] Remove empty table row in book display for cleaner presentation --- debugging/book-library/index.html | 5 ----- 1 file changed, 5 deletions(-) diff --git a/debugging/book-library/index.html b/debugging/book-library/index.html index 55531f31..4d9fdcf9 100644 --- a/debugging/book-library/index.html +++ b/debugging/book-library/index.html @@ -81,11 +81,6 @@

Library

- - - - - From 340a5b961819130ec679ae3877a36bb2bf187536 Mon Sep 17 00:00:00 2001 From: sedazam Date: Tue, 12 Aug 2025 12:36:22 +0100 Subject: [PATCH 41/58] Improve checkbox label for clarity in book submission form --- debugging/book-library/index.html | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/debugging/book-library/index.html b/debugging/book-library/index.html index 4d9fdcf9..7612956d 100644 --- a/debugging/book-library/index.html +++ b/debugging/book-library/index.html @@ -57,8 +57,7 @@

Library

type="checkbox" class="form-check-input" id="check" - value="" - />Read + /> I have read this book Date: Tue, 12 Aug 2025 12:38:12 +0100 Subject: [PATCH 42/58] Replace submit input with button for better user interaction in book submission form --- debugging/book-library/index.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/debugging/book-library/index.html b/debugging/book-library/index.html index 7612956d..7175ddda 100644 --- a/debugging/book-library/index.html +++ b/debugging/book-library/index.html @@ -59,12 +59,12 @@

Library

id="check" /> I have read this book - + > Add Book +
From 10fe9904bf5bfafd9013ce29102477552a317cb2 Mon Sep 17 00:00:00 2001 From: sedazam Date: Tue, 12 Aug 2025 12:39:04 +0100 Subject: [PATCH 43/58] Add header for actions column in book display table --- debugging/book-library/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debugging/book-library/index.html b/debugging/book-library/index.html index 7175ddda..cc4c8a56 100644 --- a/debugging/book-library/index.html +++ b/debugging/book-library/index.html @@ -75,7 +75,7 @@

Library

Author Number of Pages Read - + Actions From 80d82497b0ec95a00a605e717cfa76cbfef47d1a Mon Sep 17 00:00:00 2001 From: sedazam Date: Tue, 12 Aug 2025 12:40:35 +0100 Subject: [PATCH 44/58] Fix row insertion in render function to use tbody for correct table structure --- debugging/book-library/script.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/debugging/book-library/script.js b/debugging/book-library/script.js index 1c918c87..7e3ed88d 100644 --- a/debugging/book-library/script.js +++ b/debugging/book-library/script.js @@ -67,9 +67,10 @@ function clearTable() { function render() { clearTable(); let table = document.getElementById("display"); + let tbody = table.querySelector("tbody"); myLibrary.forEach((book, i) => { - let row = table.insertRow(1); + let row = tbody.insertRow(); let titleCell = row.insertCell(0); let authorCell = row.insertCell(1); let pagesCell = row.insertCell(2); From 9e6373900e07aa3625910b0bc4d27b1b5fc04376 Mon Sep 17 00:00:00 2001 From: sedazam Date: Wed, 13 Aug 2025 12:14:21 +0100 Subject: [PATCH 45/58] Add buttons for toggling read status and deleting books in viewReadBooks function --- debugging/book-library/script.js | 37 ++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/debugging/book-library/script.js b/debugging/book-library/script.js index 7e3ed88d..1305c9af 100644 --- a/debugging/book-library/script.js +++ b/debugging/book-library/script.js @@ -86,7 +86,11 @@ function render() { changeBtn.textContent = book.check ? "Yes" : "No"; changeBtn.onclick = () => { book.check = !book.check; - render(); + if (book.check) { + viewReadBooks(); + } else { + render(); + } }; wasReadCell.appendChild(changeBtn); @@ -107,15 +111,40 @@ function render() { function viewReadBooks() { clearTable(); let table = document.getElementById("display"); + let tbody = table.querySelector("tbody"); myLibrary .filter(book => book.check) .forEach(book => { - let row = table.insertRow(1); + let row = tbody.insertRow(); row.insertCell(0).textContent = book.title; row.insertCell(1).textContent = book.author; row.insertCell(2).textContent = book.pages; - row.insertCell(3).textContent = "Yes"; - row.insertCell(4).textContent = "-"; + + let changeBtn = document.createElement("button"); + let wasReadCell = row.insertCell(3); + changeBtn.className = "btn btn-success"; + changeBtn.textContent = "Yes"; + changeBtn.onclick = () => { + book.check = !book.check; + if (book.check) { + changeBtn.textContent = "Yes"; + } + viewReadBooks(); + }; + wasReadCell.appendChild(changeBtn); + + let deleteCell = row.insertCell(4); + let delBtn = document.createElement("button"); + delBtn.className = "btn btn-warning"; + delBtn.textContent = "Delete"; + delBtn.onclick = () => { + if (confirm(`Are you sure you want to delete ${book.title}?`)) { + myLibrary.splice(myLibrary.indexOf(book), 1); + viewReadBooks(); // Refresh the filtered view + } + }; + deleteCell.appendChild(delBtn); }); + } } \ No newline at end of file From f3427a1fc81cce13d0df2080b2daf3290f396920 Mon Sep 17 00:00:00 2001 From: sedazam Date: Wed, 13 Aug 2025 12:19:37 +0100 Subject: [PATCH 46/58] Enhance read status button functionality and improve delete confirmation in viewReadBooks --- debugging/book-library/script.js | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/debugging/book-library/script.js b/debugging/book-library/script.js index 1305c9af..2f6ca4a0 100644 --- a/debugging/book-library/script.js +++ b/debugging/book-library/script.js @@ -87,8 +87,12 @@ function render() { changeBtn.onclick = () => { book.check = !book.check; if (book.check) { + changeBtn.textContent = "Yes"; + changeBtn.className = "btn btn-success"; viewReadBooks(); } else { + changeBtn.textContent = "No"; + changeBtn.className = "btn btn-danger"; render(); } }; @@ -123,28 +127,28 @@ function viewReadBooks() { let changeBtn = document.createElement("button"); let wasReadCell = row.insertCell(3); - changeBtn.className = "btn btn-success"; - changeBtn.textContent = "Yes"; - changeBtn.onclick = () => { - book.check = !book.check; - if (book.check) { + changeBtn.className = "btn btn-success"; changeBtn.textContent = "Yes"; - } - viewReadBooks(); - }; - wasReadCell.appendChild(changeBtn); + changeBtn.onclick = () => { + book.check = !book.check; + if (book.check) { + changeBtn.textContent = "Yes"; + } else { + render(); + } + }; + wasReadCell.appendChild(changeBtn); - let deleteCell = row.insertCell(4); + let deleteCell = row.insertCell(4); let delBtn = document.createElement("button"); delBtn.className = "btn btn-warning"; delBtn.textContent = "Delete"; delBtn.onclick = () => { if (confirm(`Are you sure you want to delete ${book.title}?`)) { myLibrary.splice(myLibrary.indexOf(book), 1); - viewReadBooks(); // Refresh the filtered view + viewReadBooks(); } }; deleteCell.appendChild(delBtn); }); - } -} \ No newline at end of file + } \ No newline at end of file From 1db3d2aad173fa8fd56b111d5500eda6cee66ad6 Mon Sep 17 00:00:00 2001 From: sedazam Date: Wed, 13 Aug 2025 12:29:00 +0100 Subject: [PATCH 47/58] Refactor book submission form for improved accessibility and user experience --- debugging/book-library/index.html | 214 ++++++++++++++++++++---------- 1 file changed, 146 insertions(+), 68 deletions(-) diff --git a/debugging/book-library/index.html b/debugging/book-library/index.html index cc4c8a56..0c7eb510 100644 --- a/debugging/book-library/index.html +++ b/debugging/book-library/index.html @@ -1,7 +1,7 @@ - + - My Book Library + My Book Library @@ -15,75 +15,153 @@ -
-

Library

-

Add books to your virtual library

-
+
+
+
+

My Book Library

+

Add books to your virtual library and track your reading progress

+
+
-
- - - -
+
+ -
-
- - - - - - - - -
-
+
+
+
+

Add New Book Form

+ +
+ + + + Enter the full title of the book + +
+ +
+ + + + Enter the author's full name + +
- - - - - - - - - - - - - - -
TitleAuthorNumber of PagesReadActions
+
+ + + + Enter the total number of pages in the book + +
+ +
+ + + + Check this box if you have already read this book + +
+ + + + Click to add this book to your library + +
+
+
+ +
+

Book Library Table

+ + + + + + + + + + + + + +
+ A table showing all books in your library with their details and actions +
TitleAuthorNumber of PagesRead StatusActions
+
+
+
- + \ No newline at end of file From 7fcf6fc18d9da79c81b098a7c5d846b12bf5dc06 Mon Sep 17 00:00:00 2001 From: sedazam Date: Wed, 13 Aug 2025 13:35:11 +0100 Subject: [PATCH 48/58] Refactor HTML structure and enhance JavaScript functionality for improved user experience and accessibility --- debugging/book-library/index.html | 218 ++++----------- debugging/book-library/script.js | 446 +++++++++++++++++++++--------- debugging/book-library/style.css | 166 ++++++++++- 3 files changed, 533 insertions(+), 297 deletions(-) diff --git a/debugging/book-library/index.html b/debugging/book-library/index.html index 0c7eb510..7603a8ea 100644 --- a/debugging/book-library/index.html +++ b/debugging/book-library/index.html @@ -1,167 +1,69 @@ - + My Book Library - - - - - - - - + + + + + +
-
-
-

My Book Library

-

Add books to your virtual library and track your reading progress

-
-
- -
- - -
-
-
-

Add New Book Form

- -
- - - - Enter the full title of the book - -
- -
- - - - Enter the author's full name - -
- -
- - - - Enter the total number of pages in the book - -
- -
- - - - Check this box if you have already read this book - -
- - - - Click to add this book to your library - -
-
-
- -
-

Book Library Table

- - - - - - - - - - - - - -
- A table showing all books in your library with their details and actions -
TitleAuthorNumber of PagesRead StatusActions
-
-
+
+
+

My Book Library

+

Add books to your virtual library and track your reading progress

+
+
+ +
+
+ +
+ + + +
+ +
+
+ + + + + + + + + +
+ + +
+ + +
+
+ + + + + + + + + + + + +
TitleAuthorPagesRead StatusActions
+
- + + + - + \ No newline at end of file diff --git a/debugging/book-library/script.js b/debugging/book-library/script.js index 2f6ca4a0..f2de8f9e 100644 --- a/debugging/book-library/script.js +++ b/debugging/book-library/script.js @@ -1,154 +1,340 @@ let myLibrary = []; -window.addEventListener("load", function () { - populateStorage(); - render(); +window.addEventListener("load", function() { + console.log("Page loaded, initializing library..."); + populateStorage(); + render(); }); -function populateStorage() { - if (myLibrary.length == 0) { - let book1 = new Book("Robinson Crusoe", "Daniel Defoe", 252, true); - let book2 = new Book("The Old Man and the Sea", "Ernest Hemingway", 127, true); - myLibrary.push(book1, book2); - } +function Book(title, author, pages, isRead) { + this.title = title; + this.author = author; + this.pages = parseInt(pages) || 0; + this.isRead = isRead || false; } -const titleInput = document.getElementById("title"); -const authorInput = document.getElementById("author"); -const pagesInput = document.getElementById("pages"); -const readCheckBox = document.getElementById("check"); +function populateStorage() { + if (myLibrary.length === 0) { + let book1 = new Book("Robinson Crusoe", "Daniel Defoe", 252, true); + let book2 = new Book("The Old Man and the Sea", "Ernest Hemingway", 127, true); + let book3 = new Book("How to Code", "Seddiq Azam", 324, false); + + myLibrary.push(book1, book2, book3); + console.log("Added initial books:", myLibrary); + } +} -function submit() { - const titleValue = titleInput.value.trim(); - const authorValue = authorInput.value.trim(); - const pagesValue = pagesInput.value.trim(); +function addBook() { + console.log("Add book button clicked!"); + + const titleInput = document.getElementById("title"); + const authorInput = document.getElementById("author"); + const pagesInput = document.getElementById("pages"); + const checkInput = document.getElementById("check"); + + if (!titleInput || !authorInput || !pagesInput || !checkInput) { + showAlert("Form elements not found! Please refresh the page.", "danger"); + return; + } + + const title = titleInput.value.trim(); + const author = authorInput.value.trim(); + const pages = pagesInput.value.trim(); + const isRead = checkInput.checked; + + console.log("Form values:", { title, author, pages, isRead }); + + if (!title || !author || !pages) { + showAlert("Please fill in all required fields (Title, Author, and Pages)!", "warning"); + highlightEmptyFields(title, author, pages); + return; + } + + if (isNaN(pages) || parseInt(pages) <= 0) { + showAlert("Please enter a valid number of pages (greater than 0)!", "warning"); + pagesInput.classList.add("is-invalid"); + return; + } + + const duplicate = myLibrary.find(book => + book.title.toLowerCase() === title.toLowerCase() && + book.author.toLowerCase() === author.toLowerCase() + ); + + if (duplicate) { + showAlert(`This book "${title}" by ${author} is already in your library!`, "info"); + return; + } + + const newBook = new Book(title, author, pages, isRead); + console.log("Created new book:", newBook); + + myLibrary.push(newBook); + console.log("Library after adding book:", myLibrary.length, "total books"); + + render(); + + clearForm(); + + showAlert(`Successfully added "${title}" by ${author} to your library!`, "success"); + + if (typeof $ !== 'undefined') { + $("#demo").collapse('hide'); + } +} - if (!titleValue || !authorValue || !pagesValue) { - alert("Please fill in all fields before submitting!"); - return false; - } - if (isNaN(pagesValue) || parseInt(pagesValue) <= 0) { - alert("Please enter a valid number of pages!"); - return false; - } +function highlightEmptyFields(title, author, pages) { + const titleInput = document.getElementById("title"); + const authorInput = document.getElementById("author"); + const pagesInput = document.getElementById("pages"); + + [titleInput, authorInput, pagesInput].forEach(input => { + input.classList.remove("is-invalid", "is-valid"); + }); + + if (!title) titleInput.classList.add("is-invalid"); + if (!author) authorInput.classList.add("is-invalid"); + if (!pages) pagesInput.classList.add("is-invalid"); +} - const book = new Book(titleValue, authorValue, pagesValue, readCheckBox.checked); - myLibrary.push(book); +function clearForm() { + const titleInput = document.getElementById("title"); + const authorInput = document.getElementById("author"); + const pagesInput = document.getElementById("pages"); + const checkInput = document.getElementById("check"); + + if (titleInput) { + titleInput.value = ""; + titleInput.classList.remove("is-invalid", "is-valid"); + } + if (authorInput) { + authorInput.value = ""; + authorInput.classList.remove("is-invalid", "is-valid"); + } + if (pagesInput) { + pagesInput.value = ""; + pagesInput.classList.remove("is-invalid", "is-valid"); + } + if (checkInput) { + checkInput.checked = false; + } + + console.log("Form cleared"); +} - render(); - clearForm(); +function render() { + console.log("Rendering library with", myLibrary.length, "books"); + clearTable(); + + // Hide the form when switching to all books view + if (typeof $ !== 'undefined') { + $("#demo").collapse('hide'); + } else { + const demoElement = document.getElementById("demo"); + if (demoElement && demoElement.classList.contains("show")) { + demoElement.classList.remove("show"); + } + } + + const tbody = document.querySelector("#display tbody"); + if (!tbody) { + console.error("Could not find table body element!"); + return; + } + + if (myLibrary.length === 0) { + showEmptyState("Your library is empty. Add some books to get started!"); + return; + } + + myLibrary.forEach((book, index) => { + const row = tbody.insertRow(); + + const titleCell = row.insertCell(0); + titleCell.textContent = book.title; + titleCell.style.fontWeight = "bold"; + + const authorCell = row.insertCell(1); + authorCell.textContent = book.author; + + const pagesCell = row.insertCell(2); + pagesCell.textContent = book.pages; + + const statusCell = row.insertCell(3); + const statusBtn = createStatusButton(book, index); + statusCell.appendChild(statusBtn); + + const actionCell = row.insertCell(4); + const deleteBtn = createDeleteButton(book, index); + actionCell.appendChild(deleteBtn); + }); +} - return false; +function createStatusButton(book, index) { + const btn = document.createElement("button"); + btn.className = book.isRead ? "btn btn-success btn-sm" : "btn btn-danger btn-sm"; + btn.textContent = book.isRead ? "Read" : "Not Read"; + btn.onclick = () => toggleReadStatus(index); + return btn; } -// Clear the form -function clearForm() { - titleInput.value = ""; - authorInput.value = ""; - pagesInput.value = ""; - readCheckBox.checked = false; - } - -function Book(title, author, pages, check) { - this.title = title; - this.author = author; - this.pages = parseInt(pages) || 0; - this.check = check; +function createDeleteButton(book, index) { + const btn = document.createElement("button"); + btn.className = "btn btn-warning btn-sm"; + btn.textContent = "Delete"; + btn.onclick = () => deleteBook(index); + return btn; } function clearTable() { - const table = document.getElementById("display"); - const tbody = table.querySelector("tbody") || table; - while (tbody.children.length > 0) { - tbody.removeChild(tbody.lastElementChild); - } + const tbody = document.querySelector("#display tbody"); + if (tbody) { + tbody.innerHTML = ""; + } } -function render() { - clearTable(); - let table = document.getElementById("display"); - let tbody = table.querySelector("tbody"); - - myLibrary.forEach((book, i) => { - let row = tbody.insertRow(); - let titleCell = row.insertCell(0); - let authorCell = row.insertCell(1); - let pagesCell = row.insertCell(2); - let wasReadCell = row.insertCell(3); - let deleteCell = row.insertCell(4); - - titleCell.textContent = book.title; - authorCell.textContent = book.author; - pagesCell.textContent = book.pages; - - let changeBtn = document.createElement("button"); - changeBtn.className = "btn btn-success"; - changeBtn.textContent = book.check ? "Yes" : "No"; - changeBtn.onclick = () => { - book.check = !book.check; - if (book.check) { - changeBtn.textContent = "Yes"; - changeBtn.className = "btn btn-success"; - viewReadBooks(); - } else { - changeBtn.textContent = "No"; - changeBtn.className = "btn btn-danger"; - render(); - } - }; - wasReadCell.appendChild(changeBtn); - - let delBtn = document.createElement("button"); - delBtn.className = "btn btn-warning"; - delBtn.textContent = "Delete"; - delBtn.onclick = () => { - if (confirm(`Are you sure you want to delete the book titled: ${book.title}?`)) { - myLibrary.splice(i, 1); +function showEmptyState(message) { + const tbody = document.querySelector("#display tbody"); + if (tbody) { + const row = tbody.insertRow(); + const cell = row.insertCell(0); + cell.colSpan = 5; + cell.className = "text-center text-muted"; + cell.textContent = message; + } +} + +function toggleReadStatus(index) { + const book = myLibrary[index]; + if (book) { + book.isRead = !book.isRead; + console.log(`Toggled read status for "${book.title}" to ${book.isRead ? "Read" : "Not Read"}`); render(); - alert(`You've deleted title: ${book.title}`); - } - }; - deleteCell.appendChild(delBtn); - }); + + const statusMessage = book.isRead ? "marked as read" : "marked as unread"; + showAlert(`"${book.title}" ${statusMessage}!`, "info"); + } } -function viewReadBooks() { - clearTable(); - let table = document.getElementById("display"); - let tbody = table.querySelector("tbody"); - - myLibrary - .filter(book => book.check) - .forEach(book => { - let row = tbody.insertRow(); - row.insertCell(0).textContent = book.title; - row.insertCell(1).textContent = book.author; - row.insertCell(2).textContent = book.pages; - - let changeBtn = document.createElement("button"); - let wasReadCell = row.insertCell(3); - changeBtn.className = "btn btn-success"; - changeBtn.textContent = "Yes"; - changeBtn.onclick = () => { - book.check = !book.check; - if (book.check) { - changeBtn.textContent = "Yes"; - } else { - render(); +function deleteBook(index) { + const book = myLibrary[index]; + if (book) { + if (confirm(`Are you sure you want to delete "${book.title}" from your library?`)) { + const deletedBook = myLibrary.splice(index, 1)[0]; + console.log(`Deleted book "${deletedBook.title}" from library`); + render(); + showAlert(`"${deletedBook.title}" has been removed from your library!`, "warning"); } - }; - wasReadCell.appendChild(changeBtn); - - let deleteCell = row.insertCell(4); - let delBtn = document.createElement("button"); - delBtn.className = "btn btn-warning"; - delBtn.textContent = "Delete"; - delBtn.onclick = () => { - if (confirm(`Are you sure you want to delete ${book.title}?`)) { - myLibrary.splice(myLibrary.indexOf(book), 1); - viewReadBooks(); + } +} + +function viewReadBooks() { + console.log("Viewing read books only"); + clearTable(); + + // Hide the form when switching to read books view + if (typeof $ !== 'undefined') { + $("#demo").collapse('hide'); + } else { + const demoElement = document.getElementById("demo"); + if (demoElement && demoElement.classList.contains("show")) { + demoElement.classList.remove("show"); } - }; - deleteCell.appendChild(delBtn); + } + + const tbody = document.querySelector("#display tbody"); + if (!tbody) { + console.error("Could not find table body element!"); + return; + } + + const readBooks = myLibrary.filter(book => book.isRead); + + if (readBooks.length === 0) { + showEmptyState("You haven't read any books yet!"); + return; + } + + readBooks.forEach((book, index) => { + const row = tbody.insertRow(); + + const titleCell = row.insertCell(0); + titleCell.textContent = book.title; + titleCell.style.fontWeight = "bold"; + + const authorCell = row.insertCell(1); + authorCell.textContent = book.author; + + const pagesCell = row.insertCell(2); + pagesCell.textContent = book.pages; + + const statusCell = row.insertCell(3); + const statusBtn = document.createElement("button"); + statusBtn.className = "btn btn-success btn-sm"; + statusBtn.textContent = "Read"; + statusBtn.onclick = () => { + book.isRead = !book.isRead; + render(); // Switch back to full view + }; + statusCell.appendChild(statusBtn); + + const actionCell = row.insertCell(4); + const deleteBtn = document.createElement("button"); + deleteBtn.className = "btn btn-warning btn-sm"; + deleteBtn.textContent = "Delete"; + deleteBtn.onclick = () => { + if (confirm(`Are you sure you want to delete "${book.title}" from your library?`)) { + myLibrary.splice(myLibrary.indexOf(book), 1); + viewReadBooks(); // Refresh the filtered view + } + }; + actionCell.appendChild(deleteBtn); }); - } \ No newline at end of file +} + +function showAlert(message, type) { + const alertContainer = document.getElementById("alertContainer"); + if (!alertContainer) { + console.error("Alert container not found!"); + return; + } + + const alert = document.createElement("div"); + alert.className = `alert alert-${type} alert-dismissible fade show`; + alert.innerHTML = ` + ${getAlertIcon(type)} + ${message} + + `; + + alertContainer.appendChild(alert); + + setTimeout(() => { + alert.classList.remove("show"); + setTimeout(() => { + alertContainer.removeChild(alert); + }, 150); + }, 5000); +} + +function getAlertIcon(type) { + switch (type) { + case "success": return ' '; + case "warning": return ' '; + case "danger": return ' '; + case "info": return ' '; + default: return ''; + } +} + +document.addEventListener('keydown', function(event) { + if (event.key === 'Escape') { + if (typeof $ !== 'undefined') { + $("#demo").collapse('hide'); + } + } +}); + +console.log("Book Library JavaScript loaded successfully!"); \ No newline at end of file diff --git a/debugging/book-library/style.css b/debugging/book-library/style.css index 1f8a84ee..6f7a0d6d 100644 --- a/debugging/book-library/style.css +++ b/debugging/book-library/style.css @@ -1,21 +1,169 @@ .form-group { - max-width: 400px; - padding: 20px; - margin: auto; + max-width: 400px; + padding: 20px; + margin: auto; } button.btn { - margin: 10px; + margin: 10px; } + .row .btn { - margin-right: 10px; + margin-right: 10px; } .form-check-label { - padding-left: 20px; - margin: 5px 0px 5px 0px; + padding-left: 20px; + margin: 5px 0px 5px 0px; +} + +.jumbotron { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + color: white; + margin-bottom: 2rem; + border-radius: 0.5rem; +} + +.collapse { + background: white; + padding: 2rem; + border-radius: 8px; + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); + margin-bottom: 2rem; + border: 1px solid #e9ecef; +} + +.container { + background: #f8f9fa; + min-height: 100vh; + padding-bottom: 2rem; + padding-top: 1rem; +} + +.table { + margin-top: 1rem; + background: white; + border-radius: 0.5rem; + overflow: hidden; + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); +} + +.table-responsive { + border-radius: 0.5rem; +} + +.table-striped > tbody > tr:nth-of-type(odd) > td { + background-color: rgba(0, 123, 255, 0.05); +} + +.btn:hover { + transform: translateY(-1px); + transition: all 0.2s ease; + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); +} + +#alertContainer { + position: relative; + z-index: 1000; +} + +.alert { + margin-bottom: 1rem; + border-radius: 0.5rem; } -button.btn-info { - margin: 20px; +nav[role="navigation"] { + background: white; + padding: 1rem; + border-radius: 0.5rem; + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); + margin-bottom: 1rem; } + +.form-control:focus { + border-color: #667eea; + box-shadow: 0 0 0 0.2rem rgba(102, 126, 234, 0.25); +} + +@media (max-width: 768px) { + .btn { + margin: 5px 2px; + font-size: 0.9rem; + padding: 0.375rem 0.75rem; + } + + .form-group { + max-width: 100%; + padding: 15px; + } + + .table-responsive { + font-size: 0.9rem; + } + + .jumbotron { + padding: 1.5rem 1rem; + } + + .jumbotron h1 { + font-size: 2rem; + } + + .collapse { + padding: 1rem; + } + + nav[role="navigation"] { + padding: 0.5rem; + } +} + +@media (max-width: 576px) { + .btn { + width: 100%; + margin: 5px 0; + } + + .table { + font-size: 0.8rem; + } + + .btn-sm { + font-size: 0.7rem; + padding: 0.2rem 0.5rem; + } +} + +.btn:disabled { + opacity: 0.6; + cursor: not-allowed; +} + +.form-control.is-valid { + border-color: #28a745; +} + +.form-control.is-invalid { + border-color: #dc3545; +} + +.btn-primary { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + border: none; +} + +.btn-primary:hover { + background: linear-gradient(135deg, #5a67d8 0%, #6b46c1 100%); + border: none; +} + +.table .btn-sm { + padding: 0.25rem 0.5rem; + font-size: 0.875rem; + margin: 0 2px; +} + +.text-muted { + font-style: italic; + padding: 2rem; +} \ No newline at end of file From 2c17c9adadec496ecb74481d27a6359991e20bfc Mon Sep 17 00:00:00 2001 From: sedazam Date: Wed, 13 Aug 2025 13:39:40 +0100 Subject: [PATCH 49/58] Add title attribute to delete button for improved accessibility --- debugging/book-library/script.js | 1 + 1 file changed, 1 insertion(+) diff --git a/debugging/book-library/script.js b/debugging/book-library/script.js index f2de8f9e..64e72536 100644 --- a/debugging/book-library/script.js +++ b/debugging/book-library/script.js @@ -182,6 +182,7 @@ function createDeleteButton(book, index) { const btn = document.createElement("button"); btn.className = "btn btn-warning btn-sm"; btn.textContent = "Delete"; + btn.title = `Delete "${book.title}"`; btn.onclick = () => deleteBook(index); return btn; } From b1bde3e7cf9fe2bb212ca2dddaa65e0de43f8aaf Mon Sep 17 00:00:00 2001 From: sedazam Date: Wed, 13 Aug 2025 13:45:47 +0100 Subject: [PATCH 50/58] Add aria-label to delete button for improved accessibility --- debugging/book-library/script.js | 1 + 1 file changed, 1 insertion(+) diff --git a/debugging/book-library/script.js b/debugging/book-library/script.js index 64e72536..ebacf04d 100644 --- a/debugging/book-library/script.js +++ b/debugging/book-library/script.js @@ -183,6 +183,7 @@ function createDeleteButton(book, index) { btn.className = "btn btn-warning btn-sm"; btn.textContent = "Delete"; btn.title = `Delete "${book.title}"`; + btn.setAttribute("aria-label", `Delete ${book.title}`); // Accessibility improvement btn.onclick = () => deleteBook(index); return btn; } From a5bb00a263de148164a35b1f62f120fbc166040c Mon Sep 17 00:00:00 2001 From: sedazam Date: Wed, 13 Aug 2025 13:46:40 +0100 Subject: [PATCH 51/58] Enhance accessibility of read status button by adding title and aria-label attributes --- debugging/book-library/script.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/debugging/book-library/script.js b/debugging/book-library/script.js index ebacf04d..6cbb1127 100644 --- a/debugging/book-library/script.js +++ b/debugging/book-library/script.js @@ -174,6 +174,8 @@ function createStatusButton(book, index) { const btn = document.createElement("button"); btn.className = book.isRead ? "btn btn-success btn-sm" : "btn btn-danger btn-sm"; btn.textContent = book.isRead ? "Read" : "Not Read"; + btn.title = `Mark "${book.title}" as ${book.isRead ? "unread" : "read"}`; // Use book parameter + btn.setAttribute("aria-label", btn.title); // Accessibility improvement btn.onclick = () => toggleReadStatus(index); return btn; } From 02416c57dbf16e8c68c4112153db19b3dd51af59 Mon Sep 17 00:00:00 2001 From: sedazam Date: Wed, 13 Aug 2025 13:56:24 +0100 Subject: [PATCH 52/58] Refactor deleteBook function to accept title and author parameters, and update createDeleteButton for improved functionality and accessibility --- debugging/book-library/script.js | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/debugging/book-library/script.js b/debugging/book-library/script.js index 6cbb1127..bc7b5c07 100644 --- a/debugging/book-library/script.js +++ b/debugging/book-library/script.js @@ -180,16 +180,6 @@ function createStatusButton(book, index) { return btn; } -function createDeleteButton(book, index) { - const btn = document.createElement("button"); - btn.className = "btn btn-warning btn-sm"; - btn.textContent = "Delete"; - btn.title = `Delete "${book.title}"`; - btn.setAttribute("aria-label", `Delete ${book.title}`); // Accessibility improvement - btn.onclick = () => deleteBook(index); - return btn; -} - function clearTable() { const tbody = document.querySelector("#display tbody"); if (tbody) { @@ -220,18 +210,32 @@ function toggleReadStatus(index) { } } -function deleteBook(index) { - const book = myLibrary[index]; - if (book) { +function deleteBook(title, author) { + const index = myLibrary.findIndex(book => + book.title === title && book.author === author + ); + + if (index !== -1) { + const book = myLibrary[index]; if (confirm(`Are you sure you want to delete "${book.title}" from your library?`)) { const deletedBook = myLibrary.splice(index, 1)[0]; console.log(`Deleted book "${deletedBook.title}" from library`); render(); showAlert(`"${deletedBook.title}" has been removed from your library!`, "warning"); } + } else { + console.error("Book not found:", title, author); } } +function createDeleteButton(book, index) { + const btn = document.createElement("button"); + btn.className = "btn btn-warning btn-sm"; + btn.textContent = "Delete"; + btn.onclick = () => deleteBook(book.title, book.author); + return btn; +} + function viewReadBooks() { console.log("Viewing read books only"); clearTable(); From 0950066d8b43fafbfe8b2b5a0ad7aa0b1029e54d Mon Sep 17 00:00:00 2001 From: sedazam Date: Wed, 13 Aug 2025 14:00:40 +0100 Subject: [PATCH 53/58] Refactor HTML structure and JavaScript functions for improved readability and maintainability; enhance accessibility features for buttons and forms --- debugging/book-library/index.html | 157 ++++---- debugging/book-library/script.js | 586 +++++++++++++++--------------- debugging/book-library/style.css | 197 +++++----- 3 files changed, 494 insertions(+), 446 deletions(-) diff --git a/debugging/book-library/index.html b/debugging/book-library/index.html index 7603a8ea..68e53ba0 100644 --- a/debugging/book-library/index.html +++ b/debugging/book-library/index.html @@ -1,69 +1,104 @@ - My Book Library - - - - - - + My Book Library + + + + + + -
-
-
-

My Book Library

-

Add books to your virtual library and track your reading progress

-
-
- -
-
- -
- - - -
- -
-
- - - - - - - - - -
- - -
- - -
-
- - - - - - - - - - - - -
TitleAuthorPagesRead StatusActions
-
-
+
+
+
+

My Book Library

+

Add books to your virtual library and track your reading progress

+
+
- - - +
+
+ +
+ + + +
+ +
+
+ + + + + + + + + +
+ + +
+ + +
+
+ + + + + + + + + + + + +
TitleAuthorPagesRead StatusActions
+
+
+ + + + \ No newline at end of file diff --git a/debugging/book-library/script.js b/debugging/book-library/script.js index bc7b5c07..b9f939fe 100644 --- a/debugging/book-library/script.js +++ b/debugging/book-library/script.js @@ -1,348 +1,360 @@ let myLibrary = []; -window.addEventListener("load", function() { - console.log("Page loaded, initializing library..."); - populateStorage(); - render(); +window.addEventListener("load", function () { + console.log("Page loaded, initializing library..."); + populateStorage(); + render(); }); function Book(title, author, pages, isRead) { - this.title = title; - this.author = author; - this.pages = parseInt(pages) || 0; - this.isRead = isRead || false; + this.title = title; + this.author = author; + this.pages = parseInt(pages) || 0; + this.isRead = isRead || false; } function populateStorage() { - if (myLibrary.length === 0) { - let book1 = new Book("Robinson Crusoe", "Daniel Defoe", 252, true); - let book2 = new Book("The Old Man and the Sea", "Ernest Hemingway", 127, true); - let book3 = new Book("How to Code", "Seddiq Azam", 324, false); - - myLibrary.push(book1, book2, book3); - console.log("Added initial books:", myLibrary); - } + if (myLibrary.length === 0) { + let book1 = new Book("Robinson Crusoe", "Daniel Defoe", 252, true); + let book2 = new Book("The Old Man and the Sea", "Ernest Hemingway", 127, true); + let book3 = new Book("To Kill a Mockingbird", "Harper Lee", 324, false); + + myLibrary.push(book1, book2, book3); + console.log("Added initial books:", myLibrary); + } } function addBook() { - console.log("Add book button clicked!"); - - const titleInput = document.getElementById("title"); - const authorInput = document.getElementById("author"); - const pagesInput = document.getElementById("pages"); - const checkInput = document.getElementById("check"); - - if (!titleInput || !authorInput || !pagesInput || !checkInput) { - showAlert("Form elements not found! Please refresh the page.", "danger"); - return; - } - - const title = titleInput.value.trim(); - const author = authorInput.value.trim(); - const pages = pagesInput.value.trim(); - const isRead = checkInput.checked; - - console.log("Form values:", { title, author, pages, isRead }); - - if (!title || !author || !pages) { - showAlert("Please fill in all required fields (Title, Author, and Pages)!", "warning"); - highlightEmptyFields(title, author, pages); - return; - } - - if (isNaN(pages) || parseInt(pages) <= 0) { - showAlert("Please enter a valid number of pages (greater than 0)!", "warning"); - pagesInput.classList.add("is-invalid"); - return; - } - - const duplicate = myLibrary.find(book => - book.title.toLowerCase() === title.toLowerCase() && - book.author.toLowerCase() === author.toLowerCase() - ); - - if (duplicate) { - showAlert(`This book "${title}" by ${author} is already in your library!`, "info"); - return; - } - - const newBook = new Book(title, author, pages, isRead); - console.log("Created new book:", newBook); - - myLibrary.push(newBook); - console.log("Library after adding book:", myLibrary.length, "total books"); - - render(); - - clearForm(); - - showAlert(`Successfully added "${title}" by ${author} to your library!`, "success"); - - if (typeof $ !== 'undefined') { - $("#demo").collapse('hide'); - } + console.log("Add book button clicked!"); + + const titleInput = document.getElementById("title"); + const authorInput = document.getElementById("author"); + const pagesInput = document.getElementById("pages"); + const checkInput = document.getElementById("check"); + + if (!titleInput || !authorInput || !pagesInput || !checkInput) { + showAlert("Form elements not found! Please refresh the page.", "danger"); + return; + } + + const title = titleInput.value.trim(); + const author = authorInput.value.trim(); + const pages = pagesInput.value.trim(); + const isRead = checkInput.checked; + + console.log("Form values:", { title, author, pages, isRead }); + + if (!title || !author || !pages) { + showAlert("Please fill in all required fields (Title, Author, and Pages)!", "warning"); + highlightEmptyFields(title, author, pages); + return; + } + + if (isNaN(pages) || parseInt(pages) <= 0) { + showAlert("Please enter a valid number of pages (greater than 0)!", "warning"); + pagesInput.classList.add("is-invalid"); + return; + } + + const duplicate = myLibrary.find( + (book) => + book.title.toLowerCase() === title.toLowerCase() && + book.author.toLowerCase() === author.toLowerCase() + ); + + if (duplicate) { + showAlert(`This book "${title}" by ${author} is already in your library!`, "info"); + return; + } + + const newBook = new Book(title, author, pages, isRead); + console.log("Created new book:", newBook); + + myLibrary.push(newBook); + console.log("Library after adding book:", myLibrary.length, "total books"); + + render(); + clearForm(); + + showAlert(`Successfully added "${title}" by ${author} to your library!`, "success"); + + if (typeof $ !== 'undefined') { + $("#demo").collapse('hide'); + } } function highlightEmptyFields(title, author, pages) { - const titleInput = document.getElementById("title"); - const authorInput = document.getElementById("author"); - const pagesInput = document.getElementById("pages"); - - [titleInput, authorInput, pagesInput].forEach(input => { - input.classList.remove("is-invalid", "is-valid"); - }); - - if (!title) titleInput.classList.add("is-invalid"); - if (!author) authorInput.classList.add("is-invalid"); - if (!pages) pagesInput.classList.add("is-invalid"); + const titleInput = document.getElementById("title"); + const authorInput = document.getElementById("author"); + const pagesInput = document.getElementById("pages"); + + [titleInput, authorInput, pagesInput].forEach(input => { + input.classList.remove("is-invalid", "is-valid"); + }); + + if (!title) titleInput.classList.add("is-invalid"); + if (!author) authorInput.classList.add("is-invalid"); + if (!pages) pagesInput.classList.add("is-invalid"); } function clearForm() { - const titleInput = document.getElementById("title"); - const authorInput = document.getElementById("author"); - const pagesInput = document.getElementById("pages"); - const checkInput = document.getElementById("check"); - - if (titleInput) { - titleInput.value = ""; - titleInput.classList.remove("is-invalid", "is-valid"); - } - if (authorInput) { - authorInput.value = ""; - authorInput.classList.remove("is-invalid", "is-valid"); - } - if (pagesInput) { - pagesInput.value = ""; - pagesInput.classList.remove("is-invalid", "is-valid"); - } - if (checkInput) { - checkInput.checked = false; - } - - console.log("Form cleared"); + const titleInput = document.getElementById("title"); + const authorInput = document.getElementById("author"); + const pagesInput = document.getElementById("pages"); + const checkInput = document.getElementById("check"); + + if (titleInput) { + titleInput.value = ""; + titleInput.classList.remove("is-invalid", "is-valid"); + } + if (authorInput) { + authorInput.value = ""; + authorInput.classList.remove("is-invalid", "is-valid"); + } + if (pagesInput) { + pagesInput.value = ""; + pagesInput.classList.remove("is-invalid", "is-valid"); + } + if (checkInput) { + checkInput.checked = false; + } + + console.log("Form cleared"); } function render() { - console.log("Rendering library with", myLibrary.length, "books"); - clearTable(); - - // Hide the form when switching to all books view - if (typeof $ !== 'undefined') { - $("#demo").collapse('hide'); - } else { - const demoElement = document.getElementById("demo"); - if (demoElement && demoElement.classList.contains("show")) { - demoElement.classList.remove("show"); - } + console.log("Rendering library with", myLibrary.length, "books"); + clearTable(); + + // Hide the form when switching to all books view + if (typeof $ !== 'undefined') { + $("#demo").collapse('hide'); + } else { + const demoElement = document.getElementById("demo"); + if (demoElement && demoElement.classList.contains("show")) { + demoElement.classList.remove("show"); } + } + + const tbody = document.querySelector("#display tbody"); + if (!tbody) { + console.error("Could not find table body element!"); + return; + } + + if (myLibrary.length === 0) { + showEmptyState("Your library is empty. Add some books to get started!"); + return; + } + + myLibrary.forEach((book, index) => { + const row = tbody.insertRow(); - const tbody = document.querySelector("#display tbody"); - if (!tbody) { - console.error("Could not find table body element!"); - return; - } + const titleCell = row.insertCell(0); + titleCell.textContent = book.title; + titleCell.style.fontWeight = "bold"; - if (myLibrary.length === 0) { - showEmptyState("Your library is empty. Add some books to get started!"); - return; - } + const authorCell = row.insertCell(1); + authorCell.textContent = book.author; + + const pagesCell = row.insertCell(2); + pagesCell.textContent = book.pages; - myLibrary.forEach((book, index) => { - const row = tbody.insertRow(); - - const titleCell = row.insertCell(0); - titleCell.textContent = book.title; - titleCell.style.fontWeight = "bold"; - - const authorCell = row.insertCell(1); - authorCell.textContent = book.author; - - const pagesCell = row.insertCell(2); - pagesCell.textContent = book.pages; - - const statusCell = row.insertCell(3); - const statusBtn = createStatusButton(book, index); - statusCell.appendChild(statusBtn); - - const actionCell = row.insertCell(4); - const deleteBtn = createDeleteButton(book, index); - actionCell.appendChild(deleteBtn); - }); + const statusCell = row.insertCell(3); + const statusBtn = createStatusButton(book, index); + statusCell.appendChild(statusBtn); + + const actionCell = row.insertCell(4); + const deleteBtn = createDeleteButton(book, index); + actionCell.appendChild(deleteBtn); + }); } function createStatusButton(book, index) { - const btn = document.createElement("button"); - btn.className = book.isRead ? "btn btn-success btn-sm" : "btn btn-danger btn-sm"; - btn.textContent = book.isRead ? "Read" : "Not Read"; - btn.title = `Mark "${book.title}" as ${book.isRead ? "unread" : "read"}`; // Use book parameter - btn.setAttribute("aria-label", btn.title); // Accessibility improvement - btn.onclick = () => toggleReadStatus(index); - return btn; + const btn = document.createElement("button"); + btn.className = book.isRead ? "btn btn-success btn-sm" : "btn btn-danger btn-sm"; + btn.textContent = book.isRead ? "Read" : "Not Read"; + btn.title = `Mark "${book.title}" as ${book.isRead ? "unread" : "read"}`; + btn.setAttribute("aria-label", btn.title); + btn.onclick = () => toggleReadStatus(index); + return btn; +} + +function createDeleteButton(book, index) { + const btn = document.createElement("button"); + btn.className = "btn btn-warning btn-sm"; + btn.textContent = "Delete"; + btn.title = `Delete "${book.title}"`; + btn.setAttribute("aria-label", `Delete ${book.title}`); + + btn.dataset.bookIndex = index; + btn.onclick = function() { + const bookIndex = parseInt(this.dataset.bookIndex); + deleteBook(bookIndex); + }; + + return btn; } function clearTable() { - const tbody = document.querySelector("#display tbody"); - if (tbody) { - tbody.innerHTML = ""; - } + const tbody = document.querySelector("#display tbody"); + if (tbody) { + tbody.innerHTML = ""; + } } function showEmptyState(message) { - const tbody = document.querySelector("#display tbody"); - if (tbody) { - const row = tbody.insertRow(); - const cell = row.insertCell(0); - cell.colSpan = 5; - cell.className = "text-center text-muted"; - cell.textContent = message; - } + const tbody = document.querySelector("#display tbody"); + if (tbody) { + const row = tbody.insertRow(); + const cell = row.insertCell(0); + cell.colSpan = 5; + cell.className = "text-center text-muted"; + cell.textContent = message; + } } function toggleReadStatus(index) { - const book = myLibrary[index]; - if (book) { - book.isRead = !book.isRead; - console.log(`Toggled read status for "${book.title}" to ${book.isRead ? "Read" : "Not Read"}`); - render(); - - const statusMessage = book.isRead ? "marked as read" : "marked as unread"; - showAlert(`"${book.title}" ${statusMessage}!`, "info"); - } -} - -function deleteBook(title, author) { - const index = myLibrary.findIndex(book => - book.title === title && book.author === author - ); + const book = myLibrary[index]; + if (book) { + book.isRead = !book.isRead; + console.log(`Toggled read status for "${book.title}" to ${book.isRead ? "Read" : "Not Read"}`); + render(); - if (index !== -1) { - const book = myLibrary[index]; - if (confirm(`Are you sure you want to delete "${book.title}" from your library?`)) { - const deletedBook = myLibrary.splice(index, 1)[0]; - console.log(`Deleted book "${deletedBook.title}" from library`); - render(); - showAlert(`"${deletedBook.title}" has been removed from your library!`, "warning"); - } - } else { - console.error("Book not found:", title, author); - } + const statusMessage = book.isRead ? "marked as read" : "marked as unread"; + showAlert(`"${book.title}" ${statusMessage}!`, "info"); + } } -function createDeleteButton(book, index) { - const btn = document.createElement("button"); - btn.className = "btn btn-warning btn-sm"; - btn.textContent = "Delete"; - btn.onclick = () => deleteBook(book.title, book.author); - return btn; +function deleteBook(index) { + console.log("Delete function called with index:", index); + const book = myLibrary[index]; + console.log("Book to delete:", book); + + if (book) { + if (confirm(`Are you sure you want to delete "${book.title}" from your library?`)) { + const deletedBook = myLibrary.splice(index, 1)[0]; + console.log(`Deleted book "${deletedBook.title}" from library`); + render(); + showAlert(`"${deletedBook.title}" has been removed from your library!`, "warning"); + } + } else { + console.error("Book not found at index:", index); + } } function viewReadBooks() { - console.log("Viewing read books only"); - clearTable(); - - // Hide the form when switching to read books view - if (typeof $ !== 'undefined') { - $("#demo").collapse('hide'); - } else { - const demoElement = document.getElementById("demo"); - if (demoElement && demoElement.classList.contains("show")) { - demoElement.classList.remove("show"); - } + console.log("Viewing read books only"); + clearTable(); + + // Hide the form when switching to read books view + if (typeof $ !== 'undefined') { + $("#demo").collapse('hide'); + } else { + const demoElement = document.getElementById("demo"); + if (demoElement && demoElement.classList.contains("show")) { + demoElement.classList.remove("show"); } + } + + const tbody = document.querySelector("#display tbody"); + if (!tbody) { + console.error("Could not find table body element!"); + return; + } + + const readBooks = myLibrary.filter(book => book.isRead); + + if (readBooks.length === 0) { + showEmptyState("You haven't read any books yet!"); + return; + } + + readBooks.forEach((book) => { + const row = tbody.insertRow(); - const tbody = document.querySelector("#display tbody"); - if (!tbody) { - console.error("Could not find table body element!"); - return; - } + const titleCell = row.insertCell(0); + titleCell.textContent = book.title; + titleCell.style.fontWeight = "bold"; - const readBooks = myLibrary.filter(book => book.isRead); + const authorCell = row.insertCell(1); + authorCell.textContent = book.author; - if (readBooks.length === 0) { - showEmptyState("You haven't read any books yet!"); - return; - } + const pagesCell = row.insertCell(2); + pagesCell.textContent = book.pages; + + const statusCell = row.insertCell(3); + const statusBtn = document.createElement("button"); + statusBtn.className = "btn btn-success btn-sm"; + statusBtn.textContent = "Read"; + statusBtn.title = `Mark "${book.title}" as unread`; + statusBtn.onclick = () => { + book.isRead = !book.isRead; + render(); // Switch back to full view + }; + statusCell.appendChild(statusBtn); - readBooks.forEach((book, index) => { - const row = tbody.insertRow(); - - const titleCell = row.insertCell(0); - titleCell.textContent = book.title; - titleCell.style.fontWeight = "bold"; - - const authorCell = row.insertCell(1); - authorCell.textContent = book.author; - - const pagesCell = row.insertCell(2); - pagesCell.textContent = book.pages; - - const statusCell = row.insertCell(3); - const statusBtn = document.createElement("button"); - statusBtn.className = "btn btn-success btn-sm"; - statusBtn.textContent = "Read"; - statusBtn.onclick = () => { - book.isRead = !book.isRead; - render(); // Switch back to full view - }; - statusCell.appendChild(statusBtn); - - const actionCell = row.insertCell(4); - const deleteBtn = document.createElement("button"); - deleteBtn.className = "btn btn-warning btn-sm"; - deleteBtn.textContent = "Delete"; - deleteBtn.onclick = () => { - if (confirm(`Are you sure you want to delete "${book.title}" from your library?`)) { - myLibrary.splice(myLibrary.indexOf(book), 1); - viewReadBooks(); // Refresh the filtered view - } - }; - actionCell.appendChild(deleteBtn); - }); + const actionCell = row.insertCell(4); + const deleteBtn = document.createElement("button"); + deleteBtn.className = "btn btn-warning btn-sm"; + deleteBtn.textContent = "Delete"; + deleteBtn.title = `Delete "${book.title}"`; + deleteBtn.onclick = () => { + if (confirm(`Are you sure you want to delete "${book.title}" from your library?`)) { + const index = myLibrary.indexOf(book); + if (index !== -1) { + myLibrary.splice(index, 1); + viewReadBooks(); // Refresh the filtered view + } + } + }; + actionCell.appendChild(deleteBtn); + }); } function showAlert(message, type) { - const alertContainer = document.getElementById("alertContainer"); - if (!alertContainer) { - console.error("Alert container not found!"); - return; - } - - const alert = document.createElement("div"); - alert.className = `alert alert-${type} alert-dismissible fade show`; - alert.innerHTML = ` - ${getAlertIcon(type)} - ${message} - - `; - - alertContainer.appendChild(alert); - + const alertContainer = document.getElementById("alertContainer"); + if (!alertContainer) { + console.error("Alert container not found!"); + return; + } + + const alert = document.createElement("div"); + alert.className = `alert alert-${type} alert-dismissible fade show`; + alert.innerHTML = ` + ${getAlertIcon(type)} + ${message} + + `; + + alertContainer.appendChild(alert); + + setTimeout(() => { + alert.classList.remove("show"); setTimeout(() => { - alert.classList.remove("show"); - setTimeout(() => { - alertContainer.removeChild(alert); - }, 150); - }, 5000); + alertContainer.removeChild(alert); + }, 150); + }, 5000); } function getAlertIcon(type) { - switch (type) { - case "success": return ' '; - case "warning": return ' '; - case "danger": return ' '; - case "info": return ' '; - default: return ''; - } + switch (type) { + case "success": return ' '; + case "warning": return ' '; + case "danger": return ' '; + case "info": return ' '; + default: return ''; + } } document.addEventListener('keydown', function(event) { - if (event.key === 'Escape') { - if (typeof $ !== 'undefined') { - $("#demo").collapse('hide'); - } + if (event.key === 'Escape') { + if (typeof $ !== 'undefined') { + $("#demo").collapse('hide'); } + } }); console.log("Book Library JavaScript loaded successfully!"); \ No newline at end of file diff --git a/debugging/book-library/style.css b/debugging/book-library/style.css index 6f7a0d6d..1e39d411 100644 --- a/debugging/book-library/style.css +++ b/debugging/book-library/style.css @@ -1,169 +1,170 @@ + .form-group { - max-width: 400px; - padding: 20px; - margin: auto; + max-width: 400px; + padding: 20px; + margin: auto; } button.btn { - margin: 10px; + margin: 10px; } .row .btn { - margin-right: 10px; + margin-right: 10px; } .form-check-label { - padding-left: 20px; - margin: 5px 0px 5px 0px; + padding-left: 20px; + margin: 5px 0px 5px 0px; } .jumbotron { - background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); - color: white; - margin-bottom: 2rem; - border-radius: 0.5rem; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + color: white; + margin-bottom: 2rem; + border-radius: 0.5rem; } .collapse { - background: white; - padding: 2rem; - border-radius: 8px; - box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); - margin-bottom: 2rem; - border: 1px solid #e9ecef; + background: white; + padding: 2rem; + border-radius: 8px; + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); + margin-bottom: 2rem; + border: 1px solid #e9ecef; } .container { - background: #f8f9fa; - min-height: 100vh; - padding-bottom: 2rem; - padding-top: 1rem; + background: #f8f9fa; + min-height: 100vh; + padding-bottom: 2rem; + padding-top: 1rem; } .table { - margin-top: 1rem; - background: white; - border-radius: 0.5rem; - overflow: hidden; - box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); + margin-top: 1rem; + background: white; + border-radius: 0.5rem; + overflow: hidden; + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); } .table-responsive { - border-radius: 0.5rem; + border-radius: 0.5rem; } .table-striped > tbody > tr:nth-of-type(odd) > td { - background-color: rgba(0, 123, 255, 0.05); + background-color: rgba(0, 123, 255, 0.05); } .btn:hover { - transform: translateY(-1px); - transition: all 0.2s ease; - box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); + transform: translateY(-1px); + transition: all 0.2s ease; + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); } #alertContainer { - position: relative; - z-index: 1000; + position: relative; + z-index: 1000; } .alert { - margin-bottom: 1rem; - border-radius: 0.5rem; + margin-bottom: 1rem; + border-radius: 0.5rem; } nav[role="navigation"] { - background: white; - padding: 1rem; - border-radius: 0.5rem; - box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); - margin-bottom: 1rem; + background: white; + padding: 1rem; + border-radius: 0.5rem; + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); + margin-bottom: 1rem; } .form-control:focus { - border-color: #667eea; - box-shadow: 0 0 0 0.2rem rgba(102, 126, 234, 0.25); + border-color: #667eea; + box-shadow: 0 0 0 0.2rem rgba(102, 126, 234, 0.25); } @media (max-width: 768px) { - .btn { - margin: 5px 2px; - font-size: 0.9rem; - padding: 0.375rem 0.75rem; - } - - .form-group { - max-width: 100%; - padding: 15px; - } - - .table-responsive { - font-size: 0.9rem; - } - - .jumbotron { - padding: 1.5rem 1rem; - } - - .jumbotron h1 { - font-size: 2rem; - } - - .collapse { - padding: 1rem; - } - - nav[role="navigation"] { - padding: 0.5rem; - } + .btn { + margin: 5px 2px; + font-size: 0.9rem; + padding: 0.375rem 0.75rem; + } + + .form-group { + max-width: 100%; + padding: 15px; + } + + .table-responsive { + font-size: 0.9rem; + } + + .jumbotron { + padding: 1.5rem 1rem; + } + + .jumbotron h1 { + font-size: 2rem; + } + + .collapse { + padding: 1rem; + } + + nav[role="navigation"] { + padding: 0.5rem; + } } @media (max-width: 576px) { - .btn { - width: 100%; - margin: 5px 0; - } - - .table { - font-size: 0.8rem; - } - - .btn-sm { - font-size: 0.7rem; - padding: 0.2rem 0.5rem; - } + .btn { + width: 100%; + margin: 5px 0; + } + + .table { + font-size: 0.8rem; + } + + .btn-sm { + font-size: 0.7rem; + padding: 0.2rem 0.5rem; + } } .btn:disabled { - opacity: 0.6; - cursor: not-allowed; + opacity: 0.6; + cursor: not-allowed; } .form-control.is-valid { - border-color: #28a745; + border-color: #28a745; } .form-control.is-invalid { - border-color: #dc3545; + border-color: #dc3545; } .btn-primary { - background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); - border: none; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + border: none; } .btn-primary:hover { - background: linear-gradient(135deg, #5a67d8 0%, #6b46c1 100%); - border: none; + background: linear-gradient(135deg, #5a67d8 0%, #6b46c1 100%); + border: none; } .table .btn-sm { - padding: 0.25rem 0.5rem; - font-size: 0.875rem; - margin: 0 2px; + padding: 0.25rem 0.5rem; + font-size: 0.875rem; + margin: 0 2px; } .text-muted { - font-style: italic; - padding: 2rem; + font-style: italic; + padding: 2rem; } \ No newline at end of file From 7129071e8a293041aaaf764d4019fee1a86ceb74 Mon Sep 17 00:00:00 2001 From: sedazam Date: Wed, 13 Aug 2025 14:01:46 +0100 Subject: [PATCH 54/58] Update initial book data in populateStorage function --- debugging/book-library/script.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/debugging/book-library/script.js b/debugging/book-library/script.js index b9f939fe..ea8924cc 100644 --- a/debugging/book-library/script.js +++ b/debugging/book-library/script.js @@ -17,8 +17,8 @@ function populateStorage() { if (myLibrary.length === 0) { let book1 = new Book("Robinson Crusoe", "Daniel Defoe", 252, true); let book2 = new Book("The Old Man and the Sea", "Ernest Hemingway", 127, true); - let book3 = new Book("To Kill a Mockingbird", "Harper Lee", 324, false); - + let book3 = new Book("How to Code", "Seddiq Azam", 324, false); + myLibrary.push(book1, book2, book3); console.log("Added initial books:", myLibrary); } From 92c6565547c936063785c73770eacd30a66b2f94 Mon Sep 17 00:00:00 2001 From: sedazam Date: Wed, 13 Aug 2025 14:23:20 +0100 Subject: [PATCH 55/58] Refactor clearForm function to use form.reset() for improved clarity and efficiency; remove redundant code for resetting input fields --- debugging/book-library/script.js | 34 +++++++++++--------------------- 1 file changed, 12 insertions(+), 22 deletions(-) diff --git a/debugging/book-library/script.js b/debugging/book-library/script.js index ea8924cc..400654d6 100644 --- a/debugging/book-library/script.js +++ b/debugging/book-library/script.js @@ -98,35 +98,25 @@ function highlightEmptyFields(title, author, pages) { } function clearForm() { - const titleInput = document.getElementById("title"); - const authorInput = document.getElementById("author"); - const pagesInput = document.getElementById("pages"); - const checkInput = document.getElementById("check"); - - if (titleInput) { - titleInput.value = ""; - titleInput.classList.remove("is-invalid", "is-valid"); - } - if (authorInput) { - authorInput.value = ""; - authorInput.classList.remove("is-invalid", "is-valid"); - } - if (pagesInput) { - pagesInput.value = ""; - pagesInput.classList.remove("is-invalid", "is-valid"); - } - if (checkInput) { - checkInput.checked = false; + const form = document.getElementById("bookForm"); + if (!form) { + console.error("Form element not found!"); + return; } - - console.log("Form cleared"); + + form.reset(); + + form.querySelectorAll(".is-invalid, .is-valid").forEach(input => { + input.classList.remove("is-invalid", "is-valid"); + }); + + console.log("Form cleared using .reset()"); } function render() { console.log("Rendering library with", myLibrary.length, "books"); clearTable(); - // Hide the form when switching to all books view if (typeof $ !== 'undefined') { $("#demo").collapse('hide'); } else { From 676a5e249b7bfd0acdd05bf587bfa555f2f578b4 Mon Sep 17 00:00:00 2001 From: sedazam Date: Wed, 13 Aug 2025 14:35:21 +0100 Subject: [PATCH 56/58] Add event listener to book form for submission handling --- debugging/book-library/script.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/debugging/book-library/script.js b/debugging/book-library/script.js index 400654d6..3a391525 100644 --- a/debugging/book-library/script.js +++ b/debugging/book-library/script.js @@ -4,6 +4,13 @@ window.addEventListener("load", function () { console.log("Page loaded, initializing library..."); populateStorage(); render(); + const form = document.getElementById("bookForm"); + if (form) { + form.addEventListener("submit", function(event) { + event.preventDefault(); + addBook(); + }); + } }); function Book(title, author, pages, isRead) { From d310f398510f5b6b8d3309c653aff0471e0dc68b Mon Sep 17 00:00:00 2001 From: sedazam Date: Wed, 13 Aug 2025 14:43:21 +0100 Subject: [PATCH 57/58] Refactor book form structure for improved semantics and accessibility; ensure proper form attributes are set --- debugging/book-library/index.html | 88 ++++++++++++++++--------------- 1 file changed, 46 insertions(+), 42 deletions(-) diff --git a/debugging/book-library/index.html b/debugging/book-library/index.html index 68e53ba0..359c2e2d 100644 --- a/debugging/book-library/index.html +++ b/debugging/book-library/index.html @@ -18,8 +18,8 @@

My Book Library

-
-
+
+
-
-
- - - - - - - - - -
- - -
- - -
+
+
+
+ + + + + + + + + +
+ +
+ +
+
+
From 37b98ed390911c657bbe692ccb13cff69d20206a Mon Sep 17 00:00:00 2001 From: sedazam Date: Wed, 13 Aug 2025 17:41:00 +0100 Subject: [PATCH 58/58] Remove console log for add book button click to clean up code --- debugging/book-library/script.js | 1 - 1 file changed, 1 deletion(-) diff --git a/debugging/book-library/script.js b/debugging/book-library/script.js index 3a391525..23239dfa 100644 --- a/debugging/book-library/script.js +++ b/debugging/book-library/script.js @@ -32,7 +32,6 @@ function populateStorage() { } function addBook() { - console.log("Add book button clicked!"); const titleInput = document.getElementById("title"); const authorInput = document.getElementById("author");