feat: initial commit

This commit is contained in:
ktyl 2024-07-11 20:13:17 +01:00
commit 6731fe212c
4 changed files with 181 additions and 0 deletions

2
README.md Normal file
View File

@ -0,0 +1,2 @@
infinite scrolling
https://webdesign.tutsplus.com/how-to-implement-infinite-scrolling-with-javascript--cms-37055t

27
index.html Normal file
View File

@ -0,0 +1,27 @@
<html>
<head>
<link rel="stylesheet" href="styles.css"/>
</head>
<body>
<!-- cards are added by JavaScript so it starts empty -->
<div id="card-container"></div>
<!-- loader displays an animation before adding the next batch of cards -->
<div id="loader">
<div class="skeleton-card"></div>
<div class="skeleton-card"></div>
<div class="skeleton-card"></div>
</div>
<!-- card actions shows the card count and card total (we probably do not need this) -->
<div id="card-actions">
<span>Showing
<span id="card-count"></span> of
<span id="card-total"></span> cards
</span>
</div>
<script src="main.js"></script>
</body>
</html>

90
main.js Normal file
View File

@ -0,0 +1,90 @@
// first, let's get all the elements we'll need from our DOM
const cardContainer = document.getElementById("card-container");
const cardCountElem = document.getElementById("card-count");
const cardTotalElem = document.getElementById("card-total");
const loader = document.getElementById("loader");
// we'll need a value for the max numaer of cards to be added to the page
const cardLimit = 99;
// then we'll define a variable for how many cards we want to increase the
// page by
const cardIncrease = 9;
// how many times can we increase the content until we reach the max limit?
const pageCount = Math.ceil(cardLimit / cardIncrease);
// and define a value to determine which page we're on
let currentPage = 1;
cardTotalElem.innerHTML = cardLimit;
function getRandomColor() {
const h = Math.floor(Math.random() * 360);
return `hsl(${h}deg, 90%, 85%)`;
}
function createCard(idx) {
const card = document.createElement("div");
card.className = "card";
card.innerHTML = idx;
card.style.backgroundColor = getRandomColor();
cardContainer.appendChild(card);
}
function addCards(pageIdx) {
currentPage = pageIdx;
const startRange = (pageIdx - 1) * cardIncrease;
const endRange = currentPage == pageCount
? cardLimit
: pageIdx * cardIncrease;
cardCountElem.innerHTML = endRange;
for (let i = startRange + 1; i <= endRange; i++) {
createCard(i);
}
}
function handleInfiniteScroll() {
throttle(() => {
const endOfPage = window.innerHeight + window.pageYOffset >= document.body.offsetHeight;
if (endOfPage) {
addCards(currentPage + 1);
}
if (currentPage === pageCount) {
removeInfiniteScroll();
}
}, 1000);
}
var throttleTimer;
function throttle(callback, time) {
if (throttleTimer) return;
throttleTimer = true;
setTimeout(() => {
callback();
throttleTimer = false;
}, time);
}
function removeInfiniteScroll() {
loader.remove();
window.removeEventListener("scroll", handleInfiniteScroll);
}
addCards(currentPage);
window.addEventListener("scroll", handleInfiniteScroll);
// TODO: define the limit of the content to be loaded on the page
// TODO: detect when the user has reached the end of the content container
// TODO: load more content once the end of the container has been reached
// TODO: if there's no more content to be loaded, stop the infinite scroll

62
styles.css Normal file
View File

@ -0,0 +1,62 @@
#card-container {
display: flex;
flex-wrap: wrap;
}
.card {
height: 55vh;
width: calc((100% / 3) - 16px);
margin: 8px;
border-radius: 3px;
transition: all 200ms ease-in-out;
display: flex;
align-items: center;
justify-content: center;
}
.card:hover {
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2);
}
.card-actions {
margin: 8px;
padding: 16px 0;
display: flex;
justify-content: space-between;
align-items: center;
}
#loader {
display: flex;
}
.skeleton-card {
height: 55vh;
width: calc((100% / 3) - 16px);
margin: 8px;
border-radius: 3px;
transition: all 200ms ease-in-out;
position: relative;
background-color: #eaeaea;
}
.skeleton-card::after {
content: "";
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
transform: translateX(-100%);
background-image: linear-gradient(90deg, rgba(255, 255, 255, 0) 0, rgba(255, 255, 255, 0.2) 20%, rgba(255, 255, 255, 0.5) 60%, rgba(255, 255, 255, 0));
animation: load is infinite;
}
@keyframes load {
100% {
transform: translateX(100%);
}
}
@media screen and (prefers-reduced-motion: reduce) {
}