Ajax Paging Through Records On Scroll

I've always thought one of the cooler features on dzone was how they paged through the entries as you scroll down the list. This seems a ton more user friendly then the traditional 'next/previous' links.

I decided to see how easy it would be to recreate this functionality using ColdFusion 8 and as usual the answer was 'pretty easy'. There is a bit of JavaScript, but it's nothing too difficult to wrap your head around.

Check the demo here first. I intentionally sleep the thread for 1 second so you can see the loading icon - so don't think that it's just slow :).

On to the code bits. The first thing I have going here in this example is a super simple cfajaxproxy:

<cfajaxproxy cfc="test" jsclassname="test" />

This lets me call the function to get the display data with JavaScript - which is important in this example rather then using binding or ColdFusion.navigate(). See, I'd rather that the user really not know what was going on - and using those other methods would swap out the contents of the container and give a loading icon while we made the Async call. Normally that's ok, I just wanted this to be seemless because later we'll append the page of data to our innerHTML rather then fully replacing it.

Next I create the JS variable representing the Ajax proxy and declare a few other variables that will be used later on:

var testProxy = new test();
var startRow = 1;
var loading = "";

The main JS functions that handle the data retrieval are here:

getData = function(){
   if(!loading){
      loading = true;
      testProxy.setCallbackHandler(populateData);
      var loadIcon = document.getElementById('loadingIcon');
      loadIcon.style.visibility = 'visible';
      var data = testProxy.getRecords(startRow);   
   }   
}

So when this function is called (we'll look at that later) it checks the global 'loading' variable to make sure it's not already getting some data. Next I set a callback handler for the proxy to the 'populateData' function. This ensures that I'll be able to hide the loading gif when the data retrieval is finished. Here's the callback function:

populateData = function(d){
   var container = document.getElementById('display');
   var loadIcon = document.getElementById('loadingIcon');
   container.innerHTML = container.innerHTML + d;
   loadIcon.style.visibility = 'hidden';
   loading = false;
}

The callback takes one argument, the result of the CFC invocation. This function takes that data and appends it so the innerHTML of the display container. Finally I reset the loading flag to false signifying that the request is complete. Here's the display container:

<div id="display" style="height: 100px; width: 300px; overflow-y: scroll;" onscroll="javascript:scrollAction();"></div>
<div id="loadingIcon" style="visibility: hidden;"><img src='/CFIDE/scripts/ajax/resources/cf/images/loading.gif'/></div>

So just a fixed height div with an that fires another JS function onscroll. That function looks like this:

scrollAction = function(){
   var container = document.getElementById('display');
   if(!loading){
      if(container.scrollTop+container.clientHeight == container.scrollHeight){
         startRow = parseInt(startRow) + 10;
         getData();
      }
   }   
}

Again I check that there is not a current request running by checking the 'loading' variable. The next line was a bit tricky:

if(container.scrollTop+container.clientHeight == container.scrollHeight)

So this checks the scrollTop variable against the scrollHeight to determine if the current scroll is at the bottom of the div (ready to get more records in other words). However since the div's height will grow everytime we append more data I had to ensure that the variable div height was accounted for. Adding the clientHeight to the scrollTop handled that nicely.

If the conditional passes then we increment the global startRow variable and call the getData() function.

Oh also - A quick load event in the body makes sure we intially load the first 'page' of data.

<body onload="getData(1);">

Full code for this demo is attached.

Comments
Very cool.
# Posted By Sam Farmer | 8/21/07 6:42 PM
This is very cool indeed. I've been looking for help in creating this functionality for dayS!

Although I was looking for a jquery equivalent of this but this will do :)

thanks again
# Posted By Bhaarat | 10/18/07 10:43 AM
Hi

Thanks for the great post. but can you or someone else out there please show how to do this with PHP. i don't know any cold fusion and even though this is a great feature i am unable to use it :(
# Posted By Olaf | 10/18/07 4:58 PM
This is very nice. i liked it.
I need to create the same in asp.net. i m using the UI suite called "componentArt" which has its own grid and callback trigger.
I m specially interested to know what happens on the server and how does the data get appended to exitsting records. Normally, asp.net grids render the whole tables with <table>...</table> instead of rows.
I appriciated your help in advance. Thanks
# Posted By Viraj Doshi | 1/4/08 9:13 PM

Calendar

Sun Mon Tue Wed Thu Fri Sat
  12345
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31   

Subscribe

Enter your email address to subscribe to this blog.

Tags

actionscript ajax blogging cfsnippets coldfusion flash forms flex misc model-glue off topic personal project learn slidesix sql

Recent Comments

More CF+Java: Compiling Classes And Persisting Objects
Getburl said: I have been attempting to get Db4o working in my CF application and I have not succeeded. I would lo... [More]

Thoughts On Ajax Frameworks And ColdFusion/Adobe
Erast said: http://fanniecollins.10gb... emo http://gracetrevino.phree...... [More]

Extending Ext With Ext Extensions
Erast said: http://fanniecollins.10gb... emo http://gracetrevino.phree...... [More]

CF Needs An Open Source Contact List Importer
Kay Smoljak said: Heh, the fact that sites DO it doesn't mean they SHOULD. To us it's ok, but to a non-tech-savvy user... [More]

A Few Project Updates
Helena said: Now punctually what is the situation ? [More]

RSS


coldfusionbloggers

FullAsAGoog MXNA

Consumed By Feed-Squirrel.com