Added book adding, README, modified looks
This commit is contained in:
parent
ce59d1b051
commit
6a73665b98
|
@ -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)
|
Binary file not shown.
After Width: | Height: | Size: 237 KiB |
20
index.html
20
index.html
|
@ -10,8 +10,28 @@
|
|||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" integrity="sha512-DTOQO9RWCH3ppGqcWaEA1BIZOC6xxalwEsw9c2QQeAIftl+Vegovlnee1c9QX4TctnWMn13TZye+giMm8e2LwA==" crossorigin="anonymous" referrerpolicy="no-referrer" />
|
||||
</head>
|
||||
<body>
|
||||
<dialog>
|
||||
<form method="dialog" id="form">
|
||||
<section><label for="title">title: </label> <input type="text" name="title" id="title" required></section>
|
||||
<section><label for="author">author: </label> <input type="text" name="author" id="author" required></section>
|
||||
<section><label for="pages">pages: </label> <input type="number" name="pages" id="pages" required></section>
|
||||
<section>
|
||||
<label for="">status: </label>
|
||||
<input type="radio" name="status" id="yes" value="true" required checked>
|
||||
<label for="yes">Read</label>
|
||||
<input type="radio" name="status" id="no" value="false">
|
||||
<label for="no">Not read yet</label>
|
||||
</section>
|
||||
<section>
|
||||
<button type="submit">Add book</button>
|
||||
</section>
|
||||
</form>
|
||||
</dialog>
|
||||
<header>
|
||||
<h1>boocks</h1>
|
||||
<button type="button" id="new-book">
|
||||
<i class="fa-solid fa-plus"></i> New book
|
||||
</button>
|
||||
</header>
|
||||
<div id="books">
|
||||
|
||||
|
|
176
script.js
176
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 = "";
|
||||
// })
|
||||
// })
|
||||
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;
|
||||
});
|
92
style.css
92
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 {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue