Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions Project Library with Classes/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="title" content="Project Library" />
<meta name="image" property="og:image" content="library-icon.png" href="library-icon.png" />
<meta name="description" content="Project Library for Social Hackers Academy" />
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-eOJMYsd53ii+scO/bJGFsiCZc+5NDVN2yr8+0RDqr0Ql0h+rP48ckxlpbzKgwra6" crossorigin="anonymous">
<link rel="stylesheet" type="text/css" href="styles.css" />
<link rel="icon" type="image" href="library-icon.png">
<title>Project Library</title>
</head>
<body class="container bg-light ">
<section class="container mt-5 justify-content-center text-center">
<h1>A Personal Library inside your Browser</h1>
<h2 class="mt-4">Add Books to the list below!</h2>
<button class="mt-5 mb-5 btn btn-primary btn-lg" id="btn-new-book" type="button">NEW BOOK!</button>
</section>

<form class="mt-4 col-md-6 mx-auto text-center " id="form">
<div>
<input class="form-control text-center fs-5" type="text" id="title" placeholder="Title" required aria-required="true" />
</div>
<div class="mt-2">
<input class="form-control text-center fs-5" type="text" id="author" placeholder="Author" required aria-required="true"/>
</div>
<div class="mt-2">
<input class="form-control text-center fs-5" type="number" id="pages" placeholder="Pages" />
</div>
<div class="form-check form-check-inline mt-2">
<input class="form-check-input fs-5" type="checkbox" id="status" />
<label class="form-check-label fs-5 " for="status"> Read </label>
</div>
<div>
<button class="btn btn-primary mt-2" id="btn-add-book" type="submit">Add Book!</button>
</div>
</form>

<table class="table table-hover text-center mt-5 " id="table-library">
<thead class="table-dark">
<th>Book Title</th>
<th>Author</th>
<th>Page No</th>
<th>Have your read it?</th>
<th>Remove Book?</th>
</thead>
<tbody class="table-secondary"></tbody>
</table>

<script src="index.js"></script>
</body>
</html>
171 changes: 171 additions & 0 deletions Project Library with Classes/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
"use strict";

let myLibrary = [];
const form = document.querySelector("#form");
const bookTitle = document.querySelector("#title");
const bookAuthor = document.querySelector("#author");
const bookPages = document.querySelector("#pages");
const bookStatus = document.querySelector("#status");
const btnNewBook = document.querySelector("#btn-new-book");
const btnAddBook = document.querySelector("#btn-add-book");
const tableBody = document.querySelector("#table-library > tbody");

// Book Class constructor
class Book {
constructor(title, author, pages, status) {
this.title = title;
this.author = author;
this.pages = pages;
this.status = status;
}

toggleStatus = function () {
this.status = !this.status;
};

info = function () {
if (!this.status) {
return `${this.title} by ${this.author}, ${this.pages} pages, has not been read yet`;
} else {
return `${this.title} by ${this.author}, ${this.pages} pages, has been read`;
}
};

}

// adding new book to the Library array
function addBookToLibrary(title, author, pages, status, array) {
const newBook = new Book(title, author, pages, status);
array.push(newBook);
}

// reload localStorage
function reloadLocalStorage() {
if (localStorage.length === 0 || localStorage.myLibrary === "[]") {
addBookToLibrary("Harry Potter", "J. K. Rowling", 395, true, myLibrary);
} else {
let arrayDestringified = JSON.parse(localStorage.getItem("myLibrary"));
arrayDestringified.forEach((element) => {
addBookToLibrary(element.title, element.author, element.pages, element.status, myLibrary);
});
}
}
reloadLocalStorage();

// displaying form (modal)
btnNewBook.addEventListener("click", () => {
// form.classList.remove("hide");
displayElement(form);
form.classList.add("display-block");
hideElement(btnNewBook);
});

// adding book in DOM list
const getFormInfo = (e) => {
e.preventDefault();
const targetTitle = e.target.title.value;
const targetAuthor = e.target.author.value;
const targetPages = e.target.pages.value;
const targetStatus = e.target.status.checked;

addBookToLibrary(targetTitle, targetAuthor, targetPages, targetStatus, myLibrary);
render(myLibrary, tableBody);
saveLibraryToLocalStorage("myLibrary", myLibrary);
clearForm();
hideElement(form);
displayElement(btnNewBook);
};
form.addEventListener("submit", getFormInfo);

// rendering new book from myLibrary array to the Dom
function render(array, parentDiv) {
parentDiv.innerHTML = "";
for (let i = 0; i < array.length; i++) {
let row = `<tr data-book-title="${array[i].title}">
<td>${array[i].title}</td>
<td>${array[i].author}</td>
<td>${array[i].pages}</td>
<td>
<button class="${array[i].status ? "btn-status btn-success" : "btn-status btn-warning"} btn">
${array[i].status ? "Read!" : "Unread"}
</button>
</td>
<td><button class="btn btn-danger btn-remove-book">REMOVE</button></td>
</tr>`;

parentDiv.insertAdjacentHTML("beforeend", row);
}
}
render(myLibrary, tableBody);

// hiding element from the page
function hideElement(element) {
element.classList.add("hide");
}
hideElement(form);

// displaying element to the page
function displayElement(element) {
element.classList.remove("hide");
form.classList.add("display-block");
}

// clearing form
function clearForm() {
bookTitle.value = "";
bookAuthor.value = "";
bookPages.value = "";
bookStatus.checked = "";
}

// removing book from Library and from the DOM
tableBody.addEventListener("click", (e) => {
if (!e.target.classList.contains("btn-remove-book")) {
return;
}
e.target.closest("tr").remove();

let currentBookTitle = e.target.closest("tr").dataset.bookTitle;
removeBookFromLibrary(myLibrary, currentBookTitle);
saveLibraryToLocalStorage("myLibrary", myLibrary);
});

function removeBookFromLibrary(libraryArray, bookTitle) {
if (libraryArray.length === 0) {
return;
}

for (let book of libraryArray) {
if (book.title === bookTitle) {
let bookToRemoveIndex = libraryArray.indexOf(book);
libraryArray.splice(bookToRemoveIndex, 1);
}
}
}

// Changing the book status in the DOM and inside myLibrary
tableBody.addEventListener("click", (e) => {
if (!e.target.classList.contains("btn-status")) {
return;
}
let currentBtn = e.target;
let currentBookTitle = e.target.closest("tr").dataset.bookTitle;
toggleBookStatus(myLibrary, currentBookTitle, currentBtn);
saveLibraryToLocalStorage("myLibrary", myLibrary);
});

function toggleBookStatus(libraryArray, bookTitle, currentElement) {
for (let book of libraryArray) {
if (book.title === bookTitle) {
book.toggleStatus();
currentElement.innerText = book.status ? "Read" : "Unread";
currentElement.classList.remove(`${book.status ? "btn-warning" : "btn-success"}`);
currentElement.classList.add(`${book.status ? "btn-success" : "btn-warning"}`);
}
}
}

// saving library to localStorage
function saveLibraryToLocalStorage(arrayName, array) {
localStorage.setItem(arrayName, JSON.stringify(array));
}
Binary file added Project Library with Classes/library-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions Project Library with Classes/styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.hide {
display: none!important;
/* visibility: hidden!important; */
}