单页应用程序 div 未按预期显示
Single Page Application div not displaying as expected
我的目标是了解为什么在加载页面时没有显示带有产品 ID 的 div。
我希望产品 div 默认显示为网格,因为这是它在样式表中的设置。实际上,产品 div 直到附加到搜索字段的提交事件被触发后才会显示。
我无法理解为什么 product 在 productUpdate() 函数底部的 javascript 中被引用,即使它实际上从未定义为 const 或 var。
if(!flag_error){
product.style.display = "grid";
hint.style.display = "none";
forwardBtn.style.display = "inline";
backBtn.style.display = "inline";
我已进行了大量尝试,以准确了解哪一段代码可以打开和关闭产品 div。代码在下面,我也上传到http://va.ogs17.brighton.domains/.
HTML
<!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>V&A online item search</title>
<link rel="stylesheet" type="text/css" href="index.css">
<script src="index.js"></script>
</head>
<body>
<div class="main-container">
<div class="welcome-container">
<h1>Search the V&A Online</h1>
<h2>Start searching now by entering in a keyword in the searchbar below</h2>
</div>
<div id="search-container">
<form>
<fieldset>
<legend><strong>Search for an item here:</strong></legend>
<p>The V&A Museum is the world's leading museum of of art, design and performance, housing a permanent collection of over 2.27 million objects. You can search for them here.</p>
<img class="info-icon" src="info-icon2.png">
<p class="search-hint"> Stuck for ideas? Try searching for an object like a throne or vase. You could try a person or a place. Is there certain techniques or materials you are loooking for? Any keyword will work, even dragons!</p>
<label for="search-bar"></label>
<input id="search-bar" type="search">
<input type="submit" value="Search" href="#product-top">
<div class="nav-btn-container">
<a href="" type="button" class="back-button">Previous Item</a>
<a href="" type="button" class="forward-button">Next Item</a>
<span id="hint">This is the last item in the list.</span>
</div>
</fieldset>
</form>
</div>
<div id="loading">
<img class="loading-img" src="Bean Eater-1s-200px.gif">
</div>
<div id="product">
<a id="product-top"></a>
<div class="title">
<h2 class="">No title found</h2>
</div>
<div class="photo-container"><img class="photo" src="image-not-found.png"></div>
<div class="information">
<p class="artist">Artist: Unknown</p>
<p class="object">Object: Unkown</p>
<p class="date_text">Date: Unkown</p>
<p class="place">Place: Unkown</p>
<p class="location">Location: Unknown</p>
<p class="object_number">Object Number: Unkown</p>
<p class="museum_number">Museum Number Token: Unkown</p>
</div>
</div>
<div id="success">
<p>Success!</p>
<!-- Link back to empty form -->
</div>
<div id="error">
<p>error...</p>
<!-- Link back to empty form -->
</div>
</div>
</body>
</html>
CSS
body {
font-family:'Roboto',sans-serif;
padding: 32px;
margin: 0;
background-image: url("vanda-front.jpg");
background-size: 100%;
background-repeat: no-repeat;
background-attachment: fixed;
background-position: center;
}
img {
width: 100%;
}
.welcome-container {
color:honeydew;
text-shadow: black;
margin-top: 2rem;
margin-left: 3rem;
margin-bottom: 18rem;
}
.welcome-container h1 {
font-size: 3.5rem;
}
fieldset {
padding: 20px;
width: 60%;
margin: auto;
background-color: black;
opacity: 0.9;
border-style: none;
}
fieldset label, p, legend {
color: blanchedalmond;
}
fieldset img{
max-width: 1rem;
}
/* Button style partly by Frederico Dossena fdossena.com/?p=html5cool/buttons/i.frag */
.nav-btn-container a, input[type=submit] {
padding:0.35em 1.2em;
border:0.1em solid #FFFFFF;
margin:0 0.3em 0.3em 0;
border-radius:0.12em;
box-sizing: border-box;
background-color: black;
text-decoration:none;
font-weight:300;
color:#FFFFFF;
text-align:center;
transition: all 0.2s;
cursor: pointer;
}
input[type=submit] {
font-size: 1.5rem;
}
input[type=search] {
/* padding:0.35em 1.2em; */
border:0.1em solid #FFFFFF;
margin:0 0.3em 0.3em 0;
border-radius:0.12em;
box-sizing: border-box;
text-decoration:none;
/* min-height: 2.5rem; */
font-size: 3rem;
}
.nav-btn-container a:hover, input[type=submit]:hover {
color:#000000;
background-color:#FFFFFF;
}
.nav-btn-container {
margin-top: 1.2rem;
}
.search-hint{
display: none;
}
#product {
display: grid;
grid-template-columns: repeat(9, 1fr);
grid-template-rows: 10rem 1fr;
gap: 0.2rem;
padding: 10px;
box-sizing: border-box;
/* in the internal divs use grid-column-start and grid-row-end: ;
basic vid here - https://www.youtube.com/watch?v=Y9rHsdCxU8Q */
}
.photo-container {
opacity: 1;
}
/* text-overflow code by Jokesterfr whosebug.com/questions/7711490/prevent-text-from-overflowing-a-padded-container-in-html */
.title {
background-color: black;
opacity: 0.9;
border-style: none;
color: blanchedalmond;
font-size: 3rem;
overflow: hidden;
border-left:1em solid transparent;
border-right:1em solid transparent;
text-overflow: ellipsis;
}
.information {
background-color: black;
opacity: 0.9;
border-style: none;
color: blanchedalmond;
}
.back-button, .forward-button {
display: none;
}
.forward-button{
float: right;
}
.title {
grid-column-start: 1;
grid-column-end: 10;
grid-row-start: 1;
grid-row-end: 1;
}
.photo-container {
grid-column-start: 1;
grid-column-end: 6;
grid-row-start: 2;
grid-row-end: 3;
}
.information{
grid-column-start:6;
grid-column-end: 10;
grid-row-start: 2;
grid-row-end: 3;
}
input {
display: block;
Margin: 5px;
width: 100%;
}
#hint {
color:red;
display: none;
}
#success, #error, #product {
text-align: center;
display: none;
}
.loading-img{
display: none;
}
/* Android A70 */
/* @media(min-width: 751px) and (max-width: 1080px) {
body{background-color: red;}
} */
/* iPhone 6 */
@media(max-width: 750px) {
/* body{
background-color: orangered;
background-image: none;
} */
.welcome-container {
margin-bottom: 12rem;
}
.title {
grid-column-start: 1;
grid-column-end: 10;
grid-row-start: 1;
grid-row-end: 1;
}
.photo-container {
grid-column-start: 1;
grid-column-end: 10;
grid-row-start: 2;
grid-row-end: 3;
}
.information{
grid-column-start:1;
grid-column-end: 10;
grid-row-start: 3;
grid-row-end: 4;
}
}
JavaScript
window.addEventListener('load', function() {
//global varaibles
var searchHint = document.querySelector('.search-hint');
//by defualt, the first item is always shown. Position is incremented using next and previous buttons to show new items.
var position = 0;
var maxCap = 45;
//code by Ry whosebug.com/questions/21147832/convert-camel-case-to-human-readable-string
function toCapitalizedWords(name) {
var words = name.match(/[A-Za-z][a-z]*/g) || [];
return words.map(capitalize).join(" ");
}
function capitalize(word) {
return word.charAt(0).toUpperCase() + word.substring(1);
}
function productUpdate(step) {
if(position + step >= maxCap - 1){
//show hint
var hint = document.querySelector("#hint");
hint.style.display = "inline";
}
else {
// var loading = document.querySelector('#loading');
position += step;
var flag_error = false;
// get all form fields
var search = document.querySelector("#search-bar").value.trim();
var hint = document.querySelector("#hint");
var backBtn = document.querySelector(".back-button");
var forwardBtn = document.querySelector(".forward-button");
var productTitle = document.querySelector(".title");
var productPhoto = document.querySelector(".photo");
var productInformation = document.querySelectorAll(".information");
var xhrSearch = new XMLHttpRequest();
xhrSearch.onreadystatechange = function() {
//readystate 4 means oporation is complete developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/readyState
//status 200 means OK
if(this.readyState == 4 && this.status == 200) {
console.log(search);
//TODO
//if there is response text, do this, if not, display hint saying product not found
const result = JSON.parse(xhrSearch.responseText);
productTitle.textContent = result.records[position].fields.title;
//js loops god post whosebug.com/questions/3010840/loop-through-an-array-in-javascript
for (let item of productInformation[0].children) {
console.log(item);
itemClass = item.className;
item.textContent = toCapitalizedWords(itemClass) + ": " + result.records[position].fields[itemClass];
}
var xhrFullRecord = new XMLHttpRequest();
xhrFullRecord.onreadystatechange = function() {
if(this.readyState == 4 && this.status == 200) {
const fullRecordResult = JSON.parse(xhrFullRecord.responseText);
productPhoto.src = "https://framemark.vam.ac.uk/collections/" + fullRecordResult[0].fields.image_set[0].fields.image_id + "/full/735,/0/default.jpg";
}
}
fullRecordUrl = "https://www.vam.ac.uk/api/json/museumobject/" + result.records[position].fields.object_number;
xhrFullRecord.open("GET", fullRecordUrl);
xhrFullRecord.send();
}
};
//what happens to URL if £$&^%$£ is put in search?
url = "https://www.vam.ac.uk/api/json/museumobject/search?q=" + search + "&limit=" + maxCap;
//do I want any other params here?
xhrSearch.open("GET", url);
xhrSearch.send();
if(!flag_error){
//setTimeout(loading.style.display = "none", 5000);
product.style.display = "grid";
hint.style.display = "none";
forwardBtn.style.display = "inline";
backBtn.style.display = "inline";
}
}
}
document.querySelector('#search-container').addEventListener("submit", function(evt){
// stop page reload default action
evt.preventDefault();
position = 0;
productUpdate(0);
})
document.querySelector('.info-icon').addEventListener("click", function(evt){
// stop page reload default action
// evt.preventDefault();
if(searchHint.style.display == "inline"){
searchHint.style.display = "none";
} else {
searchHint.style.display = "inline";
}
})
document.querySelector('.back-button').addEventListener("click", function(evt){
// stop page reload default action
evt.preventDefault();
productUpdate(-1);
})
document.querySelector('.forward-button').addEventListener("click", function(evt){
// stop page reload default action
evt.preventDefault();
productUpdate(1);
})
function displayLoading(){
var loadIcon = document.querySelector(".loadingImg");
product.style.display = "none";
loadIcon.style.display = "inline";
}
});
你有 onload 事件但是 onload 没有调用 productUpdate()
window.addEventListener('load', function() {
........
........
// append this line before closing
productUpdate(0);
})
我的目标是了解为什么在加载页面时没有显示带有产品 ID 的 div。
我希望产品 div 默认显示为网格,因为这是它在样式表中的设置。实际上,产品 div 直到附加到搜索字段的提交事件被触发后才会显示。
我无法理解为什么 product 在 productUpdate() 函数底部的 javascript 中被引用,即使它实际上从未定义为 const 或 var。
if(!flag_error){
product.style.display = "grid";
hint.style.display = "none";
forwardBtn.style.display = "inline";
backBtn.style.display = "inline";
我已进行了大量尝试,以准确了解哪一段代码可以打开和关闭产品 div。代码在下面,我也上传到http://va.ogs17.brighton.domains/.
HTML
<!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>V&A online item search</title>
<link rel="stylesheet" type="text/css" href="index.css">
<script src="index.js"></script>
</head>
<body>
<div class="main-container">
<div class="welcome-container">
<h1>Search the V&A Online</h1>
<h2>Start searching now by entering in a keyword in the searchbar below</h2>
</div>
<div id="search-container">
<form>
<fieldset>
<legend><strong>Search for an item here:</strong></legend>
<p>The V&A Museum is the world's leading museum of of art, design and performance, housing a permanent collection of over 2.27 million objects. You can search for them here.</p>
<img class="info-icon" src="info-icon2.png">
<p class="search-hint"> Stuck for ideas? Try searching for an object like a throne or vase. You could try a person or a place. Is there certain techniques or materials you are loooking for? Any keyword will work, even dragons!</p>
<label for="search-bar"></label>
<input id="search-bar" type="search">
<input type="submit" value="Search" href="#product-top">
<div class="nav-btn-container">
<a href="" type="button" class="back-button">Previous Item</a>
<a href="" type="button" class="forward-button">Next Item</a>
<span id="hint">This is the last item in the list.</span>
</div>
</fieldset>
</form>
</div>
<div id="loading">
<img class="loading-img" src="Bean Eater-1s-200px.gif">
</div>
<div id="product">
<a id="product-top"></a>
<div class="title">
<h2 class="">No title found</h2>
</div>
<div class="photo-container"><img class="photo" src="image-not-found.png"></div>
<div class="information">
<p class="artist">Artist: Unknown</p>
<p class="object">Object: Unkown</p>
<p class="date_text">Date: Unkown</p>
<p class="place">Place: Unkown</p>
<p class="location">Location: Unknown</p>
<p class="object_number">Object Number: Unkown</p>
<p class="museum_number">Museum Number Token: Unkown</p>
</div>
</div>
<div id="success">
<p>Success!</p>
<!-- Link back to empty form -->
</div>
<div id="error">
<p>error...</p>
<!-- Link back to empty form -->
</div>
</div>
</body>
</html>
CSS
body {
font-family:'Roboto',sans-serif;
padding: 32px;
margin: 0;
background-image: url("vanda-front.jpg");
background-size: 100%;
background-repeat: no-repeat;
background-attachment: fixed;
background-position: center;
}
img {
width: 100%;
}
.welcome-container {
color:honeydew;
text-shadow: black;
margin-top: 2rem;
margin-left: 3rem;
margin-bottom: 18rem;
}
.welcome-container h1 {
font-size: 3.5rem;
}
fieldset {
padding: 20px;
width: 60%;
margin: auto;
background-color: black;
opacity: 0.9;
border-style: none;
}
fieldset label, p, legend {
color: blanchedalmond;
}
fieldset img{
max-width: 1rem;
}
/* Button style partly by Frederico Dossena fdossena.com/?p=html5cool/buttons/i.frag */
.nav-btn-container a, input[type=submit] {
padding:0.35em 1.2em;
border:0.1em solid #FFFFFF;
margin:0 0.3em 0.3em 0;
border-radius:0.12em;
box-sizing: border-box;
background-color: black;
text-decoration:none;
font-weight:300;
color:#FFFFFF;
text-align:center;
transition: all 0.2s;
cursor: pointer;
}
input[type=submit] {
font-size: 1.5rem;
}
input[type=search] {
/* padding:0.35em 1.2em; */
border:0.1em solid #FFFFFF;
margin:0 0.3em 0.3em 0;
border-radius:0.12em;
box-sizing: border-box;
text-decoration:none;
/* min-height: 2.5rem; */
font-size: 3rem;
}
.nav-btn-container a:hover, input[type=submit]:hover {
color:#000000;
background-color:#FFFFFF;
}
.nav-btn-container {
margin-top: 1.2rem;
}
.search-hint{
display: none;
}
#product {
display: grid;
grid-template-columns: repeat(9, 1fr);
grid-template-rows: 10rem 1fr;
gap: 0.2rem;
padding: 10px;
box-sizing: border-box;
/* in the internal divs use grid-column-start and grid-row-end: ;
basic vid here - https://www.youtube.com/watch?v=Y9rHsdCxU8Q */
}
.photo-container {
opacity: 1;
}
/* text-overflow code by Jokesterfr whosebug.com/questions/7711490/prevent-text-from-overflowing-a-padded-container-in-html */
.title {
background-color: black;
opacity: 0.9;
border-style: none;
color: blanchedalmond;
font-size: 3rem;
overflow: hidden;
border-left:1em solid transparent;
border-right:1em solid transparent;
text-overflow: ellipsis;
}
.information {
background-color: black;
opacity: 0.9;
border-style: none;
color: blanchedalmond;
}
.back-button, .forward-button {
display: none;
}
.forward-button{
float: right;
}
.title {
grid-column-start: 1;
grid-column-end: 10;
grid-row-start: 1;
grid-row-end: 1;
}
.photo-container {
grid-column-start: 1;
grid-column-end: 6;
grid-row-start: 2;
grid-row-end: 3;
}
.information{
grid-column-start:6;
grid-column-end: 10;
grid-row-start: 2;
grid-row-end: 3;
}
input {
display: block;
Margin: 5px;
width: 100%;
}
#hint {
color:red;
display: none;
}
#success, #error, #product {
text-align: center;
display: none;
}
.loading-img{
display: none;
}
/* Android A70 */
/* @media(min-width: 751px) and (max-width: 1080px) {
body{background-color: red;}
} */
/* iPhone 6 */
@media(max-width: 750px) {
/* body{
background-color: orangered;
background-image: none;
} */
.welcome-container {
margin-bottom: 12rem;
}
.title {
grid-column-start: 1;
grid-column-end: 10;
grid-row-start: 1;
grid-row-end: 1;
}
.photo-container {
grid-column-start: 1;
grid-column-end: 10;
grid-row-start: 2;
grid-row-end: 3;
}
.information{
grid-column-start:1;
grid-column-end: 10;
grid-row-start: 3;
grid-row-end: 4;
}
}
JavaScript
window.addEventListener('load', function() {
//global varaibles
var searchHint = document.querySelector('.search-hint');
//by defualt, the first item is always shown. Position is incremented using next and previous buttons to show new items.
var position = 0;
var maxCap = 45;
//code by Ry whosebug.com/questions/21147832/convert-camel-case-to-human-readable-string
function toCapitalizedWords(name) {
var words = name.match(/[A-Za-z][a-z]*/g) || [];
return words.map(capitalize).join(" ");
}
function capitalize(word) {
return word.charAt(0).toUpperCase() + word.substring(1);
}
function productUpdate(step) {
if(position + step >= maxCap - 1){
//show hint
var hint = document.querySelector("#hint");
hint.style.display = "inline";
}
else {
// var loading = document.querySelector('#loading');
position += step;
var flag_error = false;
// get all form fields
var search = document.querySelector("#search-bar").value.trim();
var hint = document.querySelector("#hint");
var backBtn = document.querySelector(".back-button");
var forwardBtn = document.querySelector(".forward-button");
var productTitle = document.querySelector(".title");
var productPhoto = document.querySelector(".photo");
var productInformation = document.querySelectorAll(".information");
var xhrSearch = new XMLHttpRequest();
xhrSearch.onreadystatechange = function() {
//readystate 4 means oporation is complete developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/readyState
//status 200 means OK
if(this.readyState == 4 && this.status == 200) {
console.log(search);
//TODO
//if there is response text, do this, if not, display hint saying product not found
const result = JSON.parse(xhrSearch.responseText);
productTitle.textContent = result.records[position].fields.title;
//js loops god post whosebug.com/questions/3010840/loop-through-an-array-in-javascript
for (let item of productInformation[0].children) {
console.log(item);
itemClass = item.className;
item.textContent = toCapitalizedWords(itemClass) + ": " + result.records[position].fields[itemClass];
}
var xhrFullRecord = new XMLHttpRequest();
xhrFullRecord.onreadystatechange = function() {
if(this.readyState == 4 && this.status == 200) {
const fullRecordResult = JSON.parse(xhrFullRecord.responseText);
productPhoto.src = "https://framemark.vam.ac.uk/collections/" + fullRecordResult[0].fields.image_set[0].fields.image_id + "/full/735,/0/default.jpg";
}
}
fullRecordUrl = "https://www.vam.ac.uk/api/json/museumobject/" + result.records[position].fields.object_number;
xhrFullRecord.open("GET", fullRecordUrl);
xhrFullRecord.send();
}
};
//what happens to URL if £$&^%$£ is put in search?
url = "https://www.vam.ac.uk/api/json/museumobject/search?q=" + search + "&limit=" + maxCap;
//do I want any other params here?
xhrSearch.open("GET", url);
xhrSearch.send();
if(!flag_error){
//setTimeout(loading.style.display = "none", 5000);
product.style.display = "grid";
hint.style.display = "none";
forwardBtn.style.display = "inline";
backBtn.style.display = "inline";
}
}
}
document.querySelector('#search-container').addEventListener("submit", function(evt){
// stop page reload default action
evt.preventDefault();
position = 0;
productUpdate(0);
})
document.querySelector('.info-icon').addEventListener("click", function(evt){
// stop page reload default action
// evt.preventDefault();
if(searchHint.style.display == "inline"){
searchHint.style.display = "none";
} else {
searchHint.style.display = "inline";
}
})
document.querySelector('.back-button').addEventListener("click", function(evt){
// stop page reload default action
evt.preventDefault();
productUpdate(-1);
})
document.querySelector('.forward-button').addEventListener("click", function(evt){
// stop page reload default action
evt.preventDefault();
productUpdate(1);
})
function displayLoading(){
var loadIcon = document.querySelector(".loadingImg");
product.style.display = "none";
loadIcon.style.display = "inline";
}
});
你有 onload 事件但是 onload 没有调用 productUpdate()
window.addEventListener('load', function() {
........
........
// append this line before closing
productUpdate(0);
})