diff --git a/README.md b/README.md
new file mode 100644
index 0000000..fce66d3
--- /dev/null
+++ b/README.md
@@ -0,0 +1,15 @@
+# odin-library
+
+A simple book tracking site using vanilla HTML CSS JS
+
+boocks - book/tracks
+
+### todo:
+
+* save library to cookies / localstorage
+* edit existing books
+
+## pics
+
+![Alt text](image.png)
+![Alt text](image-1.png)
\ No newline at end of file
diff --git a/image-1.png b/image-1.png
new file mode 100644
index 0000000..c599340
Binary files /dev/null and b/image-1.png differ
diff --git a/image.png b/image.png
new file mode 100644
index 0000000..f130d87
Binary files /dev/null and b/image.png differ
diff --git a/index.html b/index.html
index 87d1530..14ae915 100644
--- a/index.html
+++ b/index.html
@@ -10,8 +10,28 @@
+
diff --git a/script.js b/script.js
index 5ac5bee..d5472a1 100644
--- a/script.js
+++ b/script.js
@@ -9,92 +9,128 @@ function Book(title, author, pages, read) {
this.read = read;
}
-function addBookToLibrary(book) {
- library.push(book);
+function addBookToLibrary(title, author, pages, read) {
+ let bookObject = new Book(title, author, pages, read);
+ library.push(bookObject);
+ displayBooks();
+}
+
+
+function removeBookFromLibrary(dataId) {
+ library.splice(dataId, 1);
+ displayBooks();
}
let books = [
- ["book", "author", 1, true],
- ["book", "author", 1, true],
- ["book", "author", 1, true],
- ["book", "author", 1, true],
- ["book", "author", 1, true],
- ["book", "author", 1, true],
- ["book", "author", 1, true],
- ["book", "author", 1, true],
- ["book", "author", 1, true],
- ["book", "author", 1, true],
- ["book", "author", 1, true],
+ ["The Hobbit", "J.R.R. Tolkien", 295, false],
+ ["Jessica's Guide to Dating on the Dark Side", "Natalie M. Pete-Clarkson Jr.", 295, false],
+
]
-books.forEach(book => {
- let aBook = new Book(book[0], book[1], book[2], book[3]);
- addBookToLibrary(aBook);
+if (books.length) {
+ books.forEach(book => {
+ addBookToLibrary(book[0], book[1], book[2], book[3]);
+ })
+} else {
displayBooks();
-})
+}
+
function displayBooks() {
bookGrid.querySelectorAll("& > *").forEach(book => {
book.remove();
})
- let pos = 0;
- library.forEach(book => {
- bookDiv = document.createElement("div");
- bookDiv.classList.add("book");
- bookDiv.setAttribute("arrayPos", pos)
+ let dataId = 0;
+ if (library.length) {
+ library.forEach(book => {
+ let bookDiv = document.createElement("div");
+ bookDiv.classList.add("book");
+ bookDiv.setAttribute("data-id", dataId)
- bookDetails = document.createElement("div");
- bookDetails.classList.add("book-details");
- bookDetails.innerText = `${book.title}\n${book.author}\n${book.pages} pages\n${book.read ? "read" : "not read yet"}`;
- bookDiv.append(bookDetails);
+ let bookDetails = document.createElement("div");
+ bookDetails.classList.add("book-details");
- bookActions = document.createElement("div");
- bookActions.classList.add("book-actions");
-
- toggleRead = document.createElement("i");
- toggleRead.classList.add("fa-solid", "fa-book");
- toggleRead.addEventListener("click", function() {
- library[this.parentNode.parentNode.getAttribute("arrayPos")].read = !library[this.parentNode.parentNode.getAttribute("arrayPos")].read;
- displayBooks();
- });
- bookActions.append(toggleRead);
+ let allDetails = {
+ "title": `${book.title}`,
+ "author": `${book.author}`,
+ "pages": `${book.pages}`,
+ "status": `${book.read ? "read" : "not read yet"}`,
+ };
- edit = document.createElement("i");
- edit.classList.add("fa-solid", "fa-edit");
- edit.addEventListener("click", function() {
- library.splice(this.parentNode.parentNode.getAttribute("arrayPos"), 1);
- displayBooks();
- });
- bookActions.append(edit);
+ for (detail in allDetails) {
+ let detailNameContain = document.createElement("div");
+ detailNameContain.classList.add("detail-name");
- removeBtn = document.createElement("i");
- removeBtn.classList.add("fa-solid", "fa-trash");
- removeBtn.addEventListener("click", function() {
- library.splice(this.parentNode.parentNode.getAttribute("arrayPos"), 1);
- displayBooks();
- });
- bookActions.append(removeBtn);
+ let detailName = document.createElement("span");
+ detailName.textContent = `${detail}: `;
+ detailNameContain.append(detailName);
- bookDiv.append(bookActions);
+ let detailContent = document.createElement("span");
+ detailContent.textContent = allDetails[detail];
+ detailContent.classList.add("detail-content");
- bookGrid.append(bookDiv);
- pos++;
- })
+ bookDetails.append(detailNameContain, detailContent);
+ };
+
+ bookDiv.append(bookDetails);
+
+ let bookActions = document.createElement("div");
+ bookActions.classList.add("book-actions");
+
+ let toggleRead = document.createElement("i");
+ toggleRead.classList.add("fa-solid", "fa-book");
+ toggleRead.addEventListener("click", function() {
+ library[this.parentNode.parentNode.getAttribute("data-id")].read = !library[this.parentNode.parentNode.getAttribute("data-id")].read;
+ displayBooks();
+ });
+ bookActions.append(toggleRead);
+
+ // let edit = document.createElement("i");
+ // edit.classList.add("fa-solid", "fa-edit");
+ // edit.addEventListener("click", function() {
+ // removeBookFromLibrary(this.parentNode.parentNode.getAttribute("data-id"));
+ // });
+ // bookActions.append(edit);
+
+ let removeBtn = document.createElement("i");
+ removeBtn.classList.add("fa-solid", "fa-trash");
+ removeBtn.addEventListener("click", function() {
+ removeBookFromLibrary(this.parentNode.parentNode.getAttribute("data-id"));
+ });
+ bookActions.append(removeBtn);
+
+ bookDiv.append(bookActions);
+
+ bookGrid.append(bookDiv);
+
+ dataId++;
+ })
+ } else {
+ let info = document.createElement("span");
+ info.classList.add("no-books");
+ info.textContent = "No books to list. Add some!";
+ bookGrid.append(info);
+ }
}
-// const newBookBtn = document.querySelector("button#new-book");
-// const newBookDialog = document.querySelector("dialog#new-book");
-// newBookBtn.addEventListener("click", () => {
-// newBookDialog.showModal();
-// })
-// newBookDialog.querySelector("button[type='submit']").addEventListener("click", () => {
-// let names = [];
-// newBookDialog.querySelectorAll("form > input").forEach(input => {
-// if (!names.includes(input.name)) {
-// names.push(input.name);
-// }
-// });
-// names.forEach(one => {
-// document.getElementsByName(one).value = "";
-// })
-// })
\ No newline at end of file
+const newBookBtn = document.querySelector("button#new-book");
+const newBookDialog = document.querySelector("dialog");
+newBookBtn.addEventListener("click", () => {
+ newBookDialog.showModal();
+})
+
+newBookDialog.querySelector("form").addEventListener("submit", (event) => {
+ let formData = new FormData(document.querySelector("form"));
+ let bookVals = []
+ for (let [key, value] of formData.entries()) {
+ bookVals.push(value);
+ }
+ addBookToLibrary(bookVals[0], bookVals[1], bookVals[2], bookVals[3]);
+});
+
+newBookDialog.addEventListener("close", (event) => {
+ newBookDialog.querySelectorAll("input").forEach(input => {
+ input.value = null;
+ })
+ newBookDialog.querySelector("input[type='radio']").checked = true;
+});
\ No newline at end of file
diff --git a/style.css b/style.css
index 7ce19f1..1f89bfb 100644
--- a/style.css
+++ b/style.css
@@ -1,7 +1,7 @@
@import url('https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,400;0,700;1,400;1,700&display=swap');
:root {
- font-family: 'Roboto', sans-serif;
+ font-family: "Roboto", system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
}
html, body {
@@ -18,35 +18,73 @@ header {
padding: 20px 40px;
box-sizing: border-box;
text-align: center;
+ display: flex;
+ justify-content: space-between;
h1 {
font-size: 2.5rem;
font-weight: bold;
}
+ button#new-book {
+ font-size: 1rem;
+ font-weight: bold;
+ border: 2px solid #444;
+ color: #fff;
+ background-color: #232323;
+ cursor: pointer;
+ outline: none;
+ border-radius: 15px;
+ padding: 5px 10px;
+ }
}
#books {
display: grid;
- grid-template-columns: repeat(auto-fit, minmax(max(20%, 270px), 1fr));
+ grid-template-columns: repeat(auto-fill, minmax(max(20%, 270px), 1fr));
gap: 20px;
padding: 20px;
+ .no-books {
+ font-size: 2rem;
+ text-shadow: 1px 1px 1px #2222dddd;
+ }
+
.book {
background-color: #1d1d1dcc;
- padding: 30px;
+ padding: 20px;
border-radius: 20px;
font-size: 1.3rem;
text-align: center;
display: flex;
flex-direction: row;
-
+ justify-content: space-between;
+ align-items: center;
+ gap: 10px;
.book-details {
- margin: auto;
+ flex: 1;
+ display: grid;
+ align-items: stretch;
+ grid-template-columns: 50px 1fr;
+ & > span {
+ display: block;
+ padding: 4px;
+ word-break: break-word;
+ }
+ span ~ span, .detail-name ~ .detail-name {
+ border-top: 1px solid #aaaaaaaa;
+ }
+ .detail-name {
+ color: #aaa;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 0.9rem;
+ }
}
.book-actions {
display: flex;
flex-direction: column;
gap: 8px;
- justify-content: flex-end;
+ justify-content: center;
i {
display: block;
font-size: 1.2rem;
@@ -79,12 +117,12 @@ header {
.fa-book::after {
content: "toggle read";
}
- .fa-edit:hover {
+ /* .fa-edit:hover {
color: rgb(219, 175, 30);
}
.fa-edit::after {
content: "edit";
- }
+ } */
.fa-trash:hover {
color: rgb(220, 85, 85);
}
@@ -93,4 +131,40 @@ header {
}
}
}
-}
\ No newline at end of file
+}
+
+dialog {
+ background-color: #000000aa;
+ padding: 50px 40px;
+ color: #fff;
+ &[open] ~ * {
+ filter: blur(6px);
+ }
+ section {
+ display: flex;
+ justify-content: space-between;
+ gap: 5px;
+ padding: 5px;
+ align-items: center;
+ input[type="text"], input[type="number"] {
+ padding: 5px;
+ border-radius: 10px;
+ background-color: #121212aa;
+ outline: none;
+ border: 1px solid #aaaaaaaa;
+ color: #fff;
+ }
+ button[type="submit"] {
+ padding: 5px;
+ border-radius: 10px;
+ background-color: #121212aa;
+ outline: none;
+ border: 1px solid #aaaaaaaa;
+ color: #fff;
+ font-size: 1rem;
+ cursor: pointer;
+ margin: auto;
+ }
+ }
+}
+