From 6731fe212c16f579bf28fb1326048cc1c8b6cce1 Mon Sep 17 00:00:00 2001 From: ktyl Date: Thu, 11 Jul 2024 20:13:17 +0100 Subject: [PATCH] feat: initial commit --- README.md | 2 ++ index.html | 27 ++++++++++++++++ main.js | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ styles.css | 62 +++++++++++++++++++++++++++++++++++++ 4 files changed, 181 insertions(+) create mode 100644 README.md create mode 100644 index.html create mode 100644 main.js create mode 100644 styles.css diff --git a/README.md b/README.md new file mode 100644 index 0000000..85741ca --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +infinite scrolling +https://webdesign.tutsplus.com/how-to-implement-infinite-scrolling-with-javascript--cms-37055t diff --git a/index.html b/index.html new file mode 100644 index 0000000..36976d1 --- /dev/null +++ b/index.html @@ -0,0 +1,27 @@ + + + + + + + +
+ + +
+
+
+
+
+ + +
+ Showing + of + cards + +
+ + + + diff --git a/main.js b/main.js new file mode 100644 index 0000000..38878f8 --- /dev/null +++ b/main.js @@ -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 diff --git a/styles.css b/styles.css new file mode 100644 index 0000000..5acf3c8 --- /dev/null +++ b/styles.css @@ -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) { +}