javascriptarraysinfinite-scroll

Infinite scroll in Javascript with data from file


I want to do infinite scroll in plain Javascript. I saw several tutorials but all of them fetch some random data from some api. I understand the code from tutorials but I don't know how to get data in order, not random.

I want to do something similar like here: https://codepen.io/FlorinPop17/pen/RwwvKYJ but I want to use data from my local file. Let's assume it's data.js and has code like it:

data = [{}, {}] 

so it's array of objects and let's assume the content of objects is like here: https://jsonplaceholder.typicode.com/posts/

How would you change the code from this codepen to display posts one by one in order? I guess, the function getPost should have parameter "id" and every time this function is called the parameter should be plus 1? But how to do it? Or maybe I should iterate through data.js and on every iteration check if user scrolled to bottom?


Solution

  • You simply have to change the getPost() function to use your inline blog_data which contains all the available posts. The current offset is saved in a global variable post_offset which is increased by every getPost() call so the order will stay the same and no post is shown multiple times.

    // all the blog entries that are available
    const blog_data = [{
      title: "Blog Entry 1",
      body: "This is the example body text for entry 1."
    },{
      title: "This is number two",
      body: "Also blog entry number 2 has some content."
    },{
      title: "Blog entry three",
      body: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua."
    },{
      title: "Blog entry four",
      body: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua."
    },{
      title: "Blog entry five",
      body: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua."
    },{
      title: "Blog entry six",
      body: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua."
    }];
    
    const container = document.getElementById('container');
    const loading = document.querySelector('.loading');
    let post_offset = 0;
    
    getPost();
    getPost();
    getPost();
    
    window.addEventListener('scroll', () => {
      const { scrollTop, scrollHeight, clientHeight } = document.documentElement;
    
      if(clientHeight + scrollTop >= scrollHeight - 5) {
        // show the loading animation
        showLoading();
      }
    });
    
    function showLoading() {
      if(post_offset < blog_data.length){
        loading.classList.add('show');
    
        // load more data
        setTimeout(getPost, 1000)
      }
      else{
        // end has been reached, no more posts available
      }
    }
    
    async function getPost() {
      if(post_offset < blog_data.length){
        addDataToDOM(blog_data[post_offset]);
        post_offset++;
      }
    }
    
    function addDataToDOM(data) {
      const postElement = document.createElement('div');
      postElement.classList.add('blog-post');
      postElement.innerHTML = `
        <h2 class="title">${data.title}</h2>
        <p class="text">${data.body}</p>
      `;
      container.appendChild(postElement);
    
      loading.classList.remove('show');
    }
    @import url('https://fonts.googleapis.com/css?family=Open+Sans:300,600&display=swap');
    
    * {
      box-sizing: border-box;
    }
    
    body {
      background-color: #fafafa;
      font-family: 'Open Sans', sans-serif;
      padding-bottom: 100px;
    }
    
    .container {
      margin: 0 auto;
      max-width: 600px;
    }
    
    .blog-post {
      background-color: #fff;
      box-shadow: 0px 1px 2px rgba(50, 50, 50, .1), 0px 2px 4px rgba(60, 60, 60, 0.1);
      border-radius: 4px;
      padding: 40px;
      margin: 20px 0;
    }
    
    .title {  
      margin: 0;  
    }
    
    .text {
      color: #555;
      margin: 20px 0;
    }
    
    .loading {
      opacity: 0;
      display: flex;
      position: fixed;
      bottom: 50px;
      left: 50%;
      transform: translateX(-50%);
      transition: opacity .3s ease-in;
    }
    
    .loading.show {
      opacity: 1;
    }
    
    .ball {
      background-color: #777;
      border-radius: 50%;
      margin: 5px;
      height: 10px;
      width: 10px;
      animation: jump .5s ease-in infinite;
    }
    
    .ball:nth-of-type(2) {
      animation-delay: 0.1s;
    }
    
    .ball:nth-of-type(3) {
      animation-delay: 0.2s;
    }
    
    @keyframes jump {
      0%, 100% {
        transform: translateY(0);
      }
    
      50% {
        transform: translateY(-10px);
      }
    }
    <div class="container" id="container">
      <h1>Blog Posts</h1>
    </div>
    
    <div class="loading">
      <div class="ball"></div>
      <div class="ball"></div>
      <div class="ball"></div>
    </div>