@@ -2,16 +2,15 @@ let myLibrary = [];
22
33window . addEventListener ( "load" , function ( e ) {
44 populateStorage ( ) ;
5- render ( ) ;
65} ) ;
76
87function populateStorage ( ) {
98 if ( myLibrary . length == 0 ) {
10- let book1 = new Book ( "Robison Crusoe" , "Daniel Defoe" , "252" , true ) ;
9+ let book1 = new Book ( "Robison Crusoe" , "Daniel Defoe" , Number ( "252" ) , true ) ;
1110 let book2 = new Book (
1211 "The Old Man and the Sea" ,
1312 "Ernest Hemingway" ,
14- "127" ,
13+ parseInt ( "127" ) ,
1514 true
1615 ) ;
1716 myLibrary . push ( book1 ) ;
@@ -20,26 +19,50 @@ function populateStorage() {
2019 }
2120}
2221
23- const title = document . getElementById ( "title" ) ;
24- const author = document . getElementById ( "author" ) ;
25- const pages = document . getElementById ( "pages" ) ;
26- const check = document . getElementById ( "check" ) ;
22+ const bookTitleInput = document . getElementById ( "title" ) ;
23+ const bookAuthorInput = document . getElementById ( "author" ) ;
24+ const bookNumberOfPagesInput = document . getElementById ( "pages" ) ;
25+ const isBookReadCheckBox = document . getElementById ( "check" ) ;
26+
27+ // Strip out HTML tags (to prevent XSS)
28+ function sanitizeInput ( str ) {
29+ const div = document . createElement ( 'div' ) ;
30+ div . textContent = str ;
31+ return div . innerHTML ;
32+ }
33+
34+ // To check if pages input can be safely converted to integer
35+ function isValidInteger ( input ) {
36+ return Number . isInteger ( input ) ;
37+ }
38+ // prevent accidental hexadecimal input
39+ function isHexadecimal ( input ) {
40+ return / ^ 0 x [ 0 - 9 a - f A - F ] + $ / . test ( input ) ;
41+ }
2742
2843//check the right input from forms and if its ok -> add the new book (object in array)
2944//via Book function and start render function
3045function submit ( ) {
3146 if (
32- title . value == null ||
33- title . value == "" ||
34- author . value == null ||
35- author . value == "" ||
36- pages . value == null ||
37- pages . value == ""
47+ bookTitleInput . value . trim ( ) == "" ||
48+ bookAuthorInput . value . trim ( ) == "" ||
49+ bookNumberOfPagesInput . value . trim ( ) == ""
3850 ) {
3951 alert ( "Please fill all fields!" ) ;
4052 return false ;
41- } else {
42- let book = new Book ( title . value , author . value , pages . value , check . checked ) ;
53+ } else if (
54+ isNaN ( Number ( bookNumberOfPagesInput . value . trim ( ) ) ) ||
55+ ! isValidInteger ( Number ( bookNumberOfPagesInput . value . trim ( ) ) ) ||
56+ isHexadecimal ( bookNumberOfPagesInput . value . trim ( ) ) ||
57+ Number ( bookNumberOfPagesInput . value . trim ( ) ) <= 0
58+ ) {
59+ alert ( "Invalid number of pages format!" ) ;
60+ return false ;
61+ } else {
62+ const bookTitle = sanitizeInput ( bookTitleInput . value . trim ( ) ) ;
63+ const bookAuthor = sanitizeInput ( bookAuthorInput . value . trim ( ) ) ;
64+ const bookNumberOfPages = parseInt ( sanitizeInput ( bookNumberOfPagesInput . value . trim ( ) ) , 10 ) ;
65+ let book = new Book ( bookTitle , bookAuthor , bookNumberOfPages , isBookReadCheckBox . checked ) ;
4366 myLibrary . push ( book ) ;
4467 render ( ) ;
4568 }
@@ -54,51 +77,46 @@ function Book(title, author, pages, check) {
5477
5578function render ( ) {
5679 let table = document . getElementById ( "display" ) ;
57- let rowsNumber = table . rows . length ;
58- //delete old table
59- for ( let n = rowsNumber - 1 ; n > 0 ; n -- ) {
60- table . deleteRow ( n ) ;
61- }
80+ let tableBody = table . querySelector ( "tbody" ) ;
81+ tableBody . innerHTML = '' ;
6282 //insert updated row and cells
6383 let length = myLibrary . length ;
6484 for ( let i = 0 ; i < length ; i ++ ) {
65- let row = table . insertRow ( 1 ) ;
85+ let row = tableBody . insertRow ( ) ;
6686 let titleCell = row . insertCell ( 0 ) ;
6787 let authorCell = row . insertCell ( 1 ) ;
6888 let pagesCell = row . insertCell ( 2 ) ;
6989 let wasReadCell = row . insertCell ( 3 ) ;
7090 let deleteCell = row . insertCell ( 4 ) ;
71- titleCell . innerHTML = myLibrary [ i ] . title ;
72- authorCell . innerHTML = myLibrary [ i ] . author ;
73- pagesCell . innerHTML = myLibrary [ i ] . pages ;
91+ titleCell . textContent = myLibrary [ i ] . title ;
92+ authorCell . textContent = myLibrary [ i ] . author ;
93+ pagesCell . textContent = myLibrary [ i ] . pages ;
7494
7595 //add and wait for action for read/unread button
76- let changeBut = document . createElement ( "button" ) ;
77- changeBut . id = i ;
78- changeBut . className = "btn btn-success" ;
79- wasReadCell . appendChild ( changeBut ) ;
96+ let changeReadStatusButton = document . createElement ( "button" ) ;
97+ changeReadStatusButton . className = "btn btn-success" ;
98+ wasReadCell . appendChild ( changeReadStatusButton ) ;
8099 let readStatus = "" ;
81100 if ( myLibrary [ i ] . check == false ) {
82101 readStatus = "No" ;
83102 } else {
84103 readStatus = "Yes" ;
85104 }
86- changeBut . innerText = readStatus ;
105+ changeReadStatusButton . innerText = readStatus ;
87106
88- changeBut . addEventListener ( "click" , function ( ) {
107+ changeReadStatusButton . addEventListener ( "click" , function ( ) {
89108 myLibrary [ i ] . check = ! myLibrary [ i ] . check ;
90109 render ( ) ;
91110 } ) ;
92111
93112 //add delete button to every row and render again
94- let delBut = document . createElement ( "button" ) ;
95- delBut . id = i + 5 ;
96- deleteCell . appendChild ( delBut ) ;
97- delBut . className = "btn btn-warning" ;
98- delBut . innerHTML = "Delete" ;
99- delBut . addEventListener ( "click" , function ( ) {
100- alert ( `You've deleted title: ${ myLibrary [ i ] . title } ` ) ;
113+ let deleteBookButton = document . createElement ( "button" ) ;
114+ deleteCell . appendChild ( deleteBookButton ) ;
115+ deleteBookButton . className = "btn btn-warning" ;
116+ deleteBookButton . innerHTML = "Delete" ;
117+ deleteBookButton . addEventListener ( "click" , function ( ) {
101118 myLibrary . splice ( i , 1 ) ;
119+ alert ( `You've deleted title: ${ myLibrary [ i ] . title } ` ) ;
102120 render ( ) ;
103121 } ) ;
104122 }
0 commit comments