Friday, March 28, 2014

Implementing Lazy Scroll in jQuery

For as long as I can remember, web developers have turned to good old fashioned pagination when there is a lot of content to show. Don’t get me wrong, pagination is still a very effective way of displaying content, but, in this post, we will discuss an alternative – lazy scroll. This technique, also known as infinite scroll or unpaginate, loads new content via Ajax when the user has finished scrolling through the page’s existing content. Lazy scrolling is used by some of the biggest names on the Internet, including Facebook and Pinterest. In this post, we will talk about building your own jQuery plugin to implement lazy load.

Tradeoffs

 

The advantages are obvious. To get more content, you don’t need to be redirected to a new page (which has a tendency to shift your focus to a different area while the page is loading). By implementing lazy scroll, you are basically controlling the user’s focus on the page!

Lazy scroll is not effective in all situations. For example, if a user clicks a link and then uses the browser’s Back button, the user loses his/her position in the stream of data that was loaded over Ajax. One precaution while implementing this feature is to load new content on a new tab or window.

A related drawback of infinite scrolling is its inability to save the position on the stream. Suppose you want to share something on a lazy scroll page with your friend via email. You are unable to do so because the URL takes you back to the initial position. Therefore, before you decide to go ahead with it, think about the usability of your website.

Additionally, before you implement lazy scrolling, remember that it’s not very search engine friendly. To avoid any issues with respect to visibility on search engines, make sure you provide an alternative with pagination or a sitemap.

Getting Started

 

We’ll begin by laying out a very simple page. The important parts of the example HTML and CSS are shown below. The remainder of the files can be seen by clicking on the demo link at the end of this tutorial.

HTML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<div id="data-container">
  <div class="data-item">
    Hi! I am the first item.
  </div>
  <div class="data-item">
    Hi! I am the second item.
  </div>
  <div class="data-item">
    Hi! I am the third item.
  </div>
  <div class="data-item">
    Ok, this is getting boring.
  </div>
  <div class="data-item">
    Let's try something new.
  </div>
  <div class="data-item">
    How about loading some more items through AJAX?
  </div>
  <div class="data-item">
    Click the button below to load more items.
  </div>
</div>
<div id="button-more" onclick="lazyload.load()">
  Load more items
</div>
<div id="loading-div">
  loading more items
</div>

CSS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#data-container {
  margin: 10px;
}
 
#data-container .data-item {
  background-color: #444444;
  border-radius: 5px;
  -moz-border-radius: 5px;
  -webkit-border-radius: 5px;
  padding: 5px;
  margin: 5px;
  color: #fff;
}
 
#loading-div {
  display: none;
}
 
#button-more{
  cursor: pointer;
  margin: 0 auto;
  background-color: #aeaeae;
  color: #fff;
  width: 200px;
  height: 50px;
  line-height: 50px;
}

 

Basic Workflow

 

If you have a look at the document that we’ve created, new posts should be loaded when you click on the “load more” button. Here are a few points to consider.

  • A request needs to be made to a URL which returns the new items to be appended to your page.
  • This process should repeat if the button is clicked again, but newer posts should be returned the second time.
  • New posts should be provided at every subsequent request, until there are no more posts to show.
  • When there are no more posts left, you should tell the user that he has reached the end.

Ajax Pattern

 

Ideally, you must declare a variable to store the page number, which in turn changes the URL to send the request to. In our demo, we have three such pages – 2.html, 3.html, and an empty 4.html for demonstration purposes.

When you click on the button to load more posts, there is some time before the request goes through successfully and new items are loaded. In this case, we hide the load button, and show some text saying that the new items are being loaded:

1
2
$(buttonId).hide();
$(loadingId).show();

 

Appending Data to the Page

 

First, we need to undo the changes that we performed when the request was in progress, namely, showing the “load more” button again and hiding the text. Secondly, we need to append the response that we received to the list of items already present on the page. Note that in the demo, we receive HTML markup directly to keep things simple. You can send a JSON response too, adding more variables like a message or a status. The append code is shown below.

1
2
3
4
$(buttonId).show();
$(loadingId).hide();
$(response).appendTo($(container));
page += 1;

 

Handling End of Data

 

Once you reach the end of your posts, you need to show your user that there are no more posts to load on the page. This can be done in many ways. We can send the status through a code or message embedded within the response itself. However, as we use HTML markup directly in this example, an empty response marks the end of the stream.

1
2
3
4
5
6
7
8
9
10
11
12
13
$.ajax({
...
  success: function(response) {
    // What to do if the response is empty
    if (response.trim() == "") {
      $(buttonId).fadeOut();
      $(loadingId).text("No more entries to load!");
      return;
    }
    // Do something if the response is right.
  },
...
});

 

Conclusion

 

The demo that we have come up with is very basic in nature, and we can do far better if we put in some more effort. First, we can remove the button altogether and call the function when the user scrolls down to the end of the page. This would remove an extra step of the user clicking the button and make the whole process faster. Secondly, we can just send the raw data through JSON and create the markup using jQuery itself. For example:

1
2
3
4
5
6
$.each(response.items, function(index, value) {
  $("<div />", {
    "class" : "data-item",
    "text" : value
  });
});

Finally, the JSON response could consist of a message stating whether the request went through correctly, the data, and whether there are more posts to load. This is a more efficient way of sending a response in this case.

For more information on lazy load, you could visit this website dedicated to the cause. It contains general information about the idea and existing tools that you can use to implement it in your website.

A live demo can be found on GitHub pages. The code is also available on GitHub.

Source: sitepoint.com

No comments:

Post a Comment