Infinite scrolling!

Infinite scrolling!

Hey everyone,
since it's on the roadmap in the UI wiki and needed for the grid component, I went ahead and
created a infinite scrolling widget, which I believe will become incredibly popular (since no
other library has such a widget in line apparently [disclaimer: probably Dojo, they have always
stuff I don't know :D]).
While the spec isn't written yet, the script's usage is a simple as possible as possible, yet
flexible. First, you start with a markup like the following:
<div id='myTable'>
    <table>
        <tbody>
            <tr><td>Sample row</td></tr>
        </tbody>
    </table>
</div>
A couple of instructions on the markup:
1) 'myTable' must have a overflow-y/overflow value set to 'scroll'
2) The table must be prefilled with a first set of items, in this case, one sample <tr>, so the script
    can detect the correct row's height (relative to styling etc)
That's it for the markup, here's the initialization code, for a easy configuration:
$('#myTable').infiniteScrolling({
    total: 1000, // This tells the script the total rows coming from your backend
    chunk: 20 // if set to 20, 20 rows are fetched at once, reducing requests
    scroll: fn
});
now, in order to make it work, the scroll callback must be loaded with a function that handles the
ajax part for retrieving the actual rows. The callback works like this:
function(e, ui) {
    // ui.chunk gives you the actual requested chunk of data
    // ui.start gives you the item to 'start' with, from the actual chunk
    // now get your rows, if you set options.chunk to 20, retrieve 20 rows, from the start index ui.start
    ....
    // after the rows are requested, use the method ui.fill() to give the rows back to the script
    // 'data' can either be:
    // a) a flat array with <tr> nodes or their string representation
    // b) a flat array template objects, i.e. { 1: 'something', 2: 'something else' }
    // If you want to use option b), you also have to set the option 'template' on the initialization to
    // something like '<tr><td class="{$1}">{$2}</td></tr>'
    ui.fill({
        chunk: ui.chunk
        data: [...]
    });
}
and that's it, you're done! The script calls scroll() the first time upon initalization, and then everytime
the user scrolls horizontally and loads chunks accordingly.
Of course, there's a little more that you can configure:
'preload': default is 1, tells the script how many chunks should be preloaded before and after the
               visible offset
'delay':    default is 100 (ms), tells the script to wait a little once the scroll callback happened before
               your scroll function is actually executed - this is much better, because then you won't have
               thousands of requests if you scroll fast, only one once you end scrolling.
Of course, it's not production ready yet, and misses a few things / has a few quirks:
a) right now you need to pass a total row value, so it's actually finite scrolling, not infinite -  as next
    feature, I'm going to implement that if you don't use the total option, rows are not allocated in
    advance, and you can scroll as long as the callbacks retrieve data.
b) cache revalidation: there's no way to revalidate the cache right now - once a chunk has been
    filled, a cache value for this chunk is set to true and it's never requested again. There needs to
    be a mechanismn to manually rerequest it, and/or to request it after a certain amount of time.
c) There's a strange firefox bug, causing the actual chunk offsets to be off a bit - the rows in the
    visual test have a height of 22, in all browsers - however, in FF, the *actual* height, if you measure
    it, is 23 for some rows (for example, the forth) - this is insane - even more so, since Firebug
    correctly reports '22' in the layout panel, but 45 as offset for the next one (should be 44)
feel free to check it out at the jQuery UI SVN in branches/dev/grid, the visual test is at
tests/visual/infiniteScrolling.html, and it's already implemented and up and running in the grid demo.
Cheers!
Paul<br clear="all">
--
Paul Bakaus
UI Architect
--
<a href="http://paulbakaus.com">http://paulbakaus.com</a>
<a href="http://www.linkedin.com/in/paulbakaus">http://www.linkedin.com/in/paulbakaus</a>