setTimeout 函数不起作用:javascript
setTimeout function not working : javascript
场景:刚刚创建了一个简单的图书列表应用程序,它可以接受一些输入并将其显示在 UI 上,并具有其他功能,例如使用 localStorage。
就像我添加了更多自定义警报一样(例如显示警报 - 添加一本书时,- 如果作者姓名包含数字等),整个警报都已经擅离职守了。 (以前定义的警报之前工作正常)
另外 none 个相似的问题对我有用
处理页面中所有警报的方法
static showAlert(msg, className) {
const alertBox = document.createElement('div');
alertBox.className = `alert alert-${className} mb-3 p-2`;
alertBox.appendChild(document.createTextNode(msg));
const container = document.querySelector('.container');
const form = document.querySelector('#book-form');
// check whether if an alertBox already exist in the UI
if(document.querySelector('.alert')) {
// remove alertBox after some time
setTimeout(() => {
document.querySelector('.alert').remove();
}, 3000);
} else {
container.insertBefore(alertBox, form);
}
}
这是我添加新自定义提醒的地方:
if(bookName === '' || authorName === '' || bookId === '') {
Dom.showAlert('All fields are required', 'danger');
} else if (!isNaN(bookName)) {
Dom.showAlert('Name of the book should not contain numbers', 'danger');
document.querySelector('#title').value = '';
} else if (!isNaN(authorName)) {
Dom.showAlert('Author Name should not contain numbers', 'danger');
document.querySelector('#author').value = '';
} else if (isNaN(bookId)) {
Dom.showAlert('Reference Id should only consist of numbers', 'danger');
document.querySelector('#bookId').value = '';
面临的问题:
快速说明:我已将 setTimeout
延迟设置为 3000
现有警报在 3 秒后未删除(之前工作正常)
如果 dom 中需要存在另一个警报,则应删除之前显示的警报并显示新警报;即使这发生在 3 秒内。
我已将代码添加为代码片段,因为我在设置 JSFiddle 时遇到了一些问题
// Book class
class Book {
constructor(title, author, id) {
this.bookName = title;
this.authorName = author;
this.bookId = id;
}
}
// Dom class : handle user interface / dom
class Dom {
static displayBooks() {
//dummy data to mimic data in localStorage
const savedBooks = [
{
bookName: 'Vikings',
authorName: 'Michael Hirst',
bookId: 9764363,
},
{
bookName: 'The Soldier',
authorName: 'David Gary',
bookId: 5764363,
},
]
//const books = Store.getBooks();
const books = savedBooks;
books.forEach((book) => Dom.addBookToList(book))
}
static addBookToList(bookInfo) {
const tbody = document.querySelector('#book-list')
const bookRow = document.createElement('tr');
bookRow.innerHTML =
`
<tr>
<td>${bookInfo.bookName}</td>
<td>${bookInfo.authorName}</td>
<td>${bookInfo.bookId}</td>
<td><a href="#" class="btn btn-danger btn-sm deleteBtn">Delete</a></td>
</tr>
`
tbody.appendChild(bookRow);
}
static deleteBook(target) {
if(target.classList.contains('deleteBtn')) {
target.parentElement.parentElement.remove()
// show alert if user deletes a book
Dom.showAlert('Book deleted successfully', 'warning');
}
}
static showAlert(msg, className) {
const alertBox = document.createElement('div');
alertBox.className = `alert alert-${className} mb-3 p-2`;
alertBox.appendChild(document.createTextNode(msg));
const container = document.querySelector('.container');
const form = document.querySelector('#book-form');
// check whether if an alertBox already exist in the UI
if(document.querySelector('.alert')) {
// remove alerBox after an interval
setTimeout(() => {
document.querySelector('.alert').remove();
}, 3000);
} else {
container.insertBefore(alertBox, form);
}
}
static clearFields() {
document.querySelector('#title').value = '';
document.querySelector('#author').value = '';
document.querySelector('#bookId').value = '';
}
}
// Store class - deals with localStorage
/*class Store {
static getBooks() {
let books;
if(localStorage.getItem('books') === null) {
// if there is no book in the localstorage, then we initialize an empty array (of objects);
books = [];
} else {
// since the data is in the format of string, we need to change it to a javascript object in order to to things with it.Therefore we use JSON.parse
books = JSON.parse(localStorage.getItem('books'));
}
return books;
}
static addBooks(book) {
const books = Store.getBooks();
books.push(book);
localStorage.setItem('books', JSON.stringify(books))
}
static removeBooks(bookId) {
const books = Store.getBooks();
books.forEach((book, index) => {
if(book.bookId === bookId) {
books.splice(index, 1);
}
});
localStorage.setItem('books', JSON.stringify(books));
}
}*/
// Events in Dom
document.addEventListener('DOMContentLoaded', Dom.displayBooks);
// Add new book to dom/ui
document.querySelector('#book-form').addEventListener('submit', event => {
event.preventDefault();
const bookName = document.querySelector('#title').value;
const authorName = document.querySelector('#author').value;
const bookId = document.querySelector('#bookId').value;
// input validation
if(bookName === '' || authorName === '' || bookId === '') {
Dom.showAlert('All fields are required', 'danger');
} else if (!isNaN(bookName)) {
Dom.showAlert('Name of the book should not contain numbers', 'danger');
document.querySelector('#title').value = '';
} else if (!isNaN(authorName)) {
Dom.showAlert('Author Name should not contain numbers', 'danger');
document.querySelector('#author').value = '';
} else if (isNaN(bookId)) {
Dom.showAlert('Reference Id should only consist of numbers', 'danger');
document.querySelector('#bookId').value = '';
} else {
// object instantiation of book
const book = new Book(bookName, authorName, bookId);
// Add submitted book to the list
Dom.addBookToList(book);
// Add Submitted bookk to the local Storage
//Store.addBooks(book);
// show alert after adding the book
Dom.showAlert('Book added successfully', 'success');
// Clear input fields after submitting
Dom.clearFields();
}
})
// Remove / Delete a book from the list
document.querySelector('#book-list')
.addEventListener('click', event => {
// Remove book from the Dom
Dom.deleteBook(event.target);
// Remove book from the local storage
//Store.removeBooks(event.target.parentElement.previousElementSibling.textContent);
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Book List app</title>
<!-- fontAwesome script -->
<script src="https://kit.fontawesome.com/39350fd9df.js"></script>
<!-- bootstrap css -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css" type="text/css">
</head>
<body>
<div class="container mt-4">
<h1 class="display-4 text-center mb-4"><i class="fas fa-book text-success"></i> <span class="text-success">BlueStock</span> <span class="text-muted">Book Shop</span></h1>
<form action="#" id="book-form">
<div class="form-group mb-2">
<label for="title">Book Title</label>
<input type="text" name="title" id="title" class="form-control">
</div>
<div class="form-group mb-2">
<label for="author">Author Name</label>
<input type="text" name="author" id="author" class="form-control">
</div>
<div class="form-group">
<label for="book-id">Reference Id</label>
<input type="text" name="title" id="bookId" class="form-control">
</div>
<input type="submit" value="Add Book" class="btn btn-primary w-100 mt-3" id="submit">
</form>
<table class="table table-striped mt-4">
<thead>
<tr>
<th>Book Title</th>
<th>Author Name</th>
<th>Reference Id</th>
<th class="text-warning"><small>Delete book</small></th>
</tr>
</thead>
<tbody id="book-list"></tbody>
</table>
</div>
<script src="app.js" type="text/javascript"></script>
</body>
</html>
我注意到你的问题showAlert
:
showAlert(msg, className) {
// ...
if (document.querySelector('.alert')) {
/*
#1. At the first time this function called, this will always be null. Since '.alert' is not in the DOM yet (it wil be added to the DOM at the following 'else' block.
Therefore, setTimeout here won't be called, since the code never enters here at the first time.
#2. At the second time and forth, this will be called.
However, it will not enter the `else` block which is to add the alert into the DOM
*/
setTimeout(() => {
document.querySelector('.alert').remove();
}, 3000);
} else {
container.insertBefore(alertBox, form);
}
}
如果我们将其分解为您预期的行为,代码可能应该是这样的;
static showAlert(msg, className) {
// If there's an existing alert, instantly remove it.
if (document.querySelector('.alert')) {
document.querySelector('.alert').remove();
}
// Create the alert
const alertBox = document.createElement('div');
alertBox.className = `alert alert-${className} mb-3 p-2`;
alertBox.appendChild(document.createTextNode(msg));
const container = document.querySelector('.container');
const form = document.querySelector('#book-form');
// Insert alert to the DOM.
container.insertBefore(alertBox, form);
// Remove the alert above after 3s
setTimeout(() => {
alertBox.remove();
}, 3e3);
}
示例最终代码如下;
// Book class
class Book {
constructor(title, author, id) {
this.bookName = title;
this.authorName = author;
this.bookId = id;
}
}
// Dom class : handle user interface / dom
class Dom {
static displayBooks() {
//dummy data to mimic data in localStorage
const savedBooks = [{
bookName: 'Vikings',
authorName: 'Michael Hirst',
bookId: 9764363,
},
{
bookName: 'The Soldier',
authorName: 'David Gary',
bookId: 5764363,
},
]
//const books = Store.getBooks();
const books = savedBooks;
books.forEach((book) => Dom.addBookToList(book))
}
static addBookToList(bookInfo) {
const tbody = document.querySelector('#book-list')
const bookRow = document.createElement('tr');
bookRow.innerHTML =
`
<tr>
<td>${bookInfo.bookName}</td>
<td>${bookInfo.authorName}</td>
<td>${bookInfo.bookId}</td>
<td><a href="#" class="btn btn-danger btn-sm deleteBtn">Delete</a></td>
</tr>
`
tbody.appendChild(bookRow);
}
static deleteBook(target) {
if (target.classList.contains('deleteBtn')) {
target.parentElement.parentElement.remove()
// show alert if user deletes a book
Dom.showAlert('Book deleted successfully', 'warning');
}
}
static showAlert(msg, className) {
// If there's an existing alert, instantly remove it.
if (document.querySelector('.alert')) {
document.querySelector('.alert').remove();
}
// Create the alert
const alertBox = document.createElement('div');
alertBox.className = `alert alert-${className} mb-3 p-2`;
alertBox.appendChild(document.createTextNode(msg));
const container = document.querySelector('.container');
const form = document.querySelector('#book-form');
// Insert alert to the DOM.
container.insertBefore(alertBox, form);
// Remove the alert above after 3s
setTimeout(() => {
alertBox.remove();
}, 3e3);
}
static clearFields() {
document.querySelector('#title').value = '';
document.querySelector('#author').value = '';
document.querySelector('#bookId').value = '';
}
}
// Store class - deals with localStorage
/*class Store {
static getBooks() {
let books;
if(localStorage.getItem('books') === null) {
// if there is no book in the localstorage, then we initialize an empty array (of objects);
books = [];
} else {
// since the data is in the format of string, we need to change it to a javascript object in order to to things with it.Therefore we use JSON.parse
books = JSON.parse(localStorage.getItem('books'));
}
return books;
}
static addBooks(book) {
const books = Store.getBooks();
books.push(book);
localStorage.setItem('books', JSON.stringify(books))
}
static removeBooks(bookId) {
const books = Store.getBooks();
books.forEach((book, index) => {
if(book.bookId === bookId) {
books.splice(index, 1);
}
});
localStorage.setItem('books', JSON.stringify(books));
}
}*/
// Events in Dom
document.addEventListener('DOMContentLoaded', Dom.displayBooks);
// Add new book to dom/ui
document.querySelector('#book-form').addEventListener('submit', event => {
event.preventDefault();
const bookName = document.querySelector('#title').value;
const authorName = document.querySelector('#author').value;
const bookId = document.querySelector('#bookId').value;
// input validation
if (bookName === '' || authorName === '' || bookId === '') {
Dom.showAlert('All fields are required', 'danger');
} else if (!isNaN(bookName)) {
Dom.showAlert('Name of the book should not contain numbers', 'danger');
document.querySelector('#title').value = '';
} else if (!isNaN(authorName)) {
Dom.showAlert('Author Name should not contain numbers', 'danger');
document.querySelector('#author').value = '';
} else if (isNaN(bookId)) {
Dom.showAlert('Reference Id should only consist of numbers', 'danger');
document.querySelector('#bookId').value = '';
} else {
// object instantiation of book
const book = new Book(bookName, authorName, bookId);
// Add submitted book to the list
Dom.addBookToList(book);
// Add Submitted bookk to the local Storage
//Store.addBooks(book);
// show alert after adding the book
Dom.showAlert('Book added successfully', 'success');
// Clear input fields after submitting
Dom.clearFields();
}
})
// Remove / Delete a book from the list
document.querySelector('#book-list')
.addEventListener('click', event => {
// Remove book from the Dom
Dom.deleteBook(event.target);
// Remove book from the local storage
//Store.removeBooks(event.target.parentElement.previousElementSibling.textContent);
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Book List app</title>
<!-- fontAwesome script -->
<script src="https://kit.fontawesome.com/39350fd9df.js"></script>
<!-- bootstrap css -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css" type="text/css">
</head>
<body>
<div class="container mt-4">
<h1 class="display-4 text-center mb-4"><i class="fas fa-book text-success"></i> <span class="text-success">BlueStock</span> <span class="text-muted">Book Shop</span></h1>
<form action="#" id="book-form">
<div class="form-group mb-2">
<label for="title">Book Title</label>
<input type="text" name="title" id="title" class="form-control">
</div>
<div class="form-group mb-2">
<label for="author">Author Name</label>
<input type="text" name="author" id="author" class="form-control">
</div>
<div class="form-group">
<label for="book-id">Reference Id</label>
<input type="text" name="title" id="bookId" class="form-control">
</div>
<input type="submit" value="Add Book" class="btn btn-primary w-100 mt-3" id="submit">
</form>
<table class="table table-striped mt-4">
<thead>
<tr>
<th>Book Title</th>
<th>Author Name</th>
<th>Reference Id</th>
<th class="text-warning"><small>Delete book</small></th>
</tr>
</thead>
<tbody id="book-list"></tbody>
</table>
</div>
<script src="app.js" type="text/javascript"></script>
</body>
</html>
场景:刚刚创建了一个简单的图书列表应用程序,它可以接受一些输入并将其显示在 UI 上,并具有其他功能,例如使用 localStorage。
就像我添加了更多自定义警报一样(例如显示警报 - 添加一本书时,- 如果作者姓名包含数字等),整个警报都已经擅离职守了。 (以前定义的警报之前工作正常)
另外 none 个相似的问题对我有用
处理页面中所有警报的方法
static showAlert(msg, className) {
const alertBox = document.createElement('div');
alertBox.className = `alert alert-${className} mb-3 p-2`;
alertBox.appendChild(document.createTextNode(msg));
const container = document.querySelector('.container');
const form = document.querySelector('#book-form');
// check whether if an alertBox already exist in the UI
if(document.querySelector('.alert')) {
// remove alertBox after some time
setTimeout(() => {
document.querySelector('.alert').remove();
}, 3000);
} else {
container.insertBefore(alertBox, form);
}
}
这是我添加新自定义提醒的地方:
if(bookName === '' || authorName === '' || bookId === '') {
Dom.showAlert('All fields are required', 'danger');
} else if (!isNaN(bookName)) {
Dom.showAlert('Name of the book should not contain numbers', 'danger');
document.querySelector('#title').value = '';
} else if (!isNaN(authorName)) {
Dom.showAlert('Author Name should not contain numbers', 'danger');
document.querySelector('#author').value = '';
} else if (isNaN(bookId)) {
Dom.showAlert('Reference Id should only consist of numbers', 'danger');
document.querySelector('#bookId').value = '';
面临的问题:
快速说明:我已将 setTimeout
延迟设置为 3000
现有警报在 3 秒后未删除(之前工作正常)
如果 dom 中需要存在另一个警报,则应删除之前显示的警报并显示新警报;即使这发生在 3 秒内。
我已将代码添加为代码片段,因为我在设置 JSFiddle 时遇到了一些问题
// Book class
class Book {
constructor(title, author, id) {
this.bookName = title;
this.authorName = author;
this.bookId = id;
}
}
// Dom class : handle user interface / dom
class Dom {
static displayBooks() {
//dummy data to mimic data in localStorage
const savedBooks = [
{
bookName: 'Vikings',
authorName: 'Michael Hirst',
bookId: 9764363,
},
{
bookName: 'The Soldier',
authorName: 'David Gary',
bookId: 5764363,
},
]
//const books = Store.getBooks();
const books = savedBooks;
books.forEach((book) => Dom.addBookToList(book))
}
static addBookToList(bookInfo) {
const tbody = document.querySelector('#book-list')
const bookRow = document.createElement('tr');
bookRow.innerHTML =
`
<tr>
<td>${bookInfo.bookName}</td>
<td>${bookInfo.authorName}</td>
<td>${bookInfo.bookId}</td>
<td><a href="#" class="btn btn-danger btn-sm deleteBtn">Delete</a></td>
</tr>
`
tbody.appendChild(bookRow);
}
static deleteBook(target) {
if(target.classList.contains('deleteBtn')) {
target.parentElement.parentElement.remove()
// show alert if user deletes a book
Dom.showAlert('Book deleted successfully', 'warning');
}
}
static showAlert(msg, className) {
const alertBox = document.createElement('div');
alertBox.className = `alert alert-${className} mb-3 p-2`;
alertBox.appendChild(document.createTextNode(msg));
const container = document.querySelector('.container');
const form = document.querySelector('#book-form');
// check whether if an alertBox already exist in the UI
if(document.querySelector('.alert')) {
// remove alerBox after an interval
setTimeout(() => {
document.querySelector('.alert').remove();
}, 3000);
} else {
container.insertBefore(alertBox, form);
}
}
static clearFields() {
document.querySelector('#title').value = '';
document.querySelector('#author').value = '';
document.querySelector('#bookId').value = '';
}
}
// Store class - deals with localStorage
/*class Store {
static getBooks() {
let books;
if(localStorage.getItem('books') === null) {
// if there is no book in the localstorage, then we initialize an empty array (of objects);
books = [];
} else {
// since the data is in the format of string, we need to change it to a javascript object in order to to things with it.Therefore we use JSON.parse
books = JSON.parse(localStorage.getItem('books'));
}
return books;
}
static addBooks(book) {
const books = Store.getBooks();
books.push(book);
localStorage.setItem('books', JSON.stringify(books))
}
static removeBooks(bookId) {
const books = Store.getBooks();
books.forEach((book, index) => {
if(book.bookId === bookId) {
books.splice(index, 1);
}
});
localStorage.setItem('books', JSON.stringify(books));
}
}*/
// Events in Dom
document.addEventListener('DOMContentLoaded', Dom.displayBooks);
// Add new book to dom/ui
document.querySelector('#book-form').addEventListener('submit', event => {
event.preventDefault();
const bookName = document.querySelector('#title').value;
const authorName = document.querySelector('#author').value;
const bookId = document.querySelector('#bookId').value;
// input validation
if(bookName === '' || authorName === '' || bookId === '') {
Dom.showAlert('All fields are required', 'danger');
} else if (!isNaN(bookName)) {
Dom.showAlert('Name of the book should not contain numbers', 'danger');
document.querySelector('#title').value = '';
} else if (!isNaN(authorName)) {
Dom.showAlert('Author Name should not contain numbers', 'danger');
document.querySelector('#author').value = '';
} else if (isNaN(bookId)) {
Dom.showAlert('Reference Id should only consist of numbers', 'danger');
document.querySelector('#bookId').value = '';
} else {
// object instantiation of book
const book = new Book(bookName, authorName, bookId);
// Add submitted book to the list
Dom.addBookToList(book);
// Add Submitted bookk to the local Storage
//Store.addBooks(book);
// show alert after adding the book
Dom.showAlert('Book added successfully', 'success');
// Clear input fields after submitting
Dom.clearFields();
}
})
// Remove / Delete a book from the list
document.querySelector('#book-list')
.addEventListener('click', event => {
// Remove book from the Dom
Dom.deleteBook(event.target);
// Remove book from the local storage
//Store.removeBooks(event.target.parentElement.previousElementSibling.textContent);
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Book List app</title>
<!-- fontAwesome script -->
<script src="https://kit.fontawesome.com/39350fd9df.js"></script>
<!-- bootstrap css -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css" type="text/css">
</head>
<body>
<div class="container mt-4">
<h1 class="display-4 text-center mb-4"><i class="fas fa-book text-success"></i> <span class="text-success">BlueStock</span> <span class="text-muted">Book Shop</span></h1>
<form action="#" id="book-form">
<div class="form-group mb-2">
<label for="title">Book Title</label>
<input type="text" name="title" id="title" class="form-control">
</div>
<div class="form-group mb-2">
<label for="author">Author Name</label>
<input type="text" name="author" id="author" class="form-control">
</div>
<div class="form-group">
<label for="book-id">Reference Id</label>
<input type="text" name="title" id="bookId" class="form-control">
</div>
<input type="submit" value="Add Book" class="btn btn-primary w-100 mt-3" id="submit">
</form>
<table class="table table-striped mt-4">
<thead>
<tr>
<th>Book Title</th>
<th>Author Name</th>
<th>Reference Id</th>
<th class="text-warning"><small>Delete book</small></th>
</tr>
</thead>
<tbody id="book-list"></tbody>
</table>
</div>
<script src="app.js" type="text/javascript"></script>
</body>
</html>
我注意到你的问题showAlert
:
showAlert(msg, className) {
// ...
if (document.querySelector('.alert')) {
/*
#1. At the first time this function called, this will always be null. Since '.alert' is not in the DOM yet (it wil be added to the DOM at the following 'else' block.
Therefore, setTimeout here won't be called, since the code never enters here at the first time.
#2. At the second time and forth, this will be called.
However, it will not enter the `else` block which is to add the alert into the DOM
*/
setTimeout(() => {
document.querySelector('.alert').remove();
}, 3000);
} else {
container.insertBefore(alertBox, form);
}
}
如果我们将其分解为您预期的行为,代码可能应该是这样的;
static showAlert(msg, className) {
// If there's an existing alert, instantly remove it.
if (document.querySelector('.alert')) {
document.querySelector('.alert').remove();
}
// Create the alert
const alertBox = document.createElement('div');
alertBox.className = `alert alert-${className} mb-3 p-2`;
alertBox.appendChild(document.createTextNode(msg));
const container = document.querySelector('.container');
const form = document.querySelector('#book-form');
// Insert alert to the DOM.
container.insertBefore(alertBox, form);
// Remove the alert above after 3s
setTimeout(() => {
alertBox.remove();
}, 3e3);
}
示例最终代码如下;
// Book class
class Book {
constructor(title, author, id) {
this.bookName = title;
this.authorName = author;
this.bookId = id;
}
}
// Dom class : handle user interface / dom
class Dom {
static displayBooks() {
//dummy data to mimic data in localStorage
const savedBooks = [{
bookName: 'Vikings',
authorName: 'Michael Hirst',
bookId: 9764363,
},
{
bookName: 'The Soldier',
authorName: 'David Gary',
bookId: 5764363,
},
]
//const books = Store.getBooks();
const books = savedBooks;
books.forEach((book) => Dom.addBookToList(book))
}
static addBookToList(bookInfo) {
const tbody = document.querySelector('#book-list')
const bookRow = document.createElement('tr');
bookRow.innerHTML =
`
<tr>
<td>${bookInfo.bookName}</td>
<td>${bookInfo.authorName}</td>
<td>${bookInfo.bookId}</td>
<td><a href="#" class="btn btn-danger btn-sm deleteBtn">Delete</a></td>
</tr>
`
tbody.appendChild(bookRow);
}
static deleteBook(target) {
if (target.classList.contains('deleteBtn')) {
target.parentElement.parentElement.remove()
// show alert if user deletes a book
Dom.showAlert('Book deleted successfully', 'warning');
}
}
static showAlert(msg, className) {
// If there's an existing alert, instantly remove it.
if (document.querySelector('.alert')) {
document.querySelector('.alert').remove();
}
// Create the alert
const alertBox = document.createElement('div');
alertBox.className = `alert alert-${className} mb-3 p-2`;
alertBox.appendChild(document.createTextNode(msg));
const container = document.querySelector('.container');
const form = document.querySelector('#book-form');
// Insert alert to the DOM.
container.insertBefore(alertBox, form);
// Remove the alert above after 3s
setTimeout(() => {
alertBox.remove();
}, 3e3);
}
static clearFields() {
document.querySelector('#title').value = '';
document.querySelector('#author').value = '';
document.querySelector('#bookId').value = '';
}
}
// Store class - deals with localStorage
/*class Store {
static getBooks() {
let books;
if(localStorage.getItem('books') === null) {
// if there is no book in the localstorage, then we initialize an empty array (of objects);
books = [];
} else {
// since the data is in the format of string, we need to change it to a javascript object in order to to things with it.Therefore we use JSON.parse
books = JSON.parse(localStorage.getItem('books'));
}
return books;
}
static addBooks(book) {
const books = Store.getBooks();
books.push(book);
localStorage.setItem('books', JSON.stringify(books))
}
static removeBooks(bookId) {
const books = Store.getBooks();
books.forEach((book, index) => {
if(book.bookId === bookId) {
books.splice(index, 1);
}
});
localStorage.setItem('books', JSON.stringify(books));
}
}*/
// Events in Dom
document.addEventListener('DOMContentLoaded', Dom.displayBooks);
// Add new book to dom/ui
document.querySelector('#book-form').addEventListener('submit', event => {
event.preventDefault();
const bookName = document.querySelector('#title').value;
const authorName = document.querySelector('#author').value;
const bookId = document.querySelector('#bookId').value;
// input validation
if (bookName === '' || authorName === '' || bookId === '') {
Dom.showAlert('All fields are required', 'danger');
} else if (!isNaN(bookName)) {
Dom.showAlert('Name of the book should not contain numbers', 'danger');
document.querySelector('#title').value = '';
} else if (!isNaN(authorName)) {
Dom.showAlert('Author Name should not contain numbers', 'danger');
document.querySelector('#author').value = '';
} else if (isNaN(bookId)) {
Dom.showAlert('Reference Id should only consist of numbers', 'danger');
document.querySelector('#bookId').value = '';
} else {
// object instantiation of book
const book = new Book(bookName, authorName, bookId);
// Add submitted book to the list
Dom.addBookToList(book);
// Add Submitted bookk to the local Storage
//Store.addBooks(book);
// show alert after adding the book
Dom.showAlert('Book added successfully', 'success');
// Clear input fields after submitting
Dom.clearFields();
}
})
// Remove / Delete a book from the list
document.querySelector('#book-list')
.addEventListener('click', event => {
// Remove book from the Dom
Dom.deleteBook(event.target);
// Remove book from the local storage
//Store.removeBooks(event.target.parentElement.previousElementSibling.textContent);
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Book List app</title>
<!-- fontAwesome script -->
<script src="https://kit.fontawesome.com/39350fd9df.js"></script>
<!-- bootstrap css -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css" type="text/css">
</head>
<body>
<div class="container mt-4">
<h1 class="display-4 text-center mb-4"><i class="fas fa-book text-success"></i> <span class="text-success">BlueStock</span> <span class="text-muted">Book Shop</span></h1>
<form action="#" id="book-form">
<div class="form-group mb-2">
<label for="title">Book Title</label>
<input type="text" name="title" id="title" class="form-control">
</div>
<div class="form-group mb-2">
<label for="author">Author Name</label>
<input type="text" name="author" id="author" class="form-control">
</div>
<div class="form-group">
<label for="book-id">Reference Id</label>
<input type="text" name="title" id="bookId" class="form-control">
</div>
<input type="submit" value="Add Book" class="btn btn-primary w-100 mt-3" id="submit">
</form>
<table class="table table-striped mt-4">
<thead>
<tr>
<th>Book Title</th>
<th>Author Name</th>
<th>Reference Id</th>
<th class="text-warning"><small>Delete book</small></th>
</tr>
</thead>
<tbody id="book-list"></tbody>
</table>
</div>
<script src="app.js" type="text/javascript"></script>
</body>
</html>