-
Notifications
You must be signed in to change notification settings - Fork 0
/
script.js
196 lines (171 loc) · 7.59 KB
/
script.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
/* Mechanisim for removing focus outline without disturbing accessibility */
document.body.addEventListener("mousedown", () => document.body.classList.add("using-mouse"));
document.body.addEventListener("keydown", (e) => {
if(e.key === "Tab") {
document.body.classList.remove("using-mouse");
}
});
/* Initilialization for various controls on a page */
const newBookButton = document.querySelector(".new-book");
const booksDisplay = document.querySelector(".books-display");
newBookButton.addEventListener("click", () => {
document.querySelector(".bg-modal").style.display = "flex";
});
document.querySelector(".close").addEventListener("click", closeModal);
document.querySelector(".cancel").addEventListener("click", closeModal);
document.querySelector(".bg-modal form .submit").addEventListener("click", submitNewBookForm);
/* Defines what a Book object is and how they are stored */
let myLibrary = [];
class Book {
title;
author;
pages;
read;
constructor(title, author, pages, read) {
this.title = title;
this.author = author;
this.pages = pages;
this.read = read;
}
}
/* Initializes localStorage */
const localStorageWorks = isStorageAvailable("localStorage");
const localStorage = window.localStorage;
if(localStorageWorks) {
if(!localStorage.getItem("myLibrary")) {
localStorage.setItem("myLibrary",JSON.stringify(myLibrary));
} else {
myLibrary = JSON.parse(localStorage.getItem("myLibrary"));
rerender();
}
}
/* callback function for the "Submit" button on the modal popup that handles adding a new book to the library */
function submitNewBookForm(e) {
const isValid = document.querySelector('.bg-modal form').reportValidity();
if (!isValid) {
return;
}
const title = document.getElementById("name-text").value;
const author = document.getElementById("author-text").value;
const pages = document.getElementById("pages-text").value;
const read = document.getElementById("read-book").checked;
addBookToLibrary(title,author,pages,read);
closeModal();
}
/* Callback function handling removing a book from the library when the X button on a book is clicked */
function onClickOfXButtonOnBook(e) {
const bookContainer = e.currentTarget.closest(".book-container");
const title = bookContainer.querySelector(".book-title").textContent;
const author = bookContainer.querySelector(".book-author").textContent.slice(3);
const pages = +bookContainer.querySelector(".book-pages").textContent.slice(0,
bookContainer.querySelector(".book-pages").textContent.indexOf("p")-1);
const read = bookContainer.querySelector(".book-read").textContent === "Completed" ? true : false;
const bookToDelete = myLibrary.find(book => {
return book.title === title && book.author === author && book.pages === pages && book.read === read;
});
deleteBookFromLibrary(bookToDelete);
}
/* Callback function handling toggling a book's "book read" state when the book read text is clicked */
function onClickOfBookReadText(e) {
const bookContainer = e.currentTarget.closest(".book-container");
const title = bookContainer.querySelector(".book-title").textContent;
const author = bookContainer.querySelector(".book-author").textContent.slice(3);
const pages = +bookContainer.querySelector(".book-pages").textContent.slice(0,
bookContainer.querySelector(".book-pages").textContent.indexOf("p")-1); const read = bookContainer.querySelector(".book-read").textContent === "Completed" ? true : false;
const bookToUpdate = myLibrary.find(book => {
return book.title === title && book.author === author && book.pages === pages && book.read === read;
});
updateBookInLibrary(bookToUpdate,title,author,pages,!read)
}
/* Handles adding a new book to the library */
function addBookToLibrary(title,author,pages,read) {
const newBook = new Book(title,author,+pages,read);
myLibrary.push(newBook);
rerender();
updateLocalStorage();
}
/* Handles deleting a book to the library */
function deleteBookFromLibrary(book) {
myLibrary.splice(myLibrary.indexOf(book),1);
rerender();
updateLocalStorage();
}
/* Handles updating the information associated with a book in the library */
function updateBookInLibrary(book,title,author,pages,read) {
book.title = title;
book.author = author;
book.pages = pages;
book.read=read;
rerender();
updateLocalStorage();
}
/* updates the graphical display of the library to comply with the myLibrary array,
displaying the last element in the array first on the graphical interface */
function rerender() {
booksDisplay.textContent = "";
for(let i = 0; i < myLibrary.length; i++) {
const newBookContainer = document.createElement("div");
newBookContainer.classList.add("book-container");
const bookOptions = document.createElement("div");
bookOptions.classList.add("options");
const bookRemove = document.createElement("button");
bookRemove.classList.add("remove");
bookRemove.setAttribute("src","images/001-close.png");
bookRemove.setAttribute("alt","remove");
bookRemove.setAttribute("type","button");
const bookRemoveImage = document.createElement("img");
bookRemoveImage.setAttribute("src","images/001-close.png");
bookRemoveImage.setAttribute("alt","remove");
bookRemove.appendChild(bookRemoveImage);
bookOptions.appendChild(bookRemove);
newBookContainer.appendChild(bookOptions);
const bookTitle = document.createElement("h2");
bookTitle.classList.add("book-title");
bookTitle.textContent = myLibrary[i].title;
newBookContainer.appendChild(bookTitle);
const bookAuthor = document.createElement("p");
bookAuthor.classList.add("book-author");
bookAuthor.textContent = `by ${myLibrary[i].author}`;
newBookContainer.appendChild(bookAuthor);
const bookPages = document.createElement("p");
bookPages.textContent = `${myLibrary[i].pages} pages`;
bookPages.classList.add("book-pages");
newBookContainer.appendChild(bookPages);
const bookReadParagraph = document.createElement("p");
bookReadParagraph.textContent = myLibrary[i].read ? "Completed" : "Not read yet";
bookReadParagraph.classList.add("book-read");
if(myLibrary[i].read) {
bookReadParagraph.classList.add("completed");
}
newBookContainer.appendChild(bookReadParagraph);
newBookContainer.querySelector(".remove").addEventListener("click",onClickOfXButtonOnBook);
newBookContainer.querySelector(".book-read").addEventListener("click",onClickOfBookReadText);
booksDisplay.prepend(newBookContainer);
}
}
/* callback function for closing the modal that enables input of data for a new book */
function closeModal() {
document.querySelector(".bg-modal").style.display = "none";
document.querySelector(".bg-modal form").reset();
}
/* Checks whether localStorage is supported and available */
function isStorageAvailable(type) {
let storage;
try {
storage = window[type];
let x = "__storage_text__";
storage.setItem(x,x);
storage.removeItem(x);
return true;
} catch {
return e instanceof DOMException && (
e.code === 22 ||
e.code === 1014 ||
e.name === "QuotaExceededError" ||
e.name === "NS_ERROR_DOM_QUOTA_REACHED") &&
(storage && storage.length !== 0);
}
}
function updateLocalStorage() {
localStorage.setItem("myLibrary",JSON.stringify(myLibrary));
}