Issue
so i'm currently working on a project which fetches product information from a JSON file and inputs it onto a HTML page via js. I've managed to get the fetch function working, however I would like to a "Load More" function/button so that my page originally displays 12 (4x3 grid) items and when user clicks on the button it displays the remaining 12 items. Would anyone be able to help me out or push me into the right direction? Apologies if it's an easy fix and I'm being difficult or seem like i'm wasting time but I haven't been coding for very long. Any help or advice would be much appreciated!
PLEASE NOTE: YOU WILL NEED TO OPEN THE HTML USING LIVE SERVER IN VISUAL STUDIO CODE TO BE ABLE TO PREVIEW IT.
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">
<link rel="stylesheet" href="styles.css"> <!-- Link to my stylesheet -->
<title>Product List Test Page By Me</title>
</head>
<body>
<h2>Product List Test Page By Me</h2>
<!-- I need an empty container to hold the products
The container will be populated from the javascript file. -->
<div class="products"></div>
<button class="btn">Load More</button>
<script src="script.js"></script> <!-- link to the javascript file -->
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<script>
$(".product").slice(0, 12).show()
$(".btn").on("click", function(){
$(".product:hidden").slice(0, 12).slideDown()
if ($(".product:hidden").length == 0) {
$(".btn").fadeOut('slow')
}
})
</script>
CSS:
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
body{
font-family: 'Lato', Helvetica, sans-serif;
min-height: 100vh;
color: #555;
}
h2{
text-align: left;
margin-left: 20px;
font-size: 30px;
color: black;
}
.products{
display: grid;
grid-gap: 16px;
padding: 16px;
}
@media (min-width: 768px) {
.products {
grid-gap: 16px;
padding: 16px;
grid-template-columns: repeat(2, 1fr);
}
}
@media (min-width: 960px) {
.products {
grid-gap: 16px;
padding: 16px;
grid-template-columns: repeat(3, 1fr);
}
}
@media (min-width: 1200px) {
.products {
grid-gap: 16px;
padding: 16px;
grid-template-columns: repeat(4, 1fr);
}
}
.product img{
width: 100%;
display: block;
}
.product .designer{
text-align: center;
font-weight: 600;
text-transform: uppercase;
}
.product .name{
text-align: center;
padding: 0 20px 0 20px;
font-size: 0.8rem;
line-height: 22px;
}
.product .price{
text-align: center;
font-size: 0.8rem;
font-family: 'Lato', Helvetica, sans-serif;
}
.btn {
padding: .7rem 2rem;
background: royalblue;
border: none;
color: #FFF;
margin: 20px auto;
display: block;
font-size: 1.3rem;
cursor: pointer;
outline: none;
transition: .3s;
}
Javascript:
http.open('get', 'products.json', true);
http.send();
http.onload = function(){
if(this.readyState == 4 && this.status == 200){
let products = JSON.parse(this.responseText);
let output = "";
for(let item of products){
output += `
<div class="product">
<img src="${item.image}" alt="${item.name}">
<p class="designer">${item.designer}</p>
<p class="name">${item.name}</p>
<p class="price">${item.price}</p>
</div>
`;
}
document.querySelector(".products").innerHTML = output;
}
}
JSON:
{
"image": "https://via.placeholder.com/300",
"designer": "Designer",
"name": "Shirt",
"price": "£1,790"
},
{
"image": "https://via.placeholder.com/300",
"designer": "Designer",
"name": "Shirt",
"price": "£890"
},
{
"image": "https://via.placeholder.com/300",
"designer": "DesignerDesigner",
"name": "Shirt",
"price": "£1,690"
},
{
"image": "https://via.placeholder.com/300",
"designer": "Designer",
"name": "Shirt",
"price": "£750"
},
{
"image": "https://via.placeholder.com/300",
"designer": "Designer",
"name": "Shirt",
"price": "£6,330"
},
{
"image": "https://via.placeholder.com/300",
"designer": "Designer",
"name": "Shirt",
"price": "£440"
},
{
"image": "https://via.placeholder.com/300",
"designer": "Designer",
"name": "Shirt",
"price": "£850"
},
{
"image": "https://via.placeholder.com/300",
"designer": "Designer",
"name": "Shirt",
"price": "£370"
},
{
"image": "https://via.placeholder.com/300",
"designer": "Designer",
"name": "Shirt",
"price": "£865"
},
{
"image": "https://via.placeholder.com/300",
"designer": "Designer",
"name": "Shirt",
"price": "£1,000"
},
{
"image": "https://via.placeholder.com/300",
"designer": "Designer",
"name": "ShirtShirt",
"price": "£1,025"
},
{
"image": "https://via.placeholder.com/300",
"designer": "Designer",
"name": "Shirt",
"price": "£300"
},
{
"image": "https://via.placeholder.com/300",
"designer": "Designer",
"name": "Shirt",
"price": "£850"
},
{
"image": "https://via.placeholder.com/300",
"designer": "Designer",
"name": "Shirt",
"price": "£660"
},
{
"image": "https://via.placeholder.com/300",
"designer": "Designer",
"name": "Shirt",
"price": "£4,160"
},
{
"image": "https://via.placeholder.com/300",
"designer": "Designer",
"name": "Shirt",
"price": "£190"
},
{
"image": "https://via.placeholder.com/300",
"designer": "Designer",
"name": "Shirt",
"price": "£9,130"
},
{
"image": "https://via.placeholder.com/300",
"designer": "Designer",
"name": "Shirt",
"price": "£1,330"
},
{
"image": "https://via.placeholder.com/300",
"designer": "Designer",
"name": "Shirt",
"price": "£395"
},
{
"image": "https://via.placeholder.com/300",
"designer": "Designer",
"name": "Shirt",
"price": "£315"
},
{
"image": "https://via.placeholder.com/300",
"designer": "Designer",
"name": "Shirt",
"price": "£710"
},
{
"image": "https://via.placeholder.com/300",
"designer": "Designer",
"name": "Shirt",
"price": "£890"
},
{
"image": "https://via.placeholder.com/300",
"designer": "Designer",
"name": "Shirt",
"price": "£800"
},
{
"image": "https://via.placeholder.com/300",
"designer": "Designer",
"name": "Shirt",
"price": "£190"
}
]
Solution
out of convienience i added everything to the script.js
// global products array that you populate from the .json
let products = [];
// current step that increments everytime you press the load more button
let loadMoreStep = 0;
// how many items you want to add with each load more button click
let itemsPerStep = 12;
const http = new XMLHttpRequest();
http.open('get', 'products.json', true);
http.send();
http.onload = function(){
if(this.readyState == 4 && this.status == 200){
let data = JSON.parse(this.responseText);
for(let item of data){
// insert data to products array
products.push(item);
}
// call the function to initially have the first X products shown
loadMoreProducts();
}
}
function loadMoreProducts(){
let output = "";
// define the start and end index,
// e.g. at the first call of the function we want the products 1 to 12
// at the second call the products 13-24 and so on.
let startIndex = loadMoreStep * itemsPerStep;
let endIndex = (loadMoreStep + 1) * itemsPerStep;
// get the products from X to Y from the products array
let productsToLoad = products.slice(startIndex, endIndex);
console.log("Products to load", productsToLoad);
for(let item of productsToLoad){
output += `
<div class="product step-${loadMoreStep}">
<img src="${item.image}" alt="${item.name}">
<p class="designer">${item.designer}</p>
<p class="name">${item.name}</p>
<p class="price">${item.price}</p>
</div>
`;
}
// append it to the div
document.querySelector(".products").innerHTML += output;
// increment the step so the startIndex and endIndex get incremented by 'itemsPerStep'
loadMoreStep++;
}
// call the function every time you click on the .btn
document.querySelector(".btn").addEventListener('click', function(e) {
loadMoreProducts();
// some additional debug info and hide the button if there are no more products to load
console.log("displayed products:", (loadMoreStep * itemsPerStep))
if((loadMoreStep * itemsPerStep) >= products.length){
console.log("No more products to load, hide button");
this.style.display = 'none';
}
})
Answered By - David Brödner
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.