@@ -19,30 +19,40 @@ function populateStorage() {
1919 }
2020}
2121
22+ // === DOM elements ===
2223const 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
2830bookFormEl . addEventListener ( "submit" , handleBookFormSubmit ) ;
2931
3032function 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
5868function 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