gsb
gsb

Reputation: 107

Scrolling and executing an event when needed - lazy loading

Let's imagine I want to make a social media application. I make a div to hold all my posts. When I start the application, I only query as many requests as will fit on the viewport. I append them as divs themselves. When the user scrolls to the point that they can see n more posts, n more posts are queried and appended to the div.

Or another, an application that you can infinitely scroll and generates random numbers for each div, using similar logic as above.

How can I implement this? I have no idea where to start, but right now what I think I might be able to get away with adding a scroll event. Here's some psuedocode of how that might look, but I'm not sure if I can do something like this (or if it's valid logic, because it's late at night):

unsigned lastY
document.addEventListener('scroll', () => {
  // check if there is space to add more elements
  if ((lastY - postsDiv.sizeY) != 0) { // yes, there is space to add more elements
    // how many can we?
    unsigned toAdd = 
      // (I am very, very unsure if this is correct)
      floor(lastY - postsDiv.sizeY) * postsDiv.lengthInYOfEachElement;
  }
  lastY = window.scrollY
})

Is this even a good approach?

Upvotes: 2

Views: 5693

Answers (2)

cloned
cloned

Reputation: 6742

You can do this easily with the Intersection Observer (IO)

Basically you set up your structure like this:

let options = {
  rootMargin: '0px',
  threshold: 0.9
};
target = document.querySelector('#js-load-more');

observer = new IntersectionObserver(entries => {
  var entry = entries[0];
  if (entry.isIntersecting) {
    console.log('You reached the bottom of the list!');
    appendMorePosts();
  }
}, options);
observer.observe(target);

appendMorePosts = function() {
  const post = document.createElement('div');
  post.classList.add('post');
  post.innerHTML = 'blabla';
  document.querySelector('.post-container').insertBefore(post,document.querySelector('#js-load-more') );
}
.post {
  height: 400px;
  background: linear-gradient(to bottom, hotpink, cyan)
}
<div class="post-container">
<div class="post"> blabla </div> <!-- this is one "post" with images, text, .. -->
<div class="post"> blabla </div>
<div class="post"> blabla </div>
<div id="js-load-more"></div> <!-- just an empty div, to check if you should load more --> 
</div>

Upvotes: 5

TechySharnav
TechySharnav

Reputation: 5084

You can use element's scrollTop property to check for amount of height scrolled. When this amount gets past a certain percentage of element's visible scroll height, you can add your posts to the element.
In the example below, new numbers are added when user scrolls 90% (0.9) of the height.

let n = 50;
let i = 0;
let cont = document.querySelector(".container");

function generateNumbers(ini) {
  for (var i = ini; i <= n + ini; i++) {
    let span = document.createElement("span");
    span.innerText = i;
    cont.appendChild(span);
  }
}
generateNumbers(i);

cont.addEventListener("scroll", () => {
  if (cont.scrollTop >= (cont.scrollHeight - cont.clientHeight) * 0.9) {
    i = n + 1;
    n += 50;
    generateNumbers(i);
  }
});
.container {
  display: flex;
  flex-direction: column;
  height: 200px;
  overflow: scroll;
}
<div class="container">
</div>

Upvotes: 2

Related Questions