When the infinite scroll gets near to the end, it loads back to the top of the page and refreshes.
How do I stop that so it loads new images with previous images, and stop it from loading back at the top and refresh?
I don't want the infinite scroll to be implemented in the favourites section, only the show contents section.
Appreciate any help, thanks.
const resultsNav = document.getElementById('resultsNav');
const favouritesNav = document.getElementById('favouritesNav');
const imagesContainer = document.querySelector('.images-container');
const saveConfirmed = document.querySelector('.save-confirmed');
const loader = document.querySelector('.loader');
// Unsplash API
const count = 10;
const apiKey = 'UNSPLASH_API_KEY';
const apiUrl = `https://api.unsplash.com/photos/random?client_id=${apiKey}&count=${count}`;
let resultsArray = [];
let favourites = {};
function showContent(page) {
window.scrollTo({ top: 0, behavior: 'instant'});
if (page === 'results') {
resultsNav.classList.remove('hidden');
favouritesNav.classList.add('hidden');
} else {
resultsNav.classList.add('hidden');
favouritesNav.classList.remove('hidden');
}
loader.classList.add('hidden');
}
function createDOMNodes(page) {
const currentArray = page === 'results' ? resultsArray : Object.values(favourites);
currentArray.forEach((result) => {
// Card Container
const card = document.createElement('div');
card.classList.add('card');
// link
const link = document.createElement('a');
link.href = result.links.html;
link.target = '_blank';
//Images
const image = document.createElement('img');
image.src = result.urls.regular;
image.alt = 'Image';
image.loading = 'lazy';
image.classList.add('card-img-top');
//Card Body
const cardBody = document.createElement('div');
cardBody.classList.add('card-body');
// Save Text
const saveText = document.createElement('p');
saveText.classList.add('clickable');
if (page === 'results') {
saveText.textContent = 'Add To Favourites';
saveText.setAttribute('onclick', `saveFavourite('${result.urls.regular}')`);
} else {
saveText.textContent = 'Remove Favourite';
saveText.setAttribute('onclick', `removeFavourite('${result.urls.regular}')`);
}
// Append
cardBody.append(saveText);
link.appendChild(image);
card.append(link, cardBody);
imagesContainer.appendChild(card);
});
}
function updateDOM(page) {
// Get Favourites from localStorage
if (localStorage.getItem('unsplashFavourites')) {
favourites = JSON.parse(localStorage.getItem('unsplashFavourites'));
}
imagesContainer.textContent = '';
createDOMNodes(page);
showContent(page);
}
// Get 10 Images from Unsplash API
async function getUnplashPictures() {
// Show loader
loader.classList.remove('hidden');
try {
const response = await fetch(apiUrl);
resultsArray = await response.json();
updateDOM('results');
} catch (error) {
// Catch Error Here
}
}
// Add result to Favourites
function saveFavourite(itemUrl) {
// Loop through Reuslts Array to select Favourite
resultsArray.forEach((item) => {
if (item.urls.regular.includes(itemUrl) && !favourites[itemUrl]) {
favourites[itemUrl] =item;
// Show Save Confirmation for 2 Seconds
saveConfirmed.hidden = false;
setTimeout(() => {
saveConfirmed.hidden = true;
}, 2000);
// Set Favourites in localStorage
localStorage.setItem('unsplashFavourites', JSON.stringify(favourites));
}
});
}
// Remove item from Favourites
function removeFavourite(itemUrl) {
if (favourites[itemUrl]) {
delete favourites[itemUrl];
// Set Favourites in localStorage
localStorage.setItem('unsplashFavourites', JSON.stringify(favourites));
updateDOM('favourites');
}
}
// Check to see if scrolling near bottom of page, Load More Photos
window.addEventListener('scroll', () => {
if (window.innerHeight + window.scrollY >= document.body.offsetHeight - 1000) {
getUnplashPictures();
}
});
// On Load
getUnplashPictures();
The problem is in two lines of your code. First, as noted in comments,
window.scrollTo({ top: 0, behavior: 'instant'});
Is what scrolls the page to the top and you should remove it. Another problem is in the fetch logic:
resultsArray = await response.json();
Deletes the content of the whole list and replace it with the new records! That means you don't add the new data to the already-fetched records when loading more data, but replace the current data with the new.
Possible solution:
const newResultsArray = await response.json();
resultsArray = resultsArray.concat(newResultsArray); // Combine new and already-fetched records
I changed those two lines in the jsfiddle and tried it with a mock data (the api gives errors). It worked for me.