Skip to content

Commit 12d400d

Browse files
committed
Improve book form validation and table rendering
Trim title and author and reject empty values - Convert page count to a number and validate it is positive
1 parent d3bdc53 commit 12d400d

File tree

1 file changed

+66
-50
lines changed

1 file changed

+66
-50
lines changed

debugging/book-library/script.js

Lines changed: 66 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -19,30 +19,40 @@ function populateStorage() {
1919
}
2020
}
2121

22+
// === DOM elements ===
2223
const bookFormEl = document.getElementById("bookForm");
23-
const titleInputEl = document.getElementById("title");
24-
const authorInputEl = document.getElementById("author");
25-
const pagesInputEl = document.getElementById("pages");
26-
const isReadCheckboxEl = document.getElementById("check");
24+
const titleInputEl = document.getElementById("title"); // .value is a string
25+
const authorInputEl = document.getElementById("author"); // .value is a string
26+
const pagesInputEl = document.getElementById("pages"); // .value is a string
27+
const isReadCheckboxEl = document.getElementById("check"); // .checked is boolean
28+
2729
// Check the form and, if OK, add a new book and re-render
2830
bookFormEl.addEventListener("submit", handleBookFormSubmit);
2931

3032
function handleBookFormSubmit(event) {
3133
event.preventDefault(); // stop page reload
3234

33-
if (!titleInputEl.value || !pagesInputEl.value) {
34-
alert("Please fill all fields!");
35+
// 🔹 Normalise / preprocess input
36+
const title = titleInputEl.value.trim();
37+
const author = authorInputEl.value.trim();
38+
const pages = Number(pagesInputEl.value);
39+
const isRead = isReadCheckboxEl.checked;
40+
41+
// 🔹 Validation
42+
if (!title || !author) {
43+
alert("Title and author are required.");
3544
return;
3645
}
3746

38-
const newBook = new Book(
39-
titleInputEl.value,
40-
authorInputEl.value,
41-
Number(pagesInputEl.value),
42-
isReadCheckboxEl.checked
43-
);
47+
if (!Number.isFinite(pages) || pages <= 0) {
48+
alert("Pages must be a positive number.");
49+
return;
50+
}
4451

52+
// 🔹 Create and store the new book
53+
const newBook = new Book(title, author, pages, isRead);
4554
myLibrary.push(newBook);
55+
4656
render();
4757
bookFormEl.reset();
4858
}
@@ -56,54 +66,60 @@ function Book(title, author, pages, check) {
5666
}
5767

5868
function render() {
59-
let table = document.getElementById("display");
60-
let rowsNumber = table.rows.length;
69+
const table = document.getElementById("display");
70+
const tbody = table.querySelector("tbody");
6171

62-
// delete old table rows (keep header at index 0)
63-
for (let n = rowsNumber - 1; n > 0; n--) { // ✅ fixed ')'
64-
table.deleteRow(n);
65-
}
72+
// 🔹 Clear previous rows in one go (keep header)
73+
tbody.innerHTML = "";
6674

6775
// insert updated rows and cells
68-
let length = myLibrary.length;
69-
for (let i = 0; i < length; i++) {
70-
let row = table.insertRow(1);
71-
let titleCell = row.insertCell(0);
72-
let authorCell = row.insertCell(1);
73-
let pagesCell = row.insertCell(2);
74-
let wasReadCell = row.insertCell(3);
75-
let deleteCell = row.insertCell(4);
76-
77-
titleCell.innerHTML = myLibrary[i].title;
78-
authorCell.innerHTML = myLibrary[i].author;
79-
pagesCell.innerHTML = myLibrary[i].pages;
76+
myLibrary.forEach((book, index) => {
77+
const row = document.createElement("tr");
8078

81-
// Read/unread button
82-
let changeBut = document.createElement("button");
83-
changeBut.id = i;
84-
changeBut.className = "btn btn-success";
85-
wasReadCell.appendChild(changeBut);
79+
const titleCell = document.createElement("td");
80+
const authorCell = document.createElement("td");
81+
const pagesCell = document.createElement("td");
82+
const wasReadCell = document.createElement("td");
83+
const deleteCell = document.createElement("td");
8684

87-
let readStatus = myLibrary[i].check ? "Yes" : "No"; // ✅ true = Yes
88-
changeBut.innerText = readStatus;
85+
// 🔹 Use textContent (safe & fast)
86+
titleCell.textContent = book.title;
87+
authorCell.textContent = book.author;
88+
pagesCell.textContent = book.pages;
8989

90-
changeBut.addEventListener("click", function () {
91-
myLibrary[i].check = !myLibrary[i].check;
90+
// Read/unread button
91+
const readBtn = document.createElement("button");
92+
readBtn.type = "button";
93+
readBtn.className = "btn btn-success btn-sm";
94+
readBtn.textContent = book.check ? "Yes" : "No";
95+
readBtn.addEventListener("click", () => {
96+
myLibrary[index].check = !myLibrary[index].check;
9297
render();
9398
});
99+
wasReadCell.appendChild(readBtn);
94100

95101
// Delete button
96-
let delButton = document.createElement("button");
97-
delButton.id = i + 5;
98-
delButton.className = "btn btn-warning";
99-
delButton.innerHTML = "Delete";
100-
deleteCell.appendChild(delButton);
101-
102-
delButton.addEventListener("click", function () { // ✅ 'click' not 'clicks'
103-
alert(`You've deleted title: ${myLibrary[i].title}`);
104-
myLibrary.splice(i, 1);
102+
const deleteBtn = document.createElement("button");
103+
deleteBtn.type = "button";
104+
deleteBtn.className = "btn btn-warning btn-sm";
105+
deleteBtn.textContent = "Delete";
106+
107+
deleteBtn.addEventListener("click", () => {
108+
const confirmed = confirm(`Delete "${book.title}"?`);
109+
if (!confirmed) return;
110+
111+
myLibrary.splice(index, 1);
105112
render();
106113
});
107-
}
114+
115+
deleteCell.appendChild(deleteBtn);
116+
117+
row.appendChild(titleCell);
118+
row.appendChild(authorCell);
119+
row.appendChild(pagesCell);
120+
row.appendChild(wasReadCell);
121+
row.appendChild(deleteCell);
122+
123+
tbody.appendChild(row);
124+
});
108125
}
109-

0 commit comments

Comments
 (0)