0

I am designing html pages which is more than 10,000 lines inside paragraph tag with specific id. As the number of lines is more, the page loading time is more than 3 minutes. So I want to lazy load this data from javascript array object which should load more data on scroll and also able to load directly to id tagged from different page.

As the project work offline I dont want to use php and MySql so I want to use javascript for loading data.

html code

<p id="a1">श्रीगुरुभ्यो नमः ॥</p>
<p id="a2">समस्तगुणसम्पूर्णं सर्वदोषविवजितम् ।</p>
<p id="a3">नारायणं नमस्कृत्य गीतातात्पर्यमुच्यते ॥१॥</p>
<p id="a4">शास्त्रेषु भारतं सारं तत्र नामसहस्रकम् । वैष्णवं कृष्णगीता च तज्ज्ञानान्मुच्यतेञ्जसा ॥ 
</p>
<p id="a5">न भारतसमं शास्त्रं कुत एवानयोः समम् । भारतं सर्ववेदाश्च तुलामारोपिताः पुरा ॥ 
</p>
<p id="a6">देवैर्ब्रह्मादिभिः सर्वैर्‍ऋषिभिश्च समन्वितैः । व्यासस्यैवाज्ञया तत्र त्वत्यरिच्यत भारतम् ॥ 
</p>
<p id="a7">महत्त्वाद्भारवत्त्वाच्च महाभारतमुच्यते । निरुक्तमस्य यो वेद सर्वपापैः प्रमुच्यते ॥</p>

javascript array code

