为什么在我 运行 函数后缺少某些元素?
Why some element are missing after I run the function?
我想做搜索引擎,但是我查了一些书,怎么也查不到。它只有 return 零本书。
//data.js
// {
// id: string | number,
// title: string,
// author: string,
// year: number,
// isComplete: boolean,
// }
const STORAGE_KEY = "BOOKSHELF_APP";
let books = [];
let booksSearched = [];
function isStorageExist() /* boolean */ {
return false // SO does not like localStorage
if (typeof(Storage) === undefined) {
alert("Your browser doesn't support web storage.");
return false;
}
return true;
}
function saveData() {
const parsed /* string */ = JSON.stringify(books);
localStorage.setItem(STORAGE_KEY, parsed);
document.dispatchEvent(new Event("ondatasaved"));
}
function loadDataFromStorage() {
const serializedData /* string */ = localStorage.getItem(STORAGE_KEY);
let data = JSON.parse(serializedData);
if (data !== null)
books = data;
document.dispatchEvent(new Event("ondataloaded"));
}
function updateDataToStorage() {
if (isStorageExist())
saveData();
}
function composeBookObject(title, author, year, isCompleted) {
return {
id: +new Date(),
title,
author,
year,
isCompleted
};
}
function findBookById(bookId) {
for (book of books) {
if (book.id === bookId)
return book;
}
return null;
}
function searchBookByTitle(bookTitle) {
for (book of books) {
if (book.title === bookTitle) {
return book;
}
}
return null;
}
function findBookIndexById(bookId) {
let index = 0
for (book of books) {
if (book.id === bookId)
return index;
index++;
}
return -1;
}
//dom.js
const UNFINISHED_BOOK_LIST_ID = 'unfinishedBookshelfList';
const FINISHED_BOOK_LIST_ID = 'finishedBookshelfList';
const BOOK_ITEMID = "itemId";
function makeBookList(data, author, year, isCompleted) {
const container = document.createElement('article');
container.classList.add('book_item');
const textTitle = document.createElement('h3');
textTitle.innerText = `Title: ${data}`;
const textAuthor = document.createElement('p');
textAuthor.innerText = `Author: ${author}`;
const textYear = document.createElement('p');
textYear.innerText = `Year: ${year}`;
const textContainer = document.createElement('div');
textContainer.append(textTitle, textAuthor, textYear);
container.append(textContainer);
const buttonContainer = document.createElement('div');
buttonContainer.classList.add('action');
if (isCompleted) {
buttonContainer.append(
createUndoButton(),
createTrashButton()
);
} else {
buttonContainer.append(
createCheckButton(),
createTrashButton()
);
}
container.append(buttonContainer);
return container;
}
function createButton(buttonTypeClass /* string */ , eventListener /* Event */ ) {
const button = document.createElement("button");
button.classList.add(buttonTypeClass);
button.addEventListener("click", function(event) {
eventListener(event);
event.stopPropagation();
});
if (buttonTypeClass == 'green1') {
button.innerText = 'Belum Selesai Dibaca';
} else if (buttonTypeClass == 'green2') {
button.innerText = 'Selesai Dibaca';
} else if (buttonTypeClass == 'red') {
button.innerText = 'Hapus Buku';
}
return button;
}
function createUndoButton() {
return createButton("green1", function(event) {
// const button = document.querySelector('.green');
// button.innerText = 'Belum Selesai Dibaca';
undoBookFromCompleted(event.target.closest('.book_item'));
});
}
function createTrashButton() {
return createButton("red", function(event) {
removeBookFromCompleted(event.target.closest(".book_item"));
});
}
function createCheckButton() {
return createButton("green2", function(event) {
addBookToCompleted(event.target.closest('.book_item'));
});
}
function addBook() {
const unfinishedBookList = document.getElementById(UNFINISHED_BOOK_LIST_ID);
const finishedBookList = document.getElementById(FINISHED_BOOK_LIST_ID);
const textTitle = document.getElementById('inputBookTitle').value;
const textAuthor = document.getElementById('inputBookAuthor').value;
const textYear = document.getElementById('inputBookYear').value;
const isCompleted = document.getElementById('inputBookIsCompleted').checked;
const book = makeBookList(textTitle, textAuthor, textYear, isCompleted);
const bookObject = composeBookObject(textTitle, textAuthor, textYear, isCompleted);
book[BOOK_ITEMID] = bookObject.id;
books.push(bookObject);
if (isCompleted) {
finishedBookList.append(book);
} else {
unfinishedBookList.append(book);
}
updateDataToStorage();
}
function addBookToCompleted(bookElement /* HTMLELement */ ) {
const listCompleted = document.getElementById(FINISHED_BOOK_LIST_ID);
const bookTitle = bookElement.querySelector("h3").innerText;
const bookAuthor = bookElement.querySelector("p:nth-of-type(1)").innerText;
const bookYear = bookElement.querySelector("p:nth-of-type(2)").innerText;
const newBook = makeBookList(bookTitle, bookAuthor, bookYear, true);
const book = findBookById(bookElement[BOOK_ITEMID]);
book.isCompleted = true;
newBook[BOOK_ITEMID] = book.id;
listCompleted.append(newBook);
bookElement.remove();
updateDataToStorage();
}
function removeBookFromCompleted(bookElement /* HTMLELement */ ) {
const bookPosition = findBookIndexById(bookElement[BOOK_ITEMID]);
books.splice(bookPosition, 1);
bookElement.remove();
updateDataToStorage();
document.dispatchEvent(new Event("onbookremoved"));
}
function undoBookFromCompleted(bookElement /* HTMLELement */ ) {
const listUncompleted = document.getElementById(UNFINISHED_BOOK_LIST_ID);
const bookTitle = bookElement.querySelector("h3").innerText;
const bookAuthor = bookElement.querySelector("p:nth-of-type(1)").innerText;
const bookYear = bookElement.querySelector("p:nth-of-type(2)").innerText;
const newBook = makeBookList(bookTitle, bookAuthor, bookYear, false);
const book = findBookById(bookElement[BOOK_ITEMID]);
book.isCompleted = false;
newBook[BOOK_ITEMID] = book.id;
listUncompleted.append(newBook);
bookElement.remove();
updateDataToStorage();
}
function searchBooks(bookTitle) {
// const bookShelf = document.querySelectorAll('.book_shelf');
const unfinishedBookList = document.getElementById(UNFINISHED_BOOK_LIST_ID);
const finishedBookList = document.getElementById(FINISHED_BOOK_LIST_ID);
const bookSearchedObject = searchBookByTitle(bookTitle);
booksSearched.push(bookSearchedObject);
// unfinishedBookList.childElement.remove();
// finishedBookList.childElement.remove();
const bookSearched = makeBookList(bookSearchedObject.title, bookSearchedObject.author, bookSearchedObject.year);
if (bookSearched.isCompleted) {
finishedBookList.append(bookSearched);
} else {
unfinishedBookList.append(bookSearched);
}
updateDataToStorage();
}
function refreshDataFromBooks() {
const listUncompleted = document.getElementById(UNFINISHED_BOOK_LIST_ID);
let listCompleted = document.getElementById(FINISHED_BOOK_LIST_ID);
for (book of books) {
const newBook = makeBookList(book.title, book.author, book.year, book.isCompleted);
newBook[BOOK_ITEMID] = book.id;
if (book.isCompleted) {
listCompleted.append(newBook);
} else {
listUncompleted.append(newBook);
}
}
}
//script.js
document.addEventListener("DOMContentLoaded", function() {
const submitForm /* HTMLFormElement */ = document.getElementById("inputBook");
submitForm.addEventListener("submit", function(event) {
event.preventDefault();
addBook();
});
const searchButton = document.getElementById('searchSubmit');
searchButton.addEventListener('click', function() {
event.preventDefault();
console.log('ok');
const bookList = document.querySelectorAll('.book_list article');
bookList.forEach(list => list.remove());
const searchBookTitleValue = document.getElementById('searchBookTitle').value;
searchBooks(searchBookTitleValue);
});
if (isStorageExist()) {
loadDataFromStorage();
}
});
document.addEventListener("ondatasaved", () => {
console.log("Data has been saved.");
});
document.addEventListener("ondataloaded", () => {
refreshDataFromBooks();
alert('Welcome back!');
});
document.addEventListener("onbookremoved", () => {
alert('Your book has removed from the list.');
});
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
body,
input,
button {
font-family: 'Open Sans', sans-serif;
}
input,
button {
font-size: 16px;
}
.head_bar {
padding: 12px;
display: flex;
align-items: center;
justify-content: center;
background-color: cornflowerblue;
color: white;
}
main {
max-width: 800px;
width: 80%;
margin: 0 auto;
padding: 16px;
}
.input_section {
display: flex;
flex-direction: column;
padding: 16px;
border: 1px solid black;
border-radius: 10px;
}
.input_section>h2 {
text-align: center;
color: cornflowerblue;
}
.input_section>form>.input {
margin: 8px 0;
}
.input_section>form>button {
background-color: cornflowerblue;
color: white;
border: 0;
border-radius: 5px;
display: block;
width: 100%;
padding: 8px;
cursor: pointer;
}
.input_section>form>button>span {
font-weight: bold;
}
.input_section>form>.input>input {
display: block;
width: 100%;
padding: 8px;
border-radius: 5px;
}
.input_section>form>.input>label {
color: cornflowerblue;
font-weight: bold;
}
.input_section>form>.input_inline {
margin: 12px 0;
display: flex;
align-items: center;
}
.input_section>form>.input_inline>label {
color: cornflowerblue;
font-weight: bold;
margin-right: 10px;
}
.search_section {
margin: 16px 0;
display: flex;
flex-direction: column;
align-items: center;
padding: 16px;
border: 1px solid black;
border-radius: 10px;
}
.search_section>h2 {
color: cornflowerblue;
}
.search_section>form {
padding: 16px;
width: 100%;
display: grid;
grid-template-columns: auto 1fr 0.5fr;
grid-gap: 10px;
}
.search_section>form>label {
display: flex;
align-items: center;
}
.search_section>form>input {
padding: 5px;
border-radius: 5px;
}
.search_section>form>button {
background-color: cornflowerblue;
color: white;
border: 0;
border-radius: 5px;
cursor: pointer;
}
.book_shelf {
margin: 16px 0 0 0;
border: 1px solid black;
padding: 16px;
border-radius: 10px;
}
.book_shelf>h2 {
color: cornflowerblue;
}
.book_shelf>.book_list {
padding: 16px;
}
.book_shelf>.book_list>.book_item {
height: auto;
padding: 8px 16px 16px 16px;
border: 1px solid black;
border-radius: 5px;
margin: 10px 0;
display: flex;
justify-content: space-between;
}
.book_item>.action {
width: auto;
height: 30px;
margin: auto 5px;
border-radius: 10%;
display: flex;
place-content: center;
flex-basis: 1;
gap: 5px
}
.book_shelf>.book_list>.book_item>h3,
p {
margin: 8px 0;
}
.book_shelf>.book_list>.book_item>.action>button {
border: 0;
padding: 5px;
margin: 0 5px 0 0;
border-radius: 5px;
cursor: pointer;
/* }
.green1, .green2, .red { */
display: flex;
align-items: center;
/* place-content: center; */
}
.book_shelf>.book_list>.book_item>.action>.green1,
.book_shelf>.book_list>.book_item>.action>.green2 {
background-color: darkgreen;
color: white;
}
.book_shelf>.book_list>.book_item>.action>.red {
background-color: darkred;
color: white;
}
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Bookshelf Apps</title>
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;400;600;700;800&display=swap" rel="stylesheet">
<link rel="stylesheet" href="style.css">
</head>
<body>
<header class="head_bar">
<h1 class="head_bar__title">Bookshelf Apps</h1>
</header>
<main>
<section class="input_section">
<h2>Input New Book</h2>
<form id="inputBook">
<div class="input">
<label for="inputBookTitle">Title</label>
<input id="inputBookTitle" type="text" required>
</div>
<div class="input">
<label for="inputBookAuthor">Author</label>
<input id="inputBookAuthor" type="text" required>
</div>
<div class="input">
<label for="inputBookYear">Year</label>
<input id="inputBookYear" type="number" required>
</div>
<div class="input_inline">
<label for="inputBookIsCompleted">Finished Reading</label>
<input id="inputBookIsCompleted" type="checkbox">
</div>
<button id="bookSubmit" type="submit">Input Your Book To Bookshelf <span>Unfinished Reading</span></button>
</form>
</section>
<section class="search_section">
<h2>Search Book</h2>
<form id="searchBook">
<label for="searchBookTitle">Title</label>
<input id="searchBookTitle" type="text">
<button id="searchSubmit" type="submit">Search</button>
</form>
</section>
<section class="book_shelf">
<h2>Unfinished Reading</h2>
<div id="unfinishedBookshelfList" class="book_list">
</div>
</section>
<section class="book_shelf">
<h2>Selesai dibaca</h2>
<div id="finishedBookshelfList" class="book_list">
</div>
</section>
</main>
<script src="js/data.js"></script>
<script src="js/dom.js"></script>
<script src="js/script.js"></script>
</body>
</html>
已编辑:我需要触发 onbookremoved
事件来显示警报。但是在我点击从已完成的按钮中删除图书后,警报没有出现。
dom.js
function removeBookFromCompleted(bookElement /* HTMLELement */) {
const bookPosition = findBookIndexById(bookElement[BOOK_ITEMID]);
books.splice(bookPosition, 1);
bookElement.remove();
updateDataToStorage();
document.dispatchEvent(new Event("onbookremoved"));
}
script.js
document.addEventListener("onbookremoved", () => {
alert('Your book has removed from the list.');
});
您的 booklist.remove 擦除了列表而不是文章
const bookList = document.querySelectorAll('.book_list article');
我也加了
if (book.title.toLowerCase() === bookTitle.toLowerCase()) {
你还有其他几个问题
if (book.isCompleted) { // should be bookSearched.isCompleted
finishedBookList.append(bookSearched);
} else {
unfinishedBookList.append(bookSearched);
}
//data.js
// {
// id: string | number,
// title: string,
// author: string,
// year: number,
// isComplete: boolean,
// }
const STORAGE_KEY = "BOOKSHELF_APP";
let books = [];
let booksSearched = [];
function isStorageExist() /* boolean */ {
return false // SO does not like localStorage
if (typeof(Storage) === undefined) {
alert("Your browser doesn't support web storage.");
return false;
}
return true;
}
function saveData() {
const parsed /* string */ = JSON.stringify(books);
localStorage.setItem(STORAGE_KEY, parsed);
document.dispatchEvent(new Event("ondatasaved"));
}
function loadDataFromStorage() {
const serializedData /* string */ = localStorage.getItem(STORAGE_KEY);
let data = JSON.parse(serializedData);
if (data !== null)
books = data;
document.dispatchEvent(new Event("ondataloaded"));
}
function updateDataToStorage() {
if (isStorageExist())
saveData();
}
function composeBookObject(title, author, year, isCompleted) {
return {
id: +new Date(),
title,
author,
year,
isCompleted
};
}
function findBookById(bookId) {
for (book of books) {
if (book.id === bookId)
return book;
}
return null;
}
function searchBookByTitle(bookTitle) {
console.log(bookTitle, books)
for (book of books) {
if (book.title.toLowerCase() === bookTitle.toLowerCase()) {
return book;
}
}
return null;
}
function findBookIndexById(bookId) {
let index = 0
for (book of books) {
if (book.id === bookId)
return index;
index++;
}
return -1;
}
//dom.js
const UNFINISHED_BOOK_LIST_ID = 'unfinishedBookshelfList';
const FINISHED_BOOK_LIST_ID = 'finishedBookshelfList';
const BOOK_ITEMID = "itemId";
function makeBookList(data, author, year, isCompleted) {
const container = document.createElement('article');
container.classList.add('book_item');
const textTitle = document.createElement('h3');
textTitle.innerText = `Title: ${data}`;
const textAuthor = document.createElement('p');
textAuthor.innerText = `Author: ${author}`;
const textYear = document.createElement('p');
textYear.innerText = `Year: ${year}`;
const textContainer = document.createElement('div');
textContainer.append(textTitle, textAuthor, textYear);
container.append(textContainer);
const buttonContainer = document.createElement('div');
buttonContainer.classList.add('action');
if (isCompleted) {
buttonContainer.append(
createUndoButton(),
createTrashButton()
);
} else {
buttonContainer.append(
createCheckButton(),
createTrashButton()
);
}
container.append(buttonContainer);
return container;
}
function createButton(buttonTypeClass /* string */ , eventListener /* Event */ ) {
const button = document.createElement("button");
button.classList.add(buttonTypeClass);
button.addEventListener("click", function(event) {
eventListener(event);
event.stopPropagation();
});
if (buttonTypeClass == 'green1') {
button.innerText = 'Belum Selesai Dibaca';
} else if (buttonTypeClass == 'green2') {
button.innerText = 'Selesai Dibaca';
} else if (buttonTypeClass == 'red') {
button.innerText = 'Hapus Buku';
}
return button;
}
function createUndoButton() {
return createButton("green1", function(event) {
// const button = document.querySelector('.green');
// button.innerText = 'Belum Selesai Dibaca';
undoBookFromCompleted(event.target.closest('.book_item'));
});
}
function createTrashButton() {
return createButton("red", function(event) {
removeBookFromCompleted(event.target.closest(".book_item"));
});
}
function createCheckButton() {
return createButton("green2", function(event) {
addBookToCompleted(event.target.closest('.book_item'));
});
}
function addBook() {
const unfinishedBookList = document.getElementById(UNFINISHED_BOOK_LIST_ID);
const finishedBookList = document.getElementById(FINISHED_BOOK_LIST_ID);
const textTitle = document.getElementById('inputBookTitle').value;
const textAuthor = document.getElementById('inputBookAuthor').value;
const textYear = document.getElementById('inputBookYear').value;
const isCompleted = document.getElementById('inputBookIsCompleted').checked;
const book = makeBookList(textTitle, textAuthor, textYear, isCompleted);
const bookObject = composeBookObject(textTitle, textAuthor, textYear, isCompleted);
book[BOOK_ITEMID] = bookObject.id;
books.push(bookObject);
if (isCompleted) {
finishedBookList.append(book);
} else {
unfinishedBookList.append(book);
}
updateDataToStorage();
}
function addBookToCompleted(bookElement /* HTMLELement */ ) {
const listCompleted = document.getElementById(FINISHED_BOOK_LIST_ID);
const bookTitle = bookElement.querySelector("h3").innerText;
const bookAuthor = bookElement.querySelector("p:nth-of-type(1)").innerText;
const bookYear = bookElement.querySelector("p:nth-of-type(2)").innerText;
const newBook = makeBookList(bookTitle, bookAuthor, bookYear, true);
const book = findBookById(bookElement[BOOK_ITEMID]);
book.isCompleted = true;
newBook[BOOK_ITEMID] = book.id;
listCompleted.append(newBook);
bookElement.remove();
updateDataToStorage();
}
function removeBookFromCompleted(bookElement /* HTMLELement */ ) {
const bookPosition = findBookIndexById(bookElement[BOOK_ITEMID]);
books.splice(bookPosition, 1);
bookElement.remove();
updateDataToStorage();
}
function undoBookFromCompleted(bookElement /* HTMLELement */ ) {
const listUncompleted = document.getElementById(UNFINISHED_BOOK_LIST_ID);
const bookTitle = bookElement.querySelector("h3").innerText;
const bookAuthor = bookElement.querySelector("p:nth-of-type(1)").innerText;
const bookYear = bookElement.querySelector("p:nth-of-type(2)").innerText;
const newBook = makeBookList(bookTitle, bookAuthor, bookYear, false);
const book = findBookById(bookElement[BOOK_ITEMID]);
book.isCompleted = false;
newBook[BOOK_ITEMID] = book.id;
listUncompleted.append(newBook);
bookElement.remove();
updateDataToStorage();
}
function searchBooks(bookTitle) {
// const bookShelf = document.querySelectorAll('.book_shelf');
const unfinishedBookList = document.getElementById(UNFINISHED_BOOK_LIST_ID);
const finishedBookList = document.getElementById(FINISHED_BOOK_LIST_ID);
const bookSearchedObject = searchBookByTitle(bookTitle) || {
title: "na",
author: "na",
year: "na"
};
booksSearched.push(bookSearchedObject);
// unfinishedBookList.childElement.remove();
// finishedBookList.childElement.remove();
const bookSearched = makeBookList(bookSearchedObject.title, bookSearchedObject.author, bookSearchedObject.year);
// const bookElement = document.querySelectorAll('.book_item');
// if(bookShelf !== null) {
if (bookSearched.isCompleted) {
finishedBookList.append(bookSearched);
} else {
unfinishedBookList.append(bookSearched);
}
updateDataToStorage();
}
function refreshDataFromBooks() {
const listUncompleted = document.getElementById(UNFINISHED_BOOK_LIST_ID);
let listCompleted = document.getElementById(FINISHED_BOOK_LIST_ID);
for (book of books) {
const newBook = makeBookList(book.title, book.author, book.year, book.isCompleted);
newBook[BOOK_ITEMID] = book.id;
if (book.isCompleted) {
listCompleted.append(newBook);
} else {
listUncompleted.append(newBook);
}
}
}
//script.js
document.addEventListener("DOMContentLoaded", function() {
const submitForm /* HTMLFormElement */ = document.getElementById("inputBook");
submitForm.addEventListener("submit", function(event) {
event.preventDefault();
addBook();
});
const searchButton = document.getElementById('searchSubmit');
searchButton.addEventListener('click', function() {
event.preventDefault();
console.log('ok');
const bookList = document.querySelectorAll('.book_list article'); // changed
bookList.forEach(list => list.remove());
const searchBookTitleValue = document.getElementById('searchBookTitle').value;
searchBooks(searchBookTitleValue);
});
if (isStorageExist()) {
loadDataFromStorage();
}
});
document.addEventListener("ondatasaved", () => {
console.log("Data has been saved.");
});
document.addEventListener("ondataloaded", () => {
refreshDataFromBooks();
alert('Welcome back!');
});
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
body,
input,
button {
font-family: 'Open Sans', sans-serif;
}
input,
button {
font-size: 16px;
}
.head_bar {
padding: 12px;
display: flex;
align-items: center;
justify-content: center;
background-color: cornflowerblue;
color: white;
}
main {
max-width: 800px;
width: 80%;
margin: 0 auto;
padding: 16px;
}
.input_section {
display: flex;
flex-direction: column;
padding: 16px;
border: 1px solid black;
border-radius: 10px;
}
.input_section>h2 {
text-align: center;
color: cornflowerblue;
}
.input_section>form>.input {
margin: 8px 0;
}
.input_section>form>button {
background-color: cornflowerblue;
color: white;
border: 0;
border-radius: 5px;
display: block;
width: 100%;
padding: 8px;
cursor: pointer;
}
.input_section>form>button>span {
font-weight: bold;
}
.input_section>form>.input>input {
display: block;
width: 100%;
padding: 8px;
border-radius: 5px;
}
.input_section>form>.input>label {
color: cornflowerblue;
font-weight: bold;
}
.input_section>form>.input_inline {
margin: 12px 0;
display: flex;
align-items: center;
}
.input_section>form>.input_inline>label {
color: cornflowerblue;
font-weight: bold;
margin-right: 10px;
}
.search_section {
margin: 16px 0;
display: flex;
flex-direction: column;
align-items: center;
padding: 16px;
border: 1px solid black;
border-radius: 10px;
}
.search_section>h2 {
color: cornflowerblue;
}
.search_section>form {
padding: 16px;
width: 100%;
display: grid;
grid-template-columns: auto 1fr 0.5fr;
grid-gap: 10px;
}
.search_section>form>label {
display: flex;
align-items: center;
}
.search_section>form>input {
padding: 5px;
border-radius: 5px;
}
.search_section>form>button {
background-color: cornflowerblue;
color: white;
border: 0;
border-radius: 5px;
cursor: pointer;
}
.book_shelf {
margin: 16px 0 0 0;
border: 1px solid black;
padding: 16px;
border-radius: 10px;
}
.book_shelf>h2 {
color: cornflowerblue;
}
.book_shelf>.book_list {
padding: 16px;
}
.book_shelf>.book_list>.book_item {
height: auto;
padding: 8px 16px 16px 16px;
border: 1px solid black;
border-radius: 5px;
margin: 10px 0;
display: flex;
justify-content: space-between;
}
.book_item>.action {
width: auto;
height: 30px;
margin: auto 5px;
border-radius: 10%;
display: flex;
place-content: center;
flex-basis: 1;
gap: 5px
}
.book_shelf>.book_list>.book_item>h3,
p {
margin: 8px 0;
}
.book_shelf>.book_list>.book_item>.action>button {
border: 0;
padding: 5px;
margin: 0 5px 0 0;
border-radius: 5px;
cursor: pointer;
/* }
.green1, .green2, .red { */
display: flex;
align-items: center;
/* place-content: center; */
}
.book_shelf>.book_list>.book_item>.action>.green1,
.book_shelf>.book_list>.book_item>.action>.green2 {
background-color: darkgreen;
color: white;
}
.book_shelf>.book_list>.book_item>.action>.red {
background-color: darkred;
color: white;
}
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Bookshelf Apps</title>
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;400;600;700;800&display=swap" rel="stylesheet">
<link rel="stylesheet" href="style.css">
</head>
<body>
<header class="head_bar">
<h1 class="head_bar__title">Bookshelf Apps</h1>
</header>
<main>
<section class="input_section">
<h2>Input New Book</h2>
<form id="inputBook">
<div class="input">
<label for="inputBookTitle">Title</label>
<input id="inputBookTitle" type="text" required>
</div>
<div class="input">
<label for="inputBookAuthor">Author</label>
<input id="inputBookAuthor" type="text" required>
</div>
<div class="input">
<label for="inputBookYear">Year</label>
<input id="inputBookYear" type="number" required>
</div>
<div class="input_inline">
<label for="inputBookIsCompleted">Finished Reading</label>
<input id="inputBookIsCompleted" type="checkbox">
</div>
<button id="bookSubmit" type="submit">Input Your Book To Bookshelf <span>Unfinished Reading</span></button>
</form>
</section>
<section class="search_section">
<h2>Search Book</h2>
<form id="searchBook">
<label for="searchBookTitle">Title</label>
<input id="searchBookTitle" type="text">
<button id="searchSubmit" type="submit">Search</button>
</form>
</section>
<section class="book_shelf">
<h2>Unfinished Reading</h2>
<div id="unfinishedBookshelfList" class="book_list">
</div>
</section>
<section class="book_shelf">
<h2>Selesai dibaca</h2>
<div id="finishedBookshelfList" class="book_list">
</div>
</section>
</main>
<script src="js/data.js"></script>
<script src="js/dom.js"></script>
<script src="js/script.js"></script>
</body>
</html>
我想做搜索引擎,但是我查了一些书,怎么也查不到。它只有 return 零本书。
//data.js
// {
// id: string | number,
// title: string,
// author: string,
// year: number,
// isComplete: boolean,
// }
const STORAGE_KEY = "BOOKSHELF_APP";
let books = [];
let booksSearched = [];
function isStorageExist() /* boolean */ {
return false // SO does not like localStorage
if (typeof(Storage) === undefined) {
alert("Your browser doesn't support web storage.");
return false;
}
return true;
}
function saveData() {
const parsed /* string */ = JSON.stringify(books);
localStorage.setItem(STORAGE_KEY, parsed);
document.dispatchEvent(new Event("ondatasaved"));
}
function loadDataFromStorage() {
const serializedData /* string */ = localStorage.getItem(STORAGE_KEY);
let data = JSON.parse(serializedData);
if (data !== null)
books = data;
document.dispatchEvent(new Event("ondataloaded"));
}
function updateDataToStorage() {
if (isStorageExist())
saveData();
}
function composeBookObject(title, author, year, isCompleted) {
return {
id: +new Date(),
title,
author,
year,
isCompleted
};
}
function findBookById(bookId) {
for (book of books) {
if (book.id === bookId)
return book;
}
return null;
}
function searchBookByTitle(bookTitle) {
for (book of books) {
if (book.title === bookTitle) {
return book;
}
}
return null;
}
function findBookIndexById(bookId) {
let index = 0
for (book of books) {
if (book.id === bookId)
return index;
index++;
}
return -1;
}
//dom.js
const UNFINISHED_BOOK_LIST_ID = 'unfinishedBookshelfList';
const FINISHED_BOOK_LIST_ID = 'finishedBookshelfList';
const BOOK_ITEMID = "itemId";
function makeBookList(data, author, year, isCompleted) {
const container = document.createElement('article');
container.classList.add('book_item');
const textTitle = document.createElement('h3');
textTitle.innerText = `Title: ${data}`;
const textAuthor = document.createElement('p');
textAuthor.innerText = `Author: ${author}`;
const textYear = document.createElement('p');
textYear.innerText = `Year: ${year}`;
const textContainer = document.createElement('div');
textContainer.append(textTitle, textAuthor, textYear);
container.append(textContainer);
const buttonContainer = document.createElement('div');
buttonContainer.classList.add('action');
if (isCompleted) {
buttonContainer.append(
createUndoButton(),
createTrashButton()
);
} else {
buttonContainer.append(
createCheckButton(),
createTrashButton()
);
}
container.append(buttonContainer);
return container;
}
function createButton(buttonTypeClass /* string */ , eventListener /* Event */ ) {
const button = document.createElement("button");
button.classList.add(buttonTypeClass);
button.addEventListener("click", function(event) {
eventListener(event);
event.stopPropagation();
});
if (buttonTypeClass == 'green1') {
button.innerText = 'Belum Selesai Dibaca';
} else if (buttonTypeClass == 'green2') {
button.innerText = 'Selesai Dibaca';
} else if (buttonTypeClass == 'red') {
button.innerText = 'Hapus Buku';
}
return button;
}
function createUndoButton() {
return createButton("green1", function(event) {
// const button = document.querySelector('.green');
// button.innerText = 'Belum Selesai Dibaca';
undoBookFromCompleted(event.target.closest('.book_item'));
});
}
function createTrashButton() {
return createButton("red", function(event) {
removeBookFromCompleted(event.target.closest(".book_item"));
});
}
function createCheckButton() {
return createButton("green2", function(event) {
addBookToCompleted(event.target.closest('.book_item'));
});
}
function addBook() {
const unfinishedBookList = document.getElementById(UNFINISHED_BOOK_LIST_ID);
const finishedBookList = document.getElementById(FINISHED_BOOK_LIST_ID);
const textTitle = document.getElementById('inputBookTitle').value;
const textAuthor = document.getElementById('inputBookAuthor').value;
const textYear = document.getElementById('inputBookYear').value;
const isCompleted = document.getElementById('inputBookIsCompleted').checked;
const book = makeBookList(textTitle, textAuthor, textYear, isCompleted);
const bookObject = composeBookObject(textTitle, textAuthor, textYear, isCompleted);
book[BOOK_ITEMID] = bookObject.id;
books.push(bookObject);
if (isCompleted) {
finishedBookList.append(book);
} else {
unfinishedBookList.append(book);
}
updateDataToStorage();
}
function addBookToCompleted(bookElement /* HTMLELement */ ) {
const listCompleted = document.getElementById(FINISHED_BOOK_LIST_ID);
const bookTitle = bookElement.querySelector("h3").innerText;
const bookAuthor = bookElement.querySelector("p:nth-of-type(1)").innerText;
const bookYear = bookElement.querySelector("p:nth-of-type(2)").innerText;
const newBook = makeBookList(bookTitle, bookAuthor, bookYear, true);
const book = findBookById(bookElement[BOOK_ITEMID]);
book.isCompleted = true;
newBook[BOOK_ITEMID] = book.id;
listCompleted.append(newBook);
bookElement.remove();
updateDataToStorage();
}
function removeBookFromCompleted(bookElement /* HTMLELement */ ) {
const bookPosition = findBookIndexById(bookElement[BOOK_ITEMID]);
books.splice(bookPosition, 1);
bookElement.remove();
updateDataToStorage();
document.dispatchEvent(new Event("onbookremoved"));
}
function undoBookFromCompleted(bookElement /* HTMLELement */ ) {
const listUncompleted = document.getElementById(UNFINISHED_BOOK_LIST_ID);
const bookTitle = bookElement.querySelector("h3").innerText;
const bookAuthor = bookElement.querySelector("p:nth-of-type(1)").innerText;
const bookYear = bookElement.querySelector("p:nth-of-type(2)").innerText;
const newBook = makeBookList(bookTitle, bookAuthor, bookYear, false);
const book = findBookById(bookElement[BOOK_ITEMID]);
book.isCompleted = false;
newBook[BOOK_ITEMID] = book.id;
listUncompleted.append(newBook);
bookElement.remove();
updateDataToStorage();
}
function searchBooks(bookTitle) {
// const bookShelf = document.querySelectorAll('.book_shelf');
const unfinishedBookList = document.getElementById(UNFINISHED_BOOK_LIST_ID);
const finishedBookList = document.getElementById(FINISHED_BOOK_LIST_ID);
const bookSearchedObject = searchBookByTitle(bookTitle);
booksSearched.push(bookSearchedObject);
// unfinishedBookList.childElement.remove();
// finishedBookList.childElement.remove();
const bookSearched = makeBookList(bookSearchedObject.title, bookSearchedObject.author, bookSearchedObject.year);
if (bookSearched.isCompleted) {
finishedBookList.append(bookSearched);
} else {
unfinishedBookList.append(bookSearched);
}
updateDataToStorage();
}
function refreshDataFromBooks() {
const listUncompleted = document.getElementById(UNFINISHED_BOOK_LIST_ID);
let listCompleted = document.getElementById(FINISHED_BOOK_LIST_ID);
for (book of books) {
const newBook = makeBookList(book.title, book.author, book.year, book.isCompleted);
newBook[BOOK_ITEMID] = book.id;
if (book.isCompleted) {
listCompleted.append(newBook);
} else {
listUncompleted.append(newBook);
}
}
}
//script.js
document.addEventListener("DOMContentLoaded", function() {
const submitForm /* HTMLFormElement */ = document.getElementById("inputBook");
submitForm.addEventListener("submit", function(event) {
event.preventDefault();
addBook();
});
const searchButton = document.getElementById('searchSubmit');
searchButton.addEventListener('click', function() {
event.preventDefault();
console.log('ok');
const bookList = document.querySelectorAll('.book_list article');
bookList.forEach(list => list.remove());
const searchBookTitleValue = document.getElementById('searchBookTitle').value;
searchBooks(searchBookTitleValue);
});
if (isStorageExist()) {
loadDataFromStorage();
}
});
document.addEventListener("ondatasaved", () => {
console.log("Data has been saved.");
});
document.addEventListener("ondataloaded", () => {
refreshDataFromBooks();
alert('Welcome back!');
});
document.addEventListener("onbookremoved", () => {
alert('Your book has removed from the list.');
});
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
body,
input,
button {
font-family: 'Open Sans', sans-serif;
}
input,
button {
font-size: 16px;
}
.head_bar {
padding: 12px;
display: flex;
align-items: center;
justify-content: center;
background-color: cornflowerblue;
color: white;
}
main {
max-width: 800px;
width: 80%;
margin: 0 auto;
padding: 16px;
}
.input_section {
display: flex;
flex-direction: column;
padding: 16px;
border: 1px solid black;
border-radius: 10px;
}
.input_section>h2 {
text-align: center;
color: cornflowerblue;
}
.input_section>form>.input {
margin: 8px 0;
}
.input_section>form>button {
background-color: cornflowerblue;
color: white;
border: 0;
border-radius: 5px;
display: block;
width: 100%;
padding: 8px;
cursor: pointer;
}
.input_section>form>button>span {
font-weight: bold;
}
.input_section>form>.input>input {
display: block;
width: 100%;
padding: 8px;
border-radius: 5px;
}
.input_section>form>.input>label {
color: cornflowerblue;
font-weight: bold;
}
.input_section>form>.input_inline {
margin: 12px 0;
display: flex;
align-items: center;
}
.input_section>form>.input_inline>label {
color: cornflowerblue;
font-weight: bold;
margin-right: 10px;
}
.search_section {
margin: 16px 0;
display: flex;
flex-direction: column;
align-items: center;
padding: 16px;
border: 1px solid black;
border-radius: 10px;
}
.search_section>h2 {
color: cornflowerblue;
}
.search_section>form {
padding: 16px;
width: 100%;
display: grid;
grid-template-columns: auto 1fr 0.5fr;
grid-gap: 10px;
}
.search_section>form>label {
display: flex;
align-items: center;
}
.search_section>form>input {
padding: 5px;
border-radius: 5px;
}
.search_section>form>button {
background-color: cornflowerblue;
color: white;
border: 0;
border-radius: 5px;
cursor: pointer;
}
.book_shelf {
margin: 16px 0 0 0;
border: 1px solid black;
padding: 16px;
border-radius: 10px;
}
.book_shelf>h2 {
color: cornflowerblue;
}
.book_shelf>.book_list {
padding: 16px;
}
.book_shelf>.book_list>.book_item {
height: auto;
padding: 8px 16px 16px 16px;
border: 1px solid black;
border-radius: 5px;
margin: 10px 0;
display: flex;
justify-content: space-between;
}
.book_item>.action {
width: auto;
height: 30px;
margin: auto 5px;
border-radius: 10%;
display: flex;
place-content: center;
flex-basis: 1;
gap: 5px
}
.book_shelf>.book_list>.book_item>h3,
p {
margin: 8px 0;
}
.book_shelf>.book_list>.book_item>.action>button {
border: 0;
padding: 5px;
margin: 0 5px 0 0;
border-radius: 5px;
cursor: pointer;
/* }
.green1, .green2, .red { */
display: flex;
align-items: center;
/* place-content: center; */
}
.book_shelf>.book_list>.book_item>.action>.green1,
.book_shelf>.book_list>.book_item>.action>.green2 {
background-color: darkgreen;
color: white;
}
.book_shelf>.book_list>.book_item>.action>.red {
background-color: darkred;
color: white;
}
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Bookshelf Apps</title>
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;400;600;700;800&display=swap" rel="stylesheet">
<link rel="stylesheet" href="style.css">
</head>
<body>
<header class="head_bar">
<h1 class="head_bar__title">Bookshelf Apps</h1>
</header>
<main>
<section class="input_section">
<h2>Input New Book</h2>
<form id="inputBook">
<div class="input">
<label for="inputBookTitle">Title</label>
<input id="inputBookTitle" type="text" required>
</div>
<div class="input">
<label for="inputBookAuthor">Author</label>
<input id="inputBookAuthor" type="text" required>
</div>
<div class="input">
<label for="inputBookYear">Year</label>
<input id="inputBookYear" type="number" required>
</div>
<div class="input_inline">
<label for="inputBookIsCompleted">Finished Reading</label>
<input id="inputBookIsCompleted" type="checkbox">
</div>
<button id="bookSubmit" type="submit">Input Your Book To Bookshelf <span>Unfinished Reading</span></button>
</form>
</section>
<section class="search_section">
<h2>Search Book</h2>
<form id="searchBook">
<label for="searchBookTitle">Title</label>
<input id="searchBookTitle" type="text">
<button id="searchSubmit" type="submit">Search</button>
</form>
</section>
<section class="book_shelf">
<h2>Unfinished Reading</h2>
<div id="unfinishedBookshelfList" class="book_list">
</div>
</section>
<section class="book_shelf">
<h2>Selesai dibaca</h2>
<div id="finishedBookshelfList" class="book_list">
</div>
</section>
</main>
<script src="js/data.js"></script>
<script src="js/dom.js"></script>
<script src="js/script.js"></script>
</body>
</html>
已编辑:我需要触发 onbookremoved
事件来显示警报。但是在我点击从已完成的按钮中删除图书后,警报没有出现。
dom.js
function removeBookFromCompleted(bookElement /* HTMLELement */) {
const bookPosition = findBookIndexById(bookElement[BOOK_ITEMID]);
books.splice(bookPosition, 1);
bookElement.remove();
updateDataToStorage();
document.dispatchEvent(new Event("onbookremoved"));
}
script.js
document.addEventListener("onbookremoved", () => {
alert('Your book has removed from the list.');
});
您的 booklist.remove 擦除了列表而不是文章
const bookList = document.querySelectorAll('.book_list article');
我也加了
if (book.title.toLowerCase() === bookTitle.toLowerCase()) {
你还有其他几个问题
if (book.isCompleted) { // should be bookSearched.isCompleted
finishedBookList.append(bookSearched);
} else {
unfinishedBookList.append(bookSearched);
}
//data.js
// {
// id: string | number,
// title: string,
// author: string,
// year: number,
// isComplete: boolean,
// }
const STORAGE_KEY = "BOOKSHELF_APP";
let books = [];
let booksSearched = [];
function isStorageExist() /* boolean */ {
return false // SO does not like localStorage
if (typeof(Storage) === undefined) {
alert("Your browser doesn't support web storage.");
return false;
}
return true;
}
function saveData() {
const parsed /* string */ = JSON.stringify(books);
localStorage.setItem(STORAGE_KEY, parsed);
document.dispatchEvent(new Event("ondatasaved"));
}
function loadDataFromStorage() {
const serializedData /* string */ = localStorage.getItem(STORAGE_KEY);
let data = JSON.parse(serializedData);
if (data !== null)
books = data;
document.dispatchEvent(new Event("ondataloaded"));
}
function updateDataToStorage() {
if (isStorageExist())
saveData();
}
function composeBookObject(title, author, year, isCompleted) {
return {
id: +new Date(),
title,
author,
year,
isCompleted
};
}
function findBookById(bookId) {
for (book of books) {
if (book.id === bookId)
return book;
}
return null;
}
function searchBookByTitle(bookTitle) {
console.log(bookTitle, books)
for (book of books) {
if (book.title.toLowerCase() === bookTitle.toLowerCase()) {
return book;
}
}
return null;
}
function findBookIndexById(bookId) {
let index = 0
for (book of books) {
if (book.id === bookId)
return index;
index++;
}
return -1;
}
//dom.js
const UNFINISHED_BOOK_LIST_ID = 'unfinishedBookshelfList';
const FINISHED_BOOK_LIST_ID = 'finishedBookshelfList';
const BOOK_ITEMID = "itemId";
function makeBookList(data, author, year, isCompleted) {
const container = document.createElement('article');
container.classList.add('book_item');
const textTitle = document.createElement('h3');
textTitle.innerText = `Title: ${data}`;
const textAuthor = document.createElement('p');
textAuthor.innerText = `Author: ${author}`;
const textYear = document.createElement('p');
textYear.innerText = `Year: ${year}`;
const textContainer = document.createElement('div');
textContainer.append(textTitle, textAuthor, textYear);
container.append(textContainer);
const buttonContainer = document.createElement('div');
buttonContainer.classList.add('action');
if (isCompleted) {
buttonContainer.append(
createUndoButton(),
createTrashButton()
);
} else {
buttonContainer.append(
createCheckButton(),
createTrashButton()
);
}
container.append(buttonContainer);
return container;
}
function createButton(buttonTypeClass /* string */ , eventListener /* Event */ ) {
const button = document.createElement("button");
button.classList.add(buttonTypeClass);
button.addEventListener("click", function(event) {
eventListener(event);
event.stopPropagation();
});
if (buttonTypeClass == 'green1') {
button.innerText = 'Belum Selesai Dibaca';
} else if (buttonTypeClass == 'green2') {
button.innerText = 'Selesai Dibaca';
} else if (buttonTypeClass == 'red') {
button.innerText = 'Hapus Buku';
}
return button;
}
function createUndoButton() {
return createButton("green1", function(event) {
// const button = document.querySelector('.green');
// button.innerText = 'Belum Selesai Dibaca';
undoBookFromCompleted(event.target.closest('.book_item'));
});
}
function createTrashButton() {
return createButton("red", function(event) {
removeBookFromCompleted(event.target.closest(".book_item"));
});
}
function createCheckButton() {
return createButton("green2", function(event) {
addBookToCompleted(event.target.closest('.book_item'));
});
}
function addBook() {
const unfinishedBookList = document.getElementById(UNFINISHED_BOOK_LIST_ID);
const finishedBookList = document.getElementById(FINISHED_BOOK_LIST_ID);
const textTitle = document.getElementById('inputBookTitle').value;
const textAuthor = document.getElementById('inputBookAuthor').value;
const textYear = document.getElementById('inputBookYear').value;
const isCompleted = document.getElementById('inputBookIsCompleted').checked;
const book = makeBookList(textTitle, textAuthor, textYear, isCompleted);
const bookObject = composeBookObject(textTitle, textAuthor, textYear, isCompleted);
book[BOOK_ITEMID] = bookObject.id;
books.push(bookObject);
if (isCompleted) {
finishedBookList.append(book);
} else {
unfinishedBookList.append(book);
}
updateDataToStorage();
}
function addBookToCompleted(bookElement /* HTMLELement */ ) {
const listCompleted = document.getElementById(FINISHED_BOOK_LIST_ID);
const bookTitle = bookElement.querySelector("h3").innerText;
const bookAuthor = bookElement.querySelector("p:nth-of-type(1)").innerText;
const bookYear = bookElement.querySelector("p:nth-of-type(2)").innerText;
const newBook = makeBookList(bookTitle, bookAuthor, bookYear, true);
const book = findBookById(bookElement[BOOK_ITEMID]);
book.isCompleted = true;
newBook[BOOK_ITEMID] = book.id;
listCompleted.append(newBook);
bookElement.remove();
updateDataToStorage();
}
function removeBookFromCompleted(bookElement /* HTMLELement */ ) {
const bookPosition = findBookIndexById(bookElement[BOOK_ITEMID]);
books.splice(bookPosition, 1);
bookElement.remove();
updateDataToStorage();
}
function undoBookFromCompleted(bookElement /* HTMLELement */ ) {
const listUncompleted = document.getElementById(UNFINISHED_BOOK_LIST_ID);
const bookTitle = bookElement.querySelector("h3").innerText;
const bookAuthor = bookElement.querySelector("p:nth-of-type(1)").innerText;
const bookYear = bookElement.querySelector("p:nth-of-type(2)").innerText;
const newBook = makeBookList(bookTitle, bookAuthor, bookYear, false);
const book = findBookById(bookElement[BOOK_ITEMID]);
book.isCompleted = false;
newBook[BOOK_ITEMID] = book.id;
listUncompleted.append(newBook);
bookElement.remove();
updateDataToStorage();
}
function searchBooks(bookTitle) {
// const bookShelf = document.querySelectorAll('.book_shelf');
const unfinishedBookList = document.getElementById(UNFINISHED_BOOK_LIST_ID);
const finishedBookList = document.getElementById(FINISHED_BOOK_LIST_ID);
const bookSearchedObject = searchBookByTitle(bookTitle) || {
title: "na",
author: "na",
year: "na"
};
booksSearched.push(bookSearchedObject);
// unfinishedBookList.childElement.remove();
// finishedBookList.childElement.remove();
const bookSearched = makeBookList(bookSearchedObject.title, bookSearchedObject.author, bookSearchedObject.year);
// const bookElement = document.querySelectorAll('.book_item');
// if(bookShelf !== null) {
if (bookSearched.isCompleted) {
finishedBookList.append(bookSearched);
} else {
unfinishedBookList.append(bookSearched);
}
updateDataToStorage();
}
function refreshDataFromBooks() {
const listUncompleted = document.getElementById(UNFINISHED_BOOK_LIST_ID);
let listCompleted = document.getElementById(FINISHED_BOOK_LIST_ID);
for (book of books) {
const newBook = makeBookList(book.title, book.author, book.year, book.isCompleted);
newBook[BOOK_ITEMID] = book.id;
if (book.isCompleted) {
listCompleted.append(newBook);
} else {
listUncompleted.append(newBook);
}
}
}
//script.js
document.addEventListener("DOMContentLoaded", function() {
const submitForm /* HTMLFormElement */ = document.getElementById("inputBook");
submitForm.addEventListener("submit", function(event) {
event.preventDefault();
addBook();
});
const searchButton = document.getElementById('searchSubmit');
searchButton.addEventListener('click', function() {
event.preventDefault();
console.log('ok');
const bookList = document.querySelectorAll('.book_list article'); // changed
bookList.forEach(list => list.remove());
const searchBookTitleValue = document.getElementById('searchBookTitle').value;
searchBooks(searchBookTitleValue);
});
if (isStorageExist()) {
loadDataFromStorage();
}
});
document.addEventListener("ondatasaved", () => {
console.log("Data has been saved.");
});
document.addEventListener("ondataloaded", () => {
refreshDataFromBooks();
alert('Welcome back!');
});
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
body,
input,
button {
font-family: 'Open Sans', sans-serif;
}
input,
button {
font-size: 16px;
}
.head_bar {
padding: 12px;
display: flex;
align-items: center;
justify-content: center;
background-color: cornflowerblue;
color: white;
}
main {
max-width: 800px;
width: 80%;
margin: 0 auto;
padding: 16px;
}
.input_section {
display: flex;
flex-direction: column;
padding: 16px;
border: 1px solid black;
border-radius: 10px;
}
.input_section>h2 {
text-align: center;
color: cornflowerblue;
}
.input_section>form>.input {
margin: 8px 0;
}
.input_section>form>button {
background-color: cornflowerblue;
color: white;
border: 0;
border-radius: 5px;
display: block;
width: 100%;
padding: 8px;
cursor: pointer;
}
.input_section>form>button>span {
font-weight: bold;
}
.input_section>form>.input>input {
display: block;
width: 100%;
padding: 8px;
border-radius: 5px;
}
.input_section>form>.input>label {
color: cornflowerblue;
font-weight: bold;
}
.input_section>form>.input_inline {
margin: 12px 0;
display: flex;
align-items: center;
}
.input_section>form>.input_inline>label {
color: cornflowerblue;
font-weight: bold;
margin-right: 10px;
}
.search_section {
margin: 16px 0;
display: flex;
flex-direction: column;
align-items: center;
padding: 16px;
border: 1px solid black;
border-radius: 10px;
}
.search_section>h2 {
color: cornflowerblue;
}
.search_section>form {
padding: 16px;
width: 100%;
display: grid;
grid-template-columns: auto 1fr 0.5fr;
grid-gap: 10px;
}
.search_section>form>label {
display: flex;
align-items: center;
}
.search_section>form>input {
padding: 5px;
border-radius: 5px;
}
.search_section>form>button {
background-color: cornflowerblue;
color: white;
border: 0;
border-radius: 5px;
cursor: pointer;
}
.book_shelf {
margin: 16px 0 0 0;
border: 1px solid black;
padding: 16px;
border-radius: 10px;
}
.book_shelf>h2 {
color: cornflowerblue;
}
.book_shelf>.book_list {
padding: 16px;
}
.book_shelf>.book_list>.book_item {
height: auto;
padding: 8px 16px 16px 16px;
border: 1px solid black;
border-radius: 5px;
margin: 10px 0;
display: flex;
justify-content: space-between;
}
.book_item>.action {
width: auto;
height: 30px;
margin: auto 5px;
border-radius: 10%;
display: flex;
place-content: center;
flex-basis: 1;
gap: 5px
}
.book_shelf>.book_list>.book_item>h3,
p {
margin: 8px 0;
}
.book_shelf>.book_list>.book_item>.action>button {
border: 0;
padding: 5px;
margin: 0 5px 0 0;
border-radius: 5px;
cursor: pointer;
/* }
.green1, .green2, .red { */
display: flex;
align-items: center;
/* place-content: center; */
}
.book_shelf>.book_list>.book_item>.action>.green1,
.book_shelf>.book_list>.book_item>.action>.green2 {
background-color: darkgreen;
color: white;
}
.book_shelf>.book_list>.book_item>.action>.red {
background-color: darkred;
color: white;
}
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Bookshelf Apps</title>
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;400;600;700;800&display=swap" rel="stylesheet">
<link rel="stylesheet" href="style.css">
</head>
<body>
<header class="head_bar">
<h1 class="head_bar__title">Bookshelf Apps</h1>
</header>
<main>
<section class="input_section">
<h2>Input New Book</h2>
<form id="inputBook">
<div class="input">
<label for="inputBookTitle">Title</label>
<input id="inputBookTitle" type="text" required>
</div>
<div class="input">
<label for="inputBookAuthor">Author</label>
<input id="inputBookAuthor" type="text" required>
</div>
<div class="input">
<label for="inputBookYear">Year</label>
<input id="inputBookYear" type="number" required>
</div>
<div class="input_inline">
<label for="inputBookIsCompleted">Finished Reading</label>
<input id="inputBookIsCompleted" type="checkbox">
</div>
<button id="bookSubmit" type="submit">Input Your Book To Bookshelf <span>Unfinished Reading</span></button>
</form>
</section>
<section class="search_section">
<h2>Search Book</h2>
<form id="searchBook">
<label for="searchBookTitle">Title</label>
<input id="searchBookTitle" type="text">
<button id="searchSubmit" type="submit">Search</button>
</form>
</section>
<section class="book_shelf">
<h2>Unfinished Reading</h2>
<div id="unfinishedBookshelfList" class="book_list">
</div>
</section>
<section class="book_shelf">
<h2>Selesai dibaca</h2>
<div id="finishedBookshelfList" class="book_list">
</div>
</section>
</main>
<script src="js/data.js"></script>
<script src="js/dom.js"></script>
<script src="js/script.js"></script>
</body>
</html>