我从用户那里输入了 ISBN 号。一旦用户单击此处提交,就会发生以下情况:
1 - 此 ISBN 用于从 google 图书 API 检索图书,然后将检索到的图书发送到数据库(猫鼬地图集)。2 - 来自 mongoose atlas 的数据通过 get 路由发送到客户端。3 - 我获取数据并创建一个列表元素以将 url 添加到 LI 元素,然后在屏幕上显示所有内容。
我遇到的问题是,第一次单击屏幕上没有图像显示,只有 LI 元素,然后第二次单击我想要的第一个图像显示,但仍然有一个 LI 元素为空。
希望很清楚:)
这是我的代码:
HTML / CSS
<!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>Books directory</title>
<link rel="stylesheet" type="text/css" href="./style.css"/>
<script type="text/javascript" src="./client.js"></script>
</head>
<body>
<div id="main">
<section id="insert_book">
<header>
<ul>
<li><a href="">Home</li></a>
<li><a href="">About Us</li></a>
<li><a href="">Contact</li></a>
</ul>
</header>
<h1>Book directory</h1>
<h3>Add books and retrieve them easily :)</h3>
<form action="/book_directory_url" method="post">
<div id="label">
<label>Book name :</label></br>
<label>Subtitle :</label></br>
<label>Author :</label></br>
<label>Publishing house :</label></br>
<label>publishing date :</label></br>
<label>ISBN :</label></br>
<label>Collection :</label></br>
<label>Short description :</label></br>
</div>
<div id="input">
<input class="empty" id="book_name" type="text" name="book_name" placeholder="Name of the book" onfocus="this.placeholder=''" onblur="this.placeholder='Name of the book'"></br>
<input class="empty" id="subtitle" type="text" name="subtitle" placeholder="Subtitle of the book" onfocus="this.placeholder=''" onblur="this.placeholder='Subtitle of the book'"></br>
<input class="empty" id="author" type="text" name="author" placeholder="Author" onfocus="this.placeholder=''" onblur="this.placeholder='Author'"/></br>
<input class="empty" id="publishing_house" type="text" name="publishing_house" placeholder="Publishing house" onfocus="this.placeholder=''" onblur="this.placeholder='Publishing house'"></br>
<input class="empty" id="publishing_date" type="number" name="publishing_date" placeholder="Publishing year" onfocus="this.placeholder=''" onblur="this.placeholder='Publishing year'"></br>
<input class="empty" id="isbn" type="number" name="isbn" placeholder="ISBN" onfocus="this.placeholder=''" onblur="this.placeholder='ISBN'"/></br>
<input class="empty"id="collection" type="text" name="collection" placeholder="Collection" onfocus="this.placeholder=''" onblur="this.placeholder='Collection'"></br>
<textarea class="empty" id="description" cols="22" name="description" placeholder="Description" onfocus="this.placeholder=''" onblur="this.placeholder='Description'" style="resize: none;"></textarea>
</div>
</form>
<input id="submit" type="submit" value="submit">
</section>
<section id="display_book">
<p id="">No book recorded</p>
<div id="group_card">
<ul id="list_card">
</ul>
</div>
</section>
</div>
</body>
</html>
服务器.js
const http = require('http');
const app = require('./server/app');
const Books = require('./public/src/client/js/mongooseScheme');
const Images = require('./public/src/client/js/imageUrlScheme')
const fetch = require('node-fetch');
const dotenv = require('dotenv');
const { json } = require('express');
dotenv.config();
let dataObject;
const normalizePort = val =>{
const port = parseInt(val,10);
if(isNaN(port)){
return val;
}
if(port >= 0){
return port;
}
return false;
};
const port = normalizePort(process.env.PORT || 3000);
app.set('port', port);
const errorHandler = error => {
if (error.syscall !== 'listen') {
throw error;
}
const address = server.address();
const bind = typeof address === 'string' ? 'pipe ' + address : 'port: ' + port;
switch (error.code) {
case 'EACCES':
console.error(bind + ' requires elevated privileges.');
process.exit(1);
break;
case 'EADDRINUSE':
console.error(bind + ' is already in use.');
process.exit(1);
break;
default:
throw error;
}
};
const server = http.createServer(app);
server.on('error', errorHandler);
server.on('listening', () => {
const address = server.address();
const bind = typeof address === 'string' ? 'pipe ' + address : 'port ' + port;
console.log('Listening on ' + bind);
});
server.listen(port);
// Variables needed to access the API
const API_url = "https://www.googleapis.com/books/v1/volumes?q=isbn:";
const API_key = process.env.GOOGLE_BOOKS_APIKEY;
// Connection to the Google Books API to retrieve dataObject
app.post('/server', async(req,res)=>{
// receive input send by client side (used it to access pictures from google API and also )
dataObject = req.body;
const response_books_api = await fetch(`${API_url}${dataObject.book_entry.isbn}&key=${API_key}`);
try {
const json_books_api = await response_books_api.json();
console.log(json_books_api);
res.send(json_books_api);
console.log(json_books_api.items[0].volumeInfo.imageLinks.thumbnail);
// Save data from the userInput in Mongoose Atlas database
const books = new Books({
book_name: dataObject.book_entry.book_name,
subtitle: dataObject.book_entry.subtitle,
author: dataObject.book_entry.author,
publishing_date: dataObject.book_entry.publishing_date,
publishing_house: dataObject.book_entry.publishing_house,
isbn: dataObject.book_entry.isbn,
collection_data: dataObject.book_entry.collection,
description: dataObject.book_entry.description,
});
const images = new Images({
imageUrl: json_books_api.items[0].volumeInfo.imageLinks.thumbnail,
})
books.save().then(()=>{
console.log('data successfully posted!')
// res.status(201).json({
// message: 'data successfully posted!',
// });
}).catch((error)=>{
console.log(error);
// res.status(400).json({
// error: error,
// })
});
images.save().then(()=>{
console.log('data successfully posted!')
// res.status(201).json({
// message: 'data successfully posted!',
// });
}).catch((error)=>{
console.log(error);
// res.status(400).json({
// error: error,
// })
});
} catch (err) {
console.error(err);
}
});
// send the book information from database to get it on the client side
app.get('/server/books',(req,res)=>{
Books.find().then(
(books) =>{
res.status(200).json(books);
}
).catch(
(error) =>{
console.log(error);
res.statut(400).json({
error: error
});
}
);
});
// send the imageURL from database to get it on the client side
app.get('/server/images',(req,res)=>{
Images.find().then(
(images) =>{
res.status(200).json(images);
}
).catch(
(error) =>{
console.log(error);
res.statut(400).json({
error: error
});
}
);
})
客户端.js
window.onload = function(){
// to start from the second list and avoid interacting with the menu list
let increment_list = 3;
// let increment_image = 0;
document.getElementById('submit').onclick = function(){
document.getElementById('display_book').querySelector('p').style.display = 'none';
// Get the input value to pt it on a object
let book_name = document.getElementById('book_name').value;
let subtitle = document.getElementById('subtitle').value;
let author = document.getElementById('author').value;
let publishing_house = document.getElementById('publishing_house').value;
let publishing_date = document.getElementById('publishing_date').value;
let isbn = document.getElementById('isbn').value;
let collection = document.getElementById('collection').value;
let description = document.getElementById('description').value;
let empty_class = document.getElementsByClassName('empty');
console.log(publishing_date);
// Empty the input on submit
for(let i=0;i<empty_class.length;i++){
empty_class[i].value ="";
}
// Put the data on a object to send it to the server side
const book_entry = {
book_name: book_name,
subtitle: subtitle,
author: author,
publishing_date: publishing_date,
publishing_house: publishing_house,
isbn:isbn,
collection: collection,
description: description,
}
// Send the data to the server to put it on a database
fetch("http://localhost:3000/server",{
method:"POST",
credentials: "same-origin",
headers:{
"Content-Type": "application/json",
},
body: JSON.stringify({
book_entry
}),
}).then((res)=>res.json()).then((res)=>{
console.log(res);
// Create a list to display books
// Check wether or not there is a picture of the book, if yes put it on a const to use it as URL to display the image on the screen
if(res.items[0].volumeInfo.readingModes.image === true){
// async function receiveImages(){
// const data_image_mongoose = await fetch('/server/images');
// try{
// const convert_date_image_to_json = await data_image_mongoose.json();
// console.log(convert_date_image_to_json);
// displayImages(convert_date_image_to_json);
// } catch(error){
// console.log(error);
// }
// }
// receiveImages();
// function displayImages(dataImages){
// console.log(dataImages);
// const li = document.createElement('li');
// const queryUl = document.getElementsByTagName('ul')[1];
// queryUl.appendChild(li);
// // const image_book_url = res.items[0].volumeInfo.imageLinks.thumbnail;
// // const image_book_url = dataImages[increment_image].imageUrl;
// const imageElt = document.createElement('img');
// const getList = document.getElementsByTagName('li')[increment_list];
// // imageElt.setAttribute("src",image_book_url)
// getList.appendChild(imageElt);
// const delete_sign = document.createElement('p');
// delete_sign.innerHTML = "×";
// delete_sign.setAttribute('class','delete_style');
// getList.appendChild(delete_sign);
// increment_list++;
// increment_image++;
// } ;
}else{
alert('no image available, the book cannot be display!');
}
// delete onclick event
const class_delete_style = document.getElementsByClassName('delete_style');
console.log(class_delete_style);
// confirm action and proceed new action accordingly
for(let i=0;i<class_delete_style.length;i++){
class_delete_style[0].onclick = function(){
if(confirm('Are you sure ?')){
} else{
}
}
}
// for(let i=0;i<class_delete_style;i++){
// class_delete_style[i].onclick = function(){
// alert('sure ?');
// }
// }
})
// setTimeout(function(){
// window.location.reload(1);
// }, 500);
receiveImages();
//Get the images data fron the Mongoose Atlas database. Outside the onclick function to be called onload.
};
async function receiveBooks(){
const data_book_mongoose = await fetch('/server/books');
try{
const convert_data_book_to_json = await data_book_mongoose.json();
console.log(convert_data_book_to_json);
} catch(error){
console.log(error);
}
}
receiveBooks();
async function receiveImages(){
const data_image_mongoose = await fetch('/server/images');
try{
const convert_date_image_to_json = await data_image_mongoose.json();
console.log(convert_date_image_to_json);
for(var i=0; i<=convert_date_image_to_json.length;i++){
const li = document.createElement('li');
const queryUl = document.getElementsByTagName('ul')[1];
queryUl.appendChild(li);
// const image_book_url = res.items[0].volumeInfo.imageLinks.thumbnail;
// const image_book_url = dataImages[increment_image].imageUrl;
const imageElt = document.createElement('img');
const getList = document.getElementsByTagName('li')[increment_list];
// imageElt.setAttribute("src",image_book_url)
getList.appendChild(imageElt);
const delete_sign = document.createElement('p');
delete_sign.innerHTML = "×";
delete_sign.setAttribute('class','delete_style');
getList.appendChild(delete_sign);
increment_list++;
// increment_image++;
let getImg = document.getElementsByTagName('img');
console.log(getImg[0]);
console.log(getImg.length);
for(let i=0;i<getImg.length;i++){
console.log(convert_date_image_to_json);
getImg[i].setAttribute('src',convert_date_image_to_json[i].imageUrl);
}
}
} catch(error){
console.log(error);
}
}
};
应用程序.js
const express = require('express');
const cors = require('cors');
const path = require('path');
const mongoose = require('mongoose');
mongoose.connect('mongodb+srv://mln95400:z7SVLolZztfSKdgs@cluster0.7qf1b.mongodb.net/image?retryWrites=true&w=majority')
.then(()=>{
console.log('Successfully connected to the mongoDB Atlas!')
}).catch((error)=>{
console.log('impossible to connect to the mondoDB Atlas !')
console.error(error);
});
// mongoose.connect('mongodb+srv://mln95400:z7SVLolZztfSKdgs@cluster0.7qf1b.mongodb.net/image?retryWrites=true&w=majority')
// .then(()=>{
// console.log('Successfully connected to the mongoDB Atlas!')
// }).catch((error)=>{
// console.log('impossible to connect to the mondoDB Atlas !')
// console.error(error);
// });
const app = express();
app.use(cors());
app.use(express.urlencoded({extended:true}));
app.use(express.json());
app.use(express.static('public/src/client/views'));
app.use(express.static('public/src/client/js'));
app.use(express.static('public/src/client/styles'));
// app.use('/', express.static('book_directory_project-withoutWebpack/src/client/views'));
// app.get('/',(req,res)=>{
// res.sendFile('book_directory_project-withoutWebpack/src/client/views');
// })
module.exports = app;