var b = [{"title":"गीतातात्पर्यनिर्णयः","text":"श्रीगुरुभ्यो नमः ॥","url":"#a1"},
{"title":"गीतातात्पर्यनिर्णयः","text":"समस्तगुणसम्पूर्णं सर्वदोषविवजितम् ।","url":"#a2"},
{"title":"गीतातात्पर्यनिर्णयः","text":"नारायणं नमस्कृत्य गीतातात्पर्यमुच्यते ॥ 
१॥","url":"#a3"},
{"title":"गीतातात्पर्यनिर्णयः","text":"शास्त्रेषु भारतं सारं तत्र नामसहस्रकम् । वैष्णवं 
कृष्णगीता च तज्ज्ञानान्मुच्यतेञ्जसा ॥","url":"#a4"},
{"title":"गीतातात्पर्यनिर्णयः","text":"न भारतसमं शास्त्रं कुत एवानयोः समम् । भारतं 
सर्ववेदाश्च तुलामारोपिताः पुरा ॥","url":"#a5"},
{"title":"गीतातात्पर्यनिर्णयः","text":"देवैर्ब्रह्मादिभिः सर्वैर्‍ऋषिभिश्च समन्वितैः । व्यासस्यैवाज्ञया 
तत्र त्वत्यरिच्यत भारतम् ॥","url":"#a6"},
{"title":"गीतातात्पर्यनिर्णयः","text":"महत्त्वाद्भारवत्त्वाच्च महाभारतमुच्यते । निरुक्तमस्य यो 
वेद सर्वपापैः प्रमुच्यते ॥","url":"#a7"}]

I expect the javascript array objects to be loaded to the html paragraphs with id and load more on scroll. Also i want to load the page faster.

1
  • "and also able to load directly to id tagged from different page." what do you mean by that ? Can you edit that part of your question to explain it better Commented Feb 9, 2019 at 12:41

2 Answers 2

1

Check out this simple Infinite Scroll implementation: https://codepen.io/wernight/pen/YyvNoW

The idea is to load more data when the el.scrollTop (scroll position) reaches the end - el.scrollHeight. We intercept this using an eventListener for the scroll event

In your case you'll have to change

var item = document.createElement('li');

To

var item = document.createElement('p');
var data = dataArray[i];

item.id = data.url.replace('#', ''); // You'll want to remove the '#'
item.innerText = data.text;
listElm.appendChild(item);

Depending on how much data your appending at a time you may want to append them to a fragment (document.createDocumentFragment) then when we're out of the loop you can append the fragment to the your listElm

Virtual List Example Using hyperlist library:

  • Using a virtual list greatly improves performance
  • Added dynamic items height
  • Added scroll to initial position (using location hash)

This library handles the scrolling logic for us. It's a virtual list implementation which will display minimal elements in the list (around 15) and update/replace them while we scroll

You can install the library from npm or append the following script to your body:

   <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/hyperlist.min.js"></script>

Important since each item in the list will probably have different height we need a way to calculate it before the item is actually rendered in the container. That's why we have another element which is positioned outside of the screen and is used for calculation

Another important point is scrolling to the initial position. This library doesn't expose methods to scroll to a desired index. I have added logic to progressively scroll until the desired element is in view (Scroller class). This is done by first checking in the dataArray that we can find such element and then accessing a private property _itemPositions which is updated dynamically while the list is scrolled

var dataArray = createDataArray();

var section = document.getElementById('infinite-list');
var offScreen = document.getElementById('offscreen');
var container = document.createElement('div');
var scroller = document.createElement('div');

var list = HyperList.create(container, {

  scroller: scroller,
  // All items must be the exact same height currently. Although since there is
  // a generate method, in the future this should be configurable.
  itemHeight: 100,
  // Specify the total amount of items to render the virtual height.
  total: dataArray.length,

  // Wire up the data to the index. The index is then mapped to a Y position
  // in the container.
  generate(index) {
    var el = createArticle(index);
    
    // Set height dynamically 
    var height = calcHeight(el);
    
    
    return { element: el, height: height};
  },
  
});

function createArticle(index) {
 
  var data = dataArray[index];
  var item = document.createElement('article');
  var title = document.createElement('h3');
  var content = document.createElement('p');
   
  title.innerText = data.url;
  content.innerText = data.text;
  
  item.id = data.url.replace('#', '');
  item.appendChild(title);
  item.appendChild(content);
    
  return item;
}

function calcHeight(el) {
  
  // apend outside of screen to calculate height
  offScreen.appendChild(el);
                        // compensate for paddings or margins
  var height = offScreen.offsetHeight + 40;
  offScreen.removeChild(el);
  
  return height;
}

window.addEventListener('load', function() {
  var id = '#545'; // harcoded for snippet
    // use the below for actual functionality
    // var id = window.location.hash;
  scrollToId(id);
  
  
});

section.appendChild(container);

function scrollToId(id) {
  
  var index = dataArray.findIndex(function(item) {
    return item.url === id
  });
  
  if (index === -1) {
    throw new Error('Failed to find `id` in `dataArray`');
  }
  
  var scroller = new Scroller(list, container, index);
    scroller.scroll();
  
}

function Scroller(list, container, index) {
  
  this.list = list;
  this.container = container;
  this.index = index;
  
  this.scroll = function() {
    
    var nextPosition = this.list._itemPositions[index];
    if (nextPosition - this.container.scrollTop <= 1) {
      return;
    }
    
    this.container.scrollTop = nextPosition;
    
    window.requestAnimationFrame(this.scroll);
    
  }
  
  this.scroll = this.scroll.bind(this);
  
}

function createDataArray() {
 
  var sampleText = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam facilisis, lorem ut placerat fermentum, nibh justo euismod ex, eu varius urna massa a est. Interdum et malesuada fames ac ante ipsum primis in faucibus. Sed ornare dapibus lorem ac faucibus. Vestibulum arcu lorem, lacinia vestibulum mi quis, finibus auctor diam. Aenean ut tristique tellus. Etiam consectetur ante ex, a congue diam mollis a. Praesent vitae orci sit amet odio porttitor vehicula elementum et mauris. Praesent pellentesque blandit eros, a facilisis sapien tincidunt euismod. \n\nSed bibendum tellus vel nisl cursus lacinia. Pellentesque ornare purus nec massa pulvinar, eu vestibulum turpis auctor. Nullam in nibh quam. Nunc dapibus vitae metus at malesuada. Ut et turpis ornare metus malesuada fermentum. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam dignissim, elit quis facilisis blandit, turpis dolor pulvinar felis, quis aliquam mauris nulla in quam.';
  
  return (new Array(1000)).fill(1).map(function (_, index) {
  
  return { text: sampleText, url: '#' + index };
  
});
  
}
#infinite-list {
  height: 180px;
  width: 100%;
  border: 1px solid black;
}

#offscreen {
  position: fixed !important;
  left: -9999px !important;
  width: 100%;
}

/* Optional eye candy below: */
article {
  text-transform: capitalize;
  padding: 10px;
  border-bottom: 1px solid yellowgreen;
}

article:hover {
  background: #ccc;
}
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/hyperlist.min.js"></script>

<section id='infinite-list'>
</section>

<section id='offscreen'></section>

codepen link: https://codepen.io/kidroca/pen/NoYpOy

Sign up to request clarification or add additional context in comments.

5 Comments

thank you for helping me out, that worked perfectly but If I click a button from other page linked to an id of paragraph which has not scrolled yet is not going to that line. If it is scrolled already then that line is opening. Can you help me out with that?
Ok I think I understand what you need: When the page is opened from another window/tab from a link with a anchor tag to load the content at least up to that point. We can enhance the current solution to do that, but if the desired p is one of the last it will be almost the same as loading the whole page. There are solutions that change the content dynamically so that what is outside the scroll window is not loaded. You will probably need a js lib that will handle this. What techology/framework are you using?
I have updated the snippet and added a simple solution to load more content up to the targeted id and the scroll the page there - you wan't to replace #g with window.location.hash (check out the comments in the code)
I am using jquery
I have added an update with a Virtual List implementation which should work for you
0

The basic idea could be to load your object for a specific amount of data( for example from id 0 to id 100 ). Then handle onscroll event onscroll event in your code and load the remaining data when user requests that.

There are a lot of nice open source packages and libraries on Internet. Take a look at jQuery Lazy and Node.js Streams

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.