diff --git a/debugging/book-library/index.html b/debugging/book-library/index.html index 23acfa71..1d8f771f 100644 --- a/debugging/book-library/index.html +++ b/debugging/book-library/index.html @@ -1,15 +1,14 @@ - + - - + Book Library + + + + -
-

Library

-

Add books to your virtual library

-
+
+
+

Library

+

Add books to your virtual library

+
+
+ - +
+
+ + + + + + + + + + + -
-
- - - - - - - - + type="submit" + value="Submit" + class="btn btn-primary" + onclick="submit()" + /> + +
-
- - - - - - - - - - - - - - - - - - - - -
TitleAuthorNumber of PagesRead
+ + + + + + + + + + + +
TitleAuthorNumber of PagesRead
+
diff --git a/debugging/book-library/script.js b/debugging/book-library/script.js index 75ce6c1d..77a6c933 100644 --- a/debugging/book-library/script.js +++ b/debugging/book-library/script.js @@ -7,7 +7,7 @@ window.addEventListener("load", function (e) { 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", @@ -28,33 +28,66 @@ 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() { + const titleValue = title.value.trim(); + const authorValue = author.value.trim(); + const pagesValue = pages.value.trim(); if ( - title.value == null || - title.value == "" || - pages.value == null || - pages.value == "" + !titleValue || + !authorValue || + !pagesValue || + Number(pagesValue) <= 0 || + Number.isNaN(Number(pagesValue)) || + !/^[1-9]\d*$/.test(pagesValue) ) { - alert("Please fill all fields!"); + alert("Please fill all fields with valid input!"); return false; } else { - let book = new Book(title.value, title.value, pages.value, check.checked); - library.push(book); + let book = new Book( + titleValue, + authorValue, + Number(pagesValue), + check.checked + ); + myLibrary.push(book); render(); + + //clears the form for new entries + title.value = ""; + author.value = ""; + pages.value = ""; + check.checked = false; } } function Book(title, author, pages, check) { this.title = title; this.author = author; - this.pages = pages; + this.pages = Number(pages); this.check = check; } +function escapeSpecialCharacters(str) { + return str + .replace(/&/g, "&") + .replace(//g, ">") + .replace(/"/g, """) + .replace(/'/g, "'"); +} +function alertDeleteToast(message) { + const toast = document.getElementById("toast"); + toast.innerHTML = message; + toast.classList.add("visible"); + + setTimeout(() => { + toast.classList.remove("visible"); + }, 4000); +} 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 @@ -71,33 +104,31 @@ function render() { pagesCell.innerHTML = myLibrary[i].pages; //add and wait for action for read/unread button - let changeBut = document.createElement("button"); - changeBut.id = i; - changeBut.className = "btn btn-success"; - wasReadCell.appendChild(changeBut); - let readStatus = ""; - if (myLibrary[i].check == false) { - readStatus = "Yes"; - } else { - readStatus = "No"; - } - changeBut.innerText = readStatus; + let changeBtn = document.createElement("button"); + changeBtn.className = "btn btn-success"; + wasReadCell.appendChild(changeBtn); + + let readStatus = myLibrary[i].check ? "Yes" : "No"; + changeBtn.innerText = readStatus; - changeBut.addEventListener("click", function () { + changeBtn.addEventListener("click", function () { myLibrary[i].check = !myLibrary[i].check; 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 () { - alert(`You've deleted title: ${myLibrary[i].title}`); + let deleteBtn = document.createElement("button"); + deleteBtn.className = "btn btn-warning"; + deleteBtn.innerHTML = "Delete"; + deleteCell.appendChild(deleteBtn); + + deleteBtn.addEventListener("click", function () { + const deleteTitle = myLibrary[i].title; myLibrary.splice(i, 1); render(); + alertDeleteToast( + `You've deleted title:
${escapeSpecialCharacters(deleteTitle)}` + ); }); } } diff --git a/debugging/book-library/style.css b/debugging/book-library/style.css index 302950cb..187711fc 100644 --- a/debugging/book-library/style.css +++ b/debugging/book-library/style.css @@ -1,19 +1,94 @@ +.jumbotron { + padding: 1.5rem 2rem; + margin-bottom: 1rem; + text-align: center; +} + +.jumbotron h2 { + font-size: 1.5rem; + font-weight: 300; + margin-top: 0.5rem; +} + .form-group { width: 400px; height: 300px; - align-self: left; - padding-left: 20px; + padding-left: 50px; +} + +#check { + margin-left: 0; + margin-top: 10px; } .btn { display: block; } +.form-control { + border-style: solid; + border-color: lightslategrey; +} + .form-check-label { padding-left: 20px; margin: 5px 0px 5px 0px; } -button.btn-info { - margin: 20px; +.btn-info { + background-color: blue; + border-color: blue; + color: #fff; + margin: 20px 20px 20px 50px; +} + +.btn-success { + background-color: #0d4a0d; + border-color: #0d4a0d; + color: #fff; +} + +.btn-success:hover, +.btn-success:focus { + background-color: #1f6e1f; + border-color: #1f6e1f; + color: #fff; +} + +.btn-warning { + background-color: #9f6000; + border-color: #9f6000; + color: #fff; +} + +.btn-warning:hover, +.btn-warning:focus { + background-color: #b76e01; + border-color: #b76e01; + color: #fff; +} + +/* for delete alert */ +.toast { + position: fixed; + top: 130px; + left: 50%; + font-size: 1rem; + transform: translateX(-50%); + background: #a84600; + color: white; + min-width: 300px; + width: fit-content; + white-space: normal; + word-wrap: break-word; + text-align: center; + padding: 10px 15px; + border-radius: 5px; + opacity: 0; + transition: opacity 0.3s ease; + pointer-events: none; +} + +.toast.visible { + opacity: 1; }