NOTE: This blog has been moved to http://www.looksgoodworkswell.com

Tuesday, June 28, 2005

Death to Paging! - Rico LiveGrid Released

Ok, How About a Revolution?Aren't you tired of getting a chunk of search results from Google, Yahoo, A9, product listings, real estate pages, etc.? And then having to scroll to the bottom and hit the "next page?". In the words of Andy Rooney, "I know am!" What I normally do is search, scroll through results to the bottom of the page, scroll back up to double-check, then I have to scroll back down to navigate to the next page. Seems like a lot of bother to just move through my results.

Have you ever thought that there could be a better way -- or at least an alternative to the standard google paging control?


First a Little HistoryAt Sabre, we started experimenting with managing very large data sets with HTML tables. Our in-house table component had grown very rich in features (things like inline editing, sorting, selection, multi-sort, custom editors, row re-arrangement, grouping and other desktop-like features). But one thing we were not happy with was its handling of large sets of data.

Our table supported two styles of navigation: scrolling and paging. With scrolling you could create a natural way to interact with the data-- but if you had a lot of records just the amount of HTML that was required to download to the page made it unusable once you got over 1000 records.

We supported paging early on to address this issue. The user chooses the page by selecting a specific page number or using the next/previous paging controls.



One nice feature I added was a pre-calculation of the first and last field values of each page for the sorted column. I then displayed this in a page navigation combo box.

This allowed the user to navigate to a particular part of the data without having to guess which page. Additionally, I added tooltips that showed what each page contained. This worked fairly well.

However, most clients really wanted us to make the table a scrolling table. This was not feasible due to large data sets.

The Dilema
The catalyst came when we were designing a new web application. Initially all of the design discussions pointed to tables with less than 500 records. Since the user needed to select multiple values within the table we designed the screens to use the scrolling variety of our table. However, soon after implementation started the design requirements changed (!) and now we had to deal with 10's of thousands of flights.
Now we could have moved them to our paging table. However, given the requirement for the user to move through the flights and make multiple selections before moving to the next step, we were concerned with the usability of this approach. First, would users really think their flight would still be selected after paging to the next set of results? Seeing the page refresh does not make one think everything has been kept. Second, the user really wanted scrolling tables.

Enter Ajax
So what we settled on was to take the existing paging table and turn all page and sort requests into Ajax-based requests. Our theory was that if the transition between pages was almost instanteous without a page refresh then the user would be able to 1) understand selection was persistent, 2) be able to move through the data quickly. It turned out that performance was excellent. And since it was faster there was less confusion about whether selection was maintained while paging.
Darren James (on my team) did an incredible job of squeezing more and more optimizations out of the ajax response/update. It was his work on the table, cinematic effects and drag & drop that brought about the Rico framework.

User Feedback
The users absolutely love it! They couldn't believe the responsiveness they were getting from a table in a web application. But they still had one request. They wanted to control the table by scrolling. And they wanted it to be fast even with large data sets.

A Scrolling Ajax Table
So after launching Rico (http://openrico.org) Darren, Richard Cowin and I felt that this would be the right thing to tackle. We all felt that it should start as a lightweight behavior. Behaviors in Rico are just JavaScript logic and/or layout that gets applied to raw HTML. In this case we are applying just the logic of hooking up an HTML table to any arbitrary set of data via Ajax. Other behaviors (sorting, filtering, reordering, etc.) are planned later.

Introducing LiveGrid Behavior
By applying the LiveGrid behavior, your HTML table gets connected to any size data set and it gets adorned with a scrollbar to control the navigation. The scroller becomes the replacement for the standard Previous/Next page controller bar. When dragging the scroll bar you are actually issuing ajax commands to pull the data into the table in real time! Of course we provide data caching and event buffering strategies to minimize the number of requests and smooth out the scrolling.

Death to Paging?
First, let me say that I really don't believe that paging is evil or that it is wrong in all cases. But I believe the reason that most sites have paging solutions is because 1) its easy to implement, 2) handles the problem of large sets of data and 3) it is convention.

Rarely is paging decided because it is the better choice over something like scrolling. (I should hasten to add that I do discuss some of the cons of scrolling later in this article.)

Our Pitch
So, here is what we are advocating. We would like people to start thinking about replacing the paging data model with the more inuitive scrolling data model. It is not an accident that for years this has been a good model on the desktop. And there have been a number of tables built in the desktop or applet world that do exactly what LiveGrid does-- connect up to a virtual set of data and allow you to scroll through it. In fact, I wrote a table to do this very thing in 1998 for the Java Swing framework.

So we are hoping the release of LiveGrid will create a dialogue of discussion around the best way for users to move through information on the web and in web applications. We need better ways of displaying search results, product lists, real estate listings, etc. on the web.

To help you understand some of the possible impact we provide two demos for the scrolling LiveGrid.

Pitch #1: To the Corporate World: You Can Do It on the Web!
The first example demonstrates a table with around 1000 movies accessible. Only ten are shown and possibly 30 are cached on the browser at any given time. By scrolling the table, the database is queried to return more data just in time and on-the-fly.



One of the big reasons we did not take more applications at Sabre to the web was the inability to manage in a user friendly, easy manner large sets of data in tables. The LiveGrid concept solves this problem. Think of it as GoogleGrids (aka, GoogleMaps)!

Pitch #2: To the Web World: Show Results in a Scrolling LiveGrid
I worked up a search engine example using the excellent Yahoo Search Services API. This illustrates what a search engine page could look like with the LiveGrid behavior. Its really quite fun to play with. I have demonstrated it to computer novices who are not easily enamored by technical stuff. Their response has been, "Why don't they already do it this way?"


In the Yahoo Search example, we are bringing back live data from the search (usually around 35 rows for caching). Then as you scroll we are buffering as needed around you. The result is you can jump anywhere in the search data. Currently, the scroller is limited to 1000 results (the limit placed by the Yahoo Search API).

Pros
  • Familiarity. Anyone who has used a PC/Mac is familar with a scrollbar
  • Ease of use. Just scroll it baby.
  • Control is visible along the side, not hidden at the bottom
  • Shows you how much data you have and where you are in relation
  • With the tooltip and the results feedback it provides you something to watch and helps you to navigate while data loads.
  • I don't have to configure how much I want to see on a page. Designers decide what works best and then you can just scroll through it.
Cons
  • The old problem of I have two scrollbars. One in the window around the results the other on the page itself. [Solutions: make scrollbar styled differently? Keep the complete scroller above the fold]
  • If you have millions of results, you might not want to set the scroller extent to millions. The granularity of the scroll bar gets to be too small. However, it would be fascinating to actually scroll down to those last results. Anybody actually seen those? Do we even know if they exist ;-)
  • Scroller extending below the page fold. Perhaps the best use is to keep the scrolled area completely above the fold. But hey, since you can scroll so fast through your data you won't miss the few extra rows of information below the fold (that you had to scroll to anyway.)

Feedback Design Considerations
We have experimented with several ideas to provide adequate feedback. During scrolling at certain points (when crossing a buffer boundary) there can be a slight delay. We plan on adding a twirling wheel (as in Firefox or Mac) just above the scrollbar and to the right of the status to indicate when the table is busy fetching data. Is this the right approach? The balance here is to not show it too often. It should be a lot like Dunstan Orchard's Live Search on his http://1976design.com/blog which waits to search when the user pauses so the number of updates is minimized.

We added a tooltip (right now it does not fade away-- thats a bug -- but I have come to like it the way it is :-) that shows which record you are currently scrolling through. Also I dynamically update the status bar to show the range of records that are being scrolled through. I think both together give enough assurance that something is happening even with a slight delay in loading data. Certainly there are other ways to provide the feeling of scrolling while waiting slightly for data to flow in.

Your Feedback
Ultimately, its everyone in the application and web community that that will judge if the time is ripe for banishing many of the ubiquitous Prev/Next Page bars in favor of the scrollbar.
I am convinced this technique has important implications in the corporate application world and has the potential to change the way we interact with many of the search results, product listings and data grids we find on the web.

We welcome your feedback!

The Demos
You can find the two demos at:

http://openrico.org/demos/livegrid

Note: This link is broken as of 2007. I will post an alternate location for the demo of the live search. http://openrico.org/yahooSearch.page

The Solution
It should be noted that besides the demos, we are providing open source code to make your tables behave in this manner. Try it, enjoy it and make your sites and applications better. Report bugs to us so that we can provide the best LiveGrid behavior possible.

100 comments:

Patrick said...

This stuff looks absolutely awesome. The Rico project is really starting to shine as _the_ JavaSript/HTML framework. We'll be looking at ways to incorporate it in to WebWork!

Bill Scott said...

Awesome. Let us know once you incorporate pieces of it. We have a strong interest in Java based frameworks as Darren, Richard and myself have been mostly immersed in Java frameworks for the last 7 or so years.

Ramin said...

Are the demo pages broken? I can't seem to get to them. The concept itself is very interesting and something I was thinking about a while back. I was thinking along the same lines of allowing Ajax calls to fetch new data as the user scrolls. It's nice that you guys have already implemented it! Now, if I could only see it in action =]

Bill Scott said...

Oops. I had updated the text of the link but not the reference.

The links are fixed now.

Thanks for catching it!

beep said...

Still seems broken (Firefox 1.0.4 on XP)... No slider to be seen anywhere

Matt said...

Really cool.

How easy is this to use w/ your own data? is it like plugging a widget into your code, or is it rico, but customized? -- If that makes sense.

I'm curious as to how things will play out with other widgets, whether they can be incorporated back into rico easily, etc.

Bill Scott said...

I am going to get a document out there tonight to fully explain this.
But in a nutshell, you do the following:
1. Create your HTML table and give it an ID (could be generated by a tag or whatever)
2. Create a LiveGrid object and register the HTML table id with it. You can set up several parameters in this step
3. Create a LiveGrid request handler (soap, rest, JSP Struts action, PHP, Ruby or whatever your backend language is) that returns a LiveGrid ajax-response

That's it. To see what a response looks like you can hit this url directly:
http://openrico.org/yahooWebSearch.do?query=flowers&offset=0&page_size=5

The XML that is returned is the format expected by the LiveGrid object. It takes this and stuffs all values found in the <td> elements into the table.

I will get a tuturial out there tonight that better explains this.

On your other question: working with other widgets. Since Rico is very low level (pure DHTML) it should work with any web technology. Would have to know the specific widget to comment on compatibility.

Jon ├ůslund said...

Excellent stuff! Only two things that I can think of bothers me.

Not possible to scroll with keyboard. I guess this requires some work.

Also, when I click on the arrows it requires almost always more than one click to scroll a row. Seems to depend on how long the table is. 1 or 2 clicks for the livegrid page and 4 - 5 when I searched for hello on the yahoo page.

Bill Scott said...

We will look into the keyboard issue.

Yes, I agree on the scroll arrow, we thought we had a fix for it on the day we released it but it had some problems so we backed out the fix. Richard is planning on getting that resolved in the next day or so.

Thanks!

Bill Scott said...

On beep's comments about it broken. The issue was the scrollbar did not show on Firefox 1.0.4 on WinXP. We made a compromise and guessed at the scrollbar width (we worked hard to get rid of all magic numbers but this was stayed in :-( to be 19px. But of course the scrollbar width in windows is a user configuration (Duh!)

If you are having this problem temporarily size your scrollbar to 16 or 17 pixels.

We will change the way the layout is structured so that the scrollbar size will not matter.

Sander said...

Was just reading your PDF on using the ajaxEngine. Just wonder how you would register a function call to a asp.net page?

Something like ajaxEngine.registerRequest( ‘getPersonInfo’, ‘getPersonInfo.aspx’);

Would this require a different asp.net page for every function? Or would one specify the function name in the secondpart of the handler?

Bill Scott said...

Disclaimer: I have not coded with ASP. However, I understand it to be similar to JSP, etc.

You could set up your aspx page to be a single request handler. It just formulates the ajax response with appropriate text/xml set in the content header and correct xml version, etc.

Or you could pass request parameters to the aspx page and have it handle multiple types of requests and come back with a response tailored for the individual request.

In the Struts world we have the concept of an action (Java code) that does the heavy lifting then forwards to a JSP page that does the XML response formatting.

Does that help -- or am I offbase?

Sander said...

Will give it a try. I'm just wondering how this wil work with asp.net as it uses precompiled code contained within a dll.

Thanks!

Chad Maughan said...

You guys rule! When are we going to see Rico in My Sabre? Why save all the cool stuff for the airline side of business? =). And Bill, I'm guessing from your stunning portfolio that you haven't had much say in the My Sabre UI, is that true?

P.S. - we're doing some really cool stuff with the Worldspan XMLPro API (on the agency side). We're in the final stages of development, I'd love to get your opinion on it, when we're done, if you could spare a few minutes. We've got our eyes on Rico for some rich client side features. Keep up the good work, and thanks for sharing!

Bill Scott said...

This is a fun side-effect of opensourcing Rico. It really opens the door for us to share across Sabre Holdings! Even better than our corporate reuse library!

I will give you a call tomorrow so we can see the cool stuff you are working on.

Anonymous said...

Cool stuff -- I look forward to seeing where this goes.

How about an RSS feed for your blog?

Bill Scott said...

I published the Atom link in the links bar to make it easier for some readers.

I also added a feedburner XML feeder link.

These are in the Feeds secion in my sidebar.

Thanks for prompting me to get that done.

Austin said...

This is great, but I have a couple of worries.

First, scrolling is good because it lets you skim a long list quickly, or it removes the hassle of waiting for the next page of results when skimming lists slowly. Unfortunately, it loses the "chunking" effect we achieve with paging.

Chunking large data sets is also a good thing.

Second, in similar desktop apps, you can usually enter a record number and jump right to that record. For some data sets, this function is *absolutely* necessary.

Lastly, you can't bookmark a chunk of results. I do this from time to time.

I imagine jumping to a specific record and bookmarking a starting point in the records could be accomplished pretty easily.

Very nice interface, though. Very natural and intuitive.

Bill Scott said...

Excellent feedback.

Chunking effect...
Here is what I had thought about that. Nothing prevents having the next/prev bar available. We say "showing 10-19 of x" so it would be intuitive that the next batch would be brought in by paging.

Though the screen shot is not great, if you look at the predecessor of the scrolling example it had a drop down that could let you jump to the page that starts with Smith and ends with Scott (that is if you have a way to determine the chunks before-hand).

Also, the page down in the scrollbar moves you one page at a time.

Record number jump...
I have done this before on desktop apps. Similar to what Microsoft Access has on its record navigator bar. This also would be easy to add. I discussed putting this in the example (where it says Showing X of Y replacing the X with and editable field to type it in directly/tab out or enter would jump there)

Also consider that the scroller tooltip and showing feedback gives you close to that effect.

The nice thing is that the API exists for this in the live grid. It is just a request that gets an offset and a page_size request parameter under the cover. So you could call it from JS.

Bookmarking...
Another good observation. I had not thought of that -- although it seems obvious. That is one will need to think about the best way to do...

One thing that I am concerned about that we did not get around to addressing was a simple spinning wait icon while data is loading (when it takes longer than some threshold). This seems important when latency can be an issue as in the Yahoo Search.

Thanks for the excellent feedback.

Richard Cowin said...

Austin,
I agree with Bill. I think the feedback is very good.

I think the "go to record number" is a reasonable idea. As the contents get large (100,000) records, the scrollbar will not get you to a direct location based on the pixel adjustments. However, with such huge contents, I am not sure a user would typically think in terms of a specific record number. They might be thinking more in terms of a filter based on a specific field.

I think the question always boils down to what content does the user want to see and how can we get them there.

I think the mechanism will be very straight forward to implement. Perhaps as an option?

I think the bookmarking is a very good idea. I have heard a few comments on this issue. There are other concerns that the AJAX solutions break the capability to use the back button to index back to previous content.

I think the bookmark is a much simpler solution. We can always provide a bookmarklet somewhere in the table that can be dragged into a bookmark container. I think this would be pretty straight forward to implement. In fact, I think the record number range (at the top of the table) could pull double duty as a bookarklet as well. Would this provide the capability you are looking for?

Once again, I think this is very useful feedback.

Peter B said...

It doesn't work in Opera - is support for this browser planned?

Peter Krantz said...

This looks great and will make web apps more usable. However, it would be great if accessibility could be taken into consideration. Looking at the demos there are a few things which should be easy to implement:

* Make sure table headers are part of the same table as the data rows.

* Make it possible to navigate the table without a mouse.

* Provide a fallback that allows the user to do the old-fashioned paging if javascript and/or css is turned off (this may be work that should be done by the developer using the JS framework).

Good work!

George Hotelling said...

Rico looks awesome and I can't wait to use LiveGrid with Ruby on Rails, but I have a concern along the line of Austin's bookmark comment.

I would be worried about providing permalinks so people could post links to my LiveGrid data on their blogs and email them to their friends.

I wonder if you could use the URI fragment element (<a href="#some_fragment">) to link directly to a result in the LiveGrid.

Richard Cowin said...

George & Austin,
I was looking into the bookmark concern and have a question. Would it be reasonable for now to have a bookmark only index into one LiveGrid or ajax based component on a page at a time?

I see some complexities associated with providing bookmarks on multiple ajax components on a page that have master/detail type relationships. I think there might be some issues associated with the software understanding the ordering required for such indexing.

I am kind of hoping that supporting bookmarks for a single LiveGrid on a page will cover 90% of the cases. If this seems acceptable, I think we can get it out pretty quick.

Richard Cowin said...

Peter b,
At this point we have talked mostly about Safari being our next browser to support (we are mostly Mac users). I will look into Opera and see what the issues are. Can you tell me the main issues you are having?

As soon as we understand the work involved, we will give you an idea of what our future support for Opera will be.

Richard Cowin said...

Peter Krantz,

We seperated the headers to keep the interface simple. We will relook at it to see if we can achieve both goals.

We have had a few comments on the mouse and keyboard navigation. It looks like it is one of our a top priority.

I think the fallback to paging is a good idea. I will add it to our list.

Great feedback,
Thanks.

Simon G said...

What about client side sorting?

Most grid controls these days can sort their result sets without a server hit. With 1000 records - you'll bring the browser to its knees trying to sort.

Do you have a strategy to handle this? (along with resizing and reordering columns)

Bill Scott said...

SimonG,

Sorting...

Actually, we would not do client side sorting since we do not have all of the records on the client. And if we could sort 10,000 records on the client the JS would start creaking (if not croaking :-)

We are already doing server side sorting at Sabre with an ajaxified table and it works wonderfully.

Currently we are sorting tables with 10-20,000 records and it takes about half second for the table to refresh.

Why is it so fast? Well the sorting is done in Java (you could pick your own backend language) so that takes hardly anytime.

The update to the table is not anything special. It's just a content refresh of a few rows in our table. No different than a normal scroll operation.

Column re-ordering...

We have the list re-ordering by dragging columns as you have seen on other grids. It will most likely be another behavior you add to the table.

Our goal is to keep a single behavior simple. We expect that Rico will usually be buried in other toolkits (PHP, JSP/Struts, JSP/Faces, Velocity, Rails, etc.) so they can generate the appropriate behaviors by attributes set on their "tags"/"components", etc.

angusf said...

Thanks for sharing this stuff, looks great. Just like to second requests for:
- bookmarking particular point in data listing (from browser bookmark button if possible). Important to be able to share url to point in data with others.
- scroll bar arrows working (is unusable without these)

techy said...

Great ideas - I am also curious about how this could be made accessible, but overall this looks like a great idea! For bookmarking / back-button, have you looked at this article yet? I think combining this technique with your LiveGrid might do the trick.

Dan Erikson said...

Richard Cowin,

A clean interface for headers might be to ignore the thead section of the table if there is one, and populate only the tbody section with the generated rows. One can then simply place the desired headers in the thead section.

Anonymous said...

I got LiveGrid working with my own data, but I have a question. I replaced the html that outputs the 10 initial rows with blank TD cells. So when the table first loads, all of the cells are blank. Rows 1-10 of data doen't load unless I scroll down to the second page, then back up. Is there are way to easily make the first page of data come in without having to scroll down then back up? --Jay

Bill Scott said...

Jay,


In our example we load the data manually by setting the contents of each cell via the JSP bean mechanism.

However, you can make a call on your livegrid instance to refresh the content of your table view. Here's how to do this:

myLiveGrid.requestContentRefresh(0);

The parameter is the index to start the refresh at (0 is the first row of data).

When creating the live grid we need to allow an option to do this automatically.

Just as you can set a prefetchBuffer:true in the options you would be able to set requestContentRefresh:true

Sorry for the confusion.

Anonymous said...

Bill,

Thanks for your reply. When I do this:

onloads.push( function() { tu = new Rico.LiveGrid( 'data_grid',10,950,'livegridcontent.cfm', opts ); tu.requestContentRefresh(0); } );

Nothing happens, but when I do this:

onloads.push( function() { tu = new Rico.LiveGrid( 'data_grid',10,950,'livegridcontent.cfm', opts ); tu.requestContentRefresh(1); } );

it automatically loads the table, starting at row 2. How come setting requestContentRefresh to 0 does nothing?

--Jay

grtfercho said...

Just to throw a comment on the Bookmark subject.

Google map's approach seems to work without problems. Add a [Link to this Page] comment on the side of the table, reload the page to that specific set of rows and then use the bookmark mechanism from your browser to save it in your list.

Check Google Maps with any address and see the link on the right upper corner.

Darren James said...

Jay,

The reason the tu.requestContentRefresh(0) doesn't work is that there is a check in the code that updates the UI that prevents gratuitous UI refreshes. That is, if the content refresh parameter is the same as the last displayed position, it doesn't do anything. As Bill said, we need to add an option to allow for initially updating the content. I can imagine this will be a common usage scenario. In the meantime, you can change the code to the following:

onloads.push( function() {
tu = new Rico.LiveGrid( 'data_grid',10,950,'livegridcontent.cfm', opts );
tu.lastDisplayedStartPos = -1;
tu.requestContentRefresh(0); } );

Hope this helps...

Mike Levin said...
This comment has been removed by a blog administrator.
Mike Levin said...

Hi Bill,

Great article and technology. I'm dying to incorporate it into my app framework.

I'd like to see the arrow keys not scroll the list, but instead to move a highlighter capable of feeding IDs to an event handler. To scroll the list from the keyboard, think about using Page Up and Page Down instead. My rationale is that the behavior found in mainstream client-software like the Microsoft Outlook mail client is the most natural to people, and is what Ajax-driven Web apps should emulate. So, the highlighter would feed the record ID for a preview pane or detail window that would show the expanded record data.

And how about column sorting? I've played a lot around with column sorting with paging solutions. It gets sticky when the data is sorted first sorted by column A, then column B. Cached result set solutions solve this by cursoring through the larger cached data set. But what happens when you're re-querying the original data source every time, such as it appears here? I find it difficult to articulate SQL statements that essentially say: sort by column A, then by Column B and feed me X number of results starting from position Y. Alternative cursor-based SQL API's let you do this, but then you have open connections and cached results in the form of temp tables on the SQL server again, which kills scalability.

Anonymous said...

Darren, that worked great. Thanks so much. Looking forward to building this into our future apps! Jay

Richard Cowin said...
This comment has been removed by a blog administrator.
Richard Cowin said...
This comment has been removed by a blog administrator.
Richard Cowin said...

The bookmark input was very useful.

I have put together an approach along with some example application code showing how LiveGrid will support bookmarks in the next release.

Thanks.

Richard Cowin said...
This comment has been removed by a blog administrator.
Richard Cowin said...

Jon,
We are actively addressing the scrolling issues. You should see some noticeable differences in the way it is managed in the next release.

Richard Cowin said...

Dan & Peter,
Your points are well taken.
We will be making the table a bit more natural to specify. The headers really should not be separate from the table.

Anonymous said...

I have tried to get this to work on my site without any luck.
I see the response coming back from my xml feed in _processAjaxResponse()
with a responseType=object and
a responseId=data_grid_updater,
but this.ajaxObjects[responseId] seems to be udefined when it is passed to _processAjaxObjectUpdate.

I know the array is getting populated with an object during the registerAjaxObject function. I checked with alerts.

Any ideas?
Thank

Bill Scott said...

anonymous,

Can you send

1) the code sets up the livegrid behavior
2) the HTML for the table
3) the XML response that comes back

You can email me directly at billwscott@gmail.com

Chris Sears said...

As a developer, I certainly commend you guys for your work. It's very impressive.

However, as a user interface designer, I'm not very hot on the idea of using LiveGrid to replace paging in most situations. Here's why:

By turning the scrollbar into a paging/chunking control, you are violating the UI metaphor that people are accustomed to. Scrolling should move something, not load something.

How should it be done? Microsoft Access is a good model and SQL Server Enterprise Manager is even better.

When you scroll a data table in Access, it initially behaves like your LiveGrid, in that the table contents are fixed and you get a tooltip with the record number as you scroll until you drop the scrollbar. However, once the data has been fetched, scrolling back up to the previously fetched data is smooth and fluid. It looks like this is what you guys are going after, but the scrolling is just not nearly smooth enough to "feel" right.

The better example is SQL Server Enterprise Manager (EM). When scrolling down into unfetched data, EM displays empty table cells that move as the user scrolls. As the data is fetched, it is filled into the empty cells. The motion of the empty cells is critical to maintaining the visual metaphor of a scrollable window. I don't know how hard it would be to implement this type of behavior, but I think it would improve usability.

Bottom line: I like what you have done, but it's never going to kill off paging. If it made sense, Google could have offered search results in an Ajax-bound grid a long time ago. But it doesn't. It makes sense for Google maps, and that's why the dragable scrolling is present. Frames are practically taboo in modern web design, because users just don't understand them. Your LiveGrid is potentially even more confusing.

Best of luck with the project and thanks for pushing things forward.

Bill Scott said...

Chris,

Thanks for the good comments. I always enjoy a lively discussion.

There are two really, really good points you make:
1) "the motion of the empty cells is critical to maintaining the visual metaphor of a scrollable window"
2) ajax scrolling will not kill off all paging.

Now let me differ with you on some of the finer points.

As you might have noticed in my blog, I mentioned that I did not believe that paging was really dead. The title is more provacative than the content :-) I even listed pros & cons.

You imply at the start that your real issue is with the design concept of scrolling through large sets of data.

However, it seems that your critique is not so much on the concept but the implementation. Your complaint centers around that it does not feel as fluid as it should. That is not an argument about design. That is an argument about implementation (which you praised to start with). I agree that there are issues in the implementation. In fact Darren & Richard are working on making the smoothing become more natural and smooth.

But I think if you use the axiom from the design world (remember I now make my money from design, not coding :-) of "What if this were magic?" Then I think the scrolling solution holds up in most cases. Users don't always think of everything in chunks.

Think about it like this. You say that we are violating the UI metaphor that people are accustomed to. In actuality it was paging that in *some* cases broke the natural scrolling idiom that people were accustomed to.

This is kind of like the concept of "File" that Alan Cooper argues against since most people don't really understand the difference between storage and memory. He argues for removing the distinction.

The user doesn't care that the results for a real estate listing are on the server or on the client. What the scrolling in live grid does is try to make that distinction hidden. In other words hide the technical implementation in a natural model of scrolling.

In the Access example you cite, the smooth scrolling is possible because it is a desktop app. Once they have retreived records they cache them on the client. We only keep a buffer window around the actual data shown. Why? Well we live in a browser and don't want to choke the browser.

We also talked about something like the EM technique-- showing empty cells or animating a scroll, but never got anything satisfactory.
In the Google Maps example they have a side effect that the browser caches images on your machine, so once you have scrolled over to a portion of the map and go back it is still there. We don't have that luxury. However what we are doing (see an upcoming blog on richardcowin.typepad.com) is working on smoothing out the scrolling to make it appear more natural.

Your argument about Google search and google maps does not make sense to me. Just because google search does not or will not use scrollable results does not mean it is invalid. There are a number of practical applications for this: mail clients, product listings, real estate listings, etc. On the corporate side just about every data grid that went to paging can return to scrolling with Ajax. We have seen actual customers very excited to get rid of paging. I can't even count how many customers complained about paging tables that were elated on the return to scrolling.

Your argument about Google Maps also does not make sense. You are comparing a 2d graphical space to a list. Scrolling would be very limiting for a geographic space. When I wrote a wargaming system complete with GIS mapping in 1990, I used the exact same concepts that google maps is using. I had a hand and you could push the map in any direction. There I used offscreen buffering to make really smooth scrolling. However, I also provided scrollers which made it nice for nudging.

Its kind of funny but I actually toyed around with putting the hand push/scroll concept into the live grid, but thought it was too cute and gratuitous.

Finally, I don't understand your comparison of a scrolling grid to frames. Users did not care whether something was in frames, what they didn't understand was why the back button did not work. Users do understand scrolling. They are not confused in anyway about scrolling.

Now, let me clarify for everyone. If it takes a while to get data back during fetch cycles, then live grid scrolling is not a good choice. If however, you can fetch data in reasonable times then scrolling is a candidate.

Thanks for the feedback.

Richard Cowin said...

Chris, thanks for the praise.

As Bill stated, the scrolling on the next release of LiveGrid will be improved - I will post on my blog soon (we are wrapping up some code for the next release). It will also enable us to do the blank scrolling bit that you discussed.

I think Bill covers most of the points, but I wanted to introduce some posbilities as to why google search may not use an AJAX table yet and what value it may or may not add.

First of all, I think that the nature of LiveGrid adds the most value when data is well formed by nature. This type of data is typically interesting to navigate beyond the first couple of pages. A lot of times a user might want to sort or even filter this content based on various fields or characteristics of the content. I think a list of movies fits into this category very well.

As a user of google search, I typically only care about the first page or two of the results. This is because I either find what I am looking for quickly (based on the prioritization) or I give up and try a different search. It seems at first glance that LiveGrid adds only minimal value to this already prioritized type of content.

So should google search stay with paging? Well, as I said above, I still fail in my searches sometimes. It seems to me, that googles prioritization is not always ideal for me. There are times that I just give up because I don't want to navigate through thousands of results.

Clusty uses clusters as an interesting alternative for organizing search results beyond a single prioritization. If I don't immediately see what I am looking for, but one of these clusters captures my intent, I may still have a chance of finding what I am looking for. Now obviously there will be new and better ways of managing and navigating this type of content (perhaps tags will help). However, as it becomes more formed, something like LiveGrid defintely could add more value.

I think that we will see some interesting and fluid navigation mechanisms for traversing such content in the future. Will these new mechanisms look like a table? Perhaps not, but I kind of think these approaches will rely much more on AJAX than on paging.

Reuben said...

Our application has multiple views (TABS) and each view there will be a livegrid respective to that view.
Each LiveGrid has a unique identifier. We switch between views with hide show divs this works great except for the scroller.
Due to the scroller having no unique id, the capture event handler only listens to the first defined livegrid. This causes the other views to have no scroller (no data controll). How do we fix this?

Andrew said...

This is brilliant technology and certainly has many applications. We have been trying to implement it in one of our applications and have the following suggestion.

Could the buffering be improved via some type of client side cacheing of results?

At the moment the buffering technique used retrieves data that has already been retrieved. i.e. Lets say we have a page size of 10, the large buffer size is set to 70. When scrolling, we get to the 17th result and a new request is sent off with the offset being 17 for 70 results. However, we previously retrieved results 1-70, which overlaps with the new results 17-87. Wouldn't it be better to only retrieve the results from position 70 onwards? To ensure that the client doesn't have too many rows, a cache clean-up could be used at say, 5 times the buffer (in the above case it would be at 350 results). It would be great if the client only downloaded the additional rows needed, rather then 3/4 of the same data.

Bill Scott said...

Reuben,

I am not sure I completely understand the problem.

In the Rico Search example I have 3 livegrids and bounce back and forth to them the same way you are doing it with tabs without any problem.

Are you trying to get events from the scroller that is currently visible and therefore need the scroller id? But it sounds like the other grids have no scroller visible?

Can you send me some code snippets, screen shots, etc. to dev@rico.tigris.org? Once we have your problem solved I will post the result in the rico.tigris.org forum and note it here.

Richard Cowin said...

Reuben,
I will see if we have a workaround.

We will have a cleaner fix by next release - should be soon.

Richard Cowin said...

Andrew,

Thanks.

Very observant.
We actually considered using the partial (nonoverlapping) buffer load initially, but decided to do a simpler approach for first release. However, I think it is a good suggestion and we will be implementing soon (hopefully next release).

The next release will have some other improvements that will make the scrolling look more natural and responsive. It will also resolves some scrolling issues brought up by some earlier comments.

Anonymous said...

Has anyone gotten this to work yet? I havent had any luck. Could you share examples if you have?

Bill Scott said...

Anonymous,

Please be more specific. There are any number of features that are available and there are many other folks that are already using all aspects of rico.

The best place is to got the rico.tigris.org, register, and post a message with details to the Forum Discussion.

Thanks

Richard Cowin said...

The forum is at http://rico.tigris.org/servlets/ProjectForumView.
People are sharing examples there.
Feel free to ask questions, regardless of your level of familiarity.

Anonymous said...

Hi,

Excellant stuff. Tried it. However, cannot work around 2 problems.

a) The table does not show the data the first time the page is loaded [inspite of data being fetched]
b) How do I place links inside a cell? Inspite of my sending the data with "A" tags, the cell does not show the link.

Abhay

Andre said...

We handle scrolling/paging in EBA Grid in a similar way. warning: It's not open source, and is IE only until later this fall. However it supports asp, jsp and php. It also has keyboard navigation, which was mentioned above as a good feature.

I wanted to comment on the drawbacks of scrolling comment. Users do expect to "move" through data as they scroll, and this is the experience they get with AJAX. Assuming you load the data fast enough, the user should never know the data is being loaded;-)

Romka said...

Pretty cool idea... however i see this problem as a user - lets say i have list of movie linked to details page - when i click on Details i view it and go back to the page i came from ... with scrolling - you go back to the top of the list.

Anonymous said...

HI all
its really cool thing, i was trying it with rails application, but facing some problems.
can anybody help me who hav done it with rails?

Anonymous said...

First, let me say that LiveGrid is just unbelievably cool - kudos for introducing it to the world.

However, I'm having a technical issue getting it implemented. I am trying to use it within a Rails app (like the previous poster). I'm getting an error which I'm sure is caused by my own incompetency but since I'm doing so many new things at once I'm not sure where the problem lies.

The error (Firefox 1.0.7 Javascript console) is as follows:

{largeBufferSize:7, nearLimitFactor:0.2}.extend is not a function.

/javascripts/rico.js Line: 1755

Does this familiar to anyone? My installating is pretty virgin still so I figure if I'm getting this then others may as well, so it'd be good to have it posted publicly. I do have prototype.js included right before rico.js in my rhtml page.

TIA.

Dan said...

I'm unable to get to the demos from this blog. I get 404 errors. OS X 10.4.2 with Firefox 1.

Richard Cowin said...

romka,
The back button approach can be implemented with the current Rico library. The LiveGrid is set to index into any position at startup as well as to have its sort column and direction specified. This is used in the LiveGrid demo on the openrico.org site with the link above the table. I have talked a bit about coding with this on my blog.

There is also some articles on doing back button in ajax controls that can easily be used in Rico. I cannot find some that I used to use, but you can find a few by just typing ajax and back button in google.

Best of luck.

Richard Cowin said...

Dan,
All the demos on the openrico.org are currently in Ruby on Rails. I will be publishing these on the site for easy download soon.

If you still are having problems you might try posting to the Rico forum on Tigris http://rico.tigris.org/servlets/ProjectForumView.

Prometeo said...

This stuff is great, but it seems absolutely imposible for the mobile devices. When will there be a solution for Ajax or RIA for this low profile devices?

muncman said...

Regarding the 'extend is not a function' error, I was getting that, too. To get around it -and I'm not claiming this is a great solution- I not only included protoype.js version 1.4, but also version 1.3. Hope that helps.

Anonymous said...

I'm still stuck with that "extend is not a function" error... I tried the trick of including both versions of Prototype, without success... and I don't see what the error is with the rico code. Any further help would be greatly appreciated. Thanks!

Bill Scott said...

Anonymous,
Can you post your problem to the rico.tigris.org forum?

(http://rico.tigris.org/servlets/ProjectForumView)

When you do so, please post your code and one of us will help you with it.

chucklarge said...

Does anyone have a working example with php? I am trying to follow RicoLiveGrid.pdf but don't know java well enough to translate it to php. Thanks

Anonymous said...

I'll do that, Bill. Thanks for the reply!

Anonymous said...

Be very obliged if you could post the ruby on rails demo source code for download.
Thanks

Anonymous said...

Hi All-
I am having a little trouble using the Rico LiveGrid and would be most grateful to anyone who could help me out.

The logic in rico.js that's used to parse the xml response is failing in my case, and I have spent quite a long time looking at this.

I have even simply cut and pasted the response example provided in
the doc into my jsp, but this doesn't work either.

The response object claims to have zero length, although clearly it
does/should not.

....
var response = request.responseXML.getElementsByTagName("ajax-response");
alert(response.length);
....

If anyone could possibly give me a hint as to what I'm doing wrong, I would
be most grateful.
Thanks in advance!

-Randy

---my testRicoResponse.jsp---
OK, this system won't allow me to post the jsp file containing the xml, but trust me, it's valid-- even ie displays it properly.
I'd be more than happy to email it to anyone crazy enough to try and help me :-)

rkilmon at gmail dot com

Anonymous said...

Hi All-
I am having a little trouble using the Rico LiveGrid and would be most grateful to anyone who could help me out.

The logic in rico.js that's used to parse the xml response is failing in my case, and I have spent quite a long time looking at this.

I have even simply cut and pasted the response example provided in
the doc into my jsp, but this doesn't work either.

The response object claims to have zero length, although clearly it
does/should not.

....
var response = request.responseXML.getElementsByTagName("ajax-response");
alert(response.length);
....

If anyone could possibly give me a hint as to what I'm doing wrong, I would
be most grateful.
Thanks in advance!

-Randy

---my testRicoResponse.jsp---
OK, this system won't allow me to post the jsp file containing the xml, but trust me, it's valid-- even ie displays it properly.
I'd be more than happy to email it to anyone crazy enough to try and help me :-)

rkilmon at gmail dot com

Anonymous said...

Hi All-
I am having a little trouble using the Rico LiveGrid and would be most grateful to anyone who could help me out.

The logic in rico.js that's used to parse the xml response is failing in my case, and I have spent quite a long time looking at this.

I have even simply cut and pasted the response example provided in
the doc into my jsp, but this doesn't work either.

The response object claims to have zero length, although clearly it
does/should not.

....
var response = request.responseXML.getElementsByTagName("ajax-response");
alert(response.length);
....

If anyone could possibly give me a hint as to what I'm doing wrong, I would
be most grateful.
Thanks in advance!

-Randy

---my testRicoResponse.jsp---
OK, this system won't allow me to post the jsp file containing the xml, but trust me, it's valid-- even ie displays it properly.
I'd be more than happy to email it to anyone crazy enough to try and help me :-)

rkilmon at gmail dot com

Anonymous said...

ok, so apparently "preview" actually publishes to the page.
sorry for the triple post!!!

Bill Scott said...

It appears that Randy's problem is in the way his .jsp is formatting the XML file.

The
<?xml version="1.0" encoding="ISO-8859-1"?>

must always come first in the XML returned.

In his example it came as the third line.

Anonymous said...

Yes Bill, thanks so much for the info!
(you might want to modify the sample code to reflect this, as I was just using what was provided.)
Cheers-
Randy

Tom Stewart said...

I'm experiencing an issue where the application defined parameters are not passed or seen by rico.

Using the source example (provided by 'view src' of the livegrid.page), I set the requestparameters option (as described in your PDF).

e.g. ...
var tu = null;
var sFinance = 'finance='+$('txtFinance').value;
var sPlant = 'plant='+$('txtPlant').value;
var sTour = 'tour='+$('txtTour').value;
var params = [sFinance, sPlant, sTour];
var appOpts = { prefetchBuffer: true, onscroll: updateHeader, requestParameters: params }
tu = new Rico.LiveGrid('data_grid',5,100,'XMLSections.asp',appOpts);

Apparently, the params aren't being seen by rico or passed to prototype's Ajax.Request object. Instead, (the default?) the sendRequestWithData's url looks like: XMLSections.asp?id=data_grid&pagesize=70&offset=0

I had hoped to observe something like:
XMLSections.asp?id=data_grid&pagesize=70&offset=0&finance=001712&plant=GMF&tour=1

Any idea(s), suggestions or explanations why the defined parameters fail to get passed? Your help is most appreciated.

Thanks,
--Tom

Tom Stewart said...

Amazing! Rico does pass parameters!
I used the setRequestParams() method to pass my parameters. It worked.

Mack said...

Bill!

Please help me! I am trying to use the LiveGrid from Rico. When I load the page it displays the initial table with the scroll bar. I am just prepopulating the data in the table. When I hit the scroll bar the first time it just clears of everything and it is just an empty table at this point! The XML I am creating in the response is valid. I perfectly followed the livegrid tutorial. There are no javascript errors too!

Please help!

Bill Scott said...

Mack,

Your best bet is to post to http://rico.tigris.org/servlets/ProjectForumView

Be aware that a new forum is being set up on the rico site that will make it easier to participate.

Yves Peeters said...

How about printing? can u still make the page printerfriendly?

John said...

The grid looks great. It would be nice to have an example of just the grid with the source code (ex: downloadable files).

Viewing the source of the current demo is ok, but there are many other items being used on the page which makes studying just the grid a little confusing.

msksatish@gmail.com said...

Can we have resizable "row" heights? for eg:
the 1st row in the table is of height x and the second row is of height 2x;

I need this coz; I dont want to truncate contents in second row

Anonymous said...

designing search result

Here's some useful info on designing search result
which you might be looking for. The url is: http://www.jaldisearch.com/

JHanna said...

Good work-this is an issue that has bedeviled me for a long time. We have a css/javascript method based on modifications of

http://www.imaputz.com/cssStuff/bulletVersion.html (CSS)

and

http://www.kryogenix.org/code/browser/sorttable/ (Sorting at client)

Our mods to these scripts focused on using thead and tbody, and eliminating some quirks in display of the tables.

Some things on my wishlist for the perfect grid solution, other than what I know you have:

1. Resizeable and repositionable columns, with cookies to remember the lay out for the user. We don't have-I have seen commercial solutions that have. See

http://www.scbr.com/docs/products/dhtmlxGrid/

2. Ability to toggle between scrollable grid and no scroll. We do with CSS; not sure if you have that ability just with CSS. This comes in handy for printing the entire table when desired.

3. Ability to support controls in the table. You may have-haven't tested yet. It would be nice to have the ability to have editable fields that look like regular data in cells, though text fields in appropriate places do that job nicely for us.

4. Fixed footers outside of scroll area. We have but not foolproof.

Thanks-

Anonymous said...

What has happened to the openrico.org site?

Is it down for good?

Haven't been able to acess it from work or home for 3 days now.

Jim

FeaturePics Images said...

can not open
livegrid.page
yahooSearch.page

Are they dead?

Kyle said...

Didn't Microsoft attempt something like this in their Live search a couple of years ago? I feel like they did, and most people didn't care for it, and they killed it shortly thereafter.

I like the idea, but the execution I think could be improved. Why not treat it more like Google's SearchMash, where, rather than introducing a second scroll bar, you just use the browser's default, and keep everything above the results fixed in a floating div.

Using a second scroll bar reminds me of an article linked from the O'Reilly Radar blog a couple weeks ago entitled "The Uncanny Valley of User Interfaces" (google it) in which the author posited, if I recall correctly, that some interfaces belong on the desktop, and some feel more natural to the desktop. The examples he used were Gmail, which he claimed fit his mental model of a web app, versus Zimbra, which didn't feel at all like a webapp, and thus caused discomfort in it's use as it challenged his mental model of what a webapp should be.

Some of these new AJAX interfaces like the one shown in this post don't feel right in my mental model of a web app. I believe I'd prefer to give the user a set of choices from which to choose how many results fit on a page (ie. 10, 25, 50, 100, etc.).

Just my .02

Anonymous said...

below is still paging but i dont have to click often- (just a read, actually not usefull)

For the yahoo search result.
Their is a frame in which 10 results are shown for 30 seconds and then (page fades) refreshes with new 10 results every 30 seconds. At any time i can pause.

1 Their is a small slider which can be used to go back or forth in 30 seconds increments.
2 Their is a slider to increase or decrease page refresh, increase to 20 seconds or decrease page refresh to 40 seconds.

Anonymous said...

Microsoft have had this with their image search for as long as I can remember http://search.live.com/images/results.aspx?q=&mkt=en-nz&FORM=LIVSOP

Anonymous said...

(Just a read - actually not usefull)

ice (database) - water (data result)

paging - ice to water cycle

scrolling (river) - ice to water flow determined by the pull of gravity which is the user.

top-down (ice on ocean) - ice block melts to water - click blocks of ice from above to break down to results.

data rain - data is splashed on the screen which settles below with details like water and then solidifies even further below as ice (data sets).

also.,
Plasma ball.... action at a point triggers display of connecting results.

lightning n more..

Marcos said...

Great post.
Paging is an arcaic method of showing data...
With the new methods available like ajax we have to think of new ways.
And if you have a million results, then narrow your search, surely you won't look at the whole result.
Search engines have to follow the change also making them more accourate. Now we are all used to the Google "inteligence", so websites have to improve their seach engines too.

Anonymous said...

Hi! You can find an ASP NET C# wrapper of Rico Live Grid at http://www.codeplex.com/SharpPieces

Thanks!

JP said...

The new url of demo is http://demos.openrico.org/livegrid

Jazzbo said...

I've just found the Rico LiveGrid and am very encouraged and impressed. Currently I've already invested my time in developing several complex jsp pages as part of my project by which to capture the data that will be displayed via the grid. They include (a js version of) combobox and calendar elements and a strict tabular & css-controlled layout. I'm now tempted to scrap the jsp path and instead capture the data using the LiveGrid form mechanism by which to edit grid content. I'll only be able to do so though if I'm going to be able to implement a form layout that is of a more complex nature (that includes within itself some ajax calls for some of its field content - that depends on other fields). My question is: Do you think this is going to be practical without too much work making mods on the Rico code?

Julien Couvreur said...

Hum. The double scrollbar and inability to scroll with the keyboard are a big deal for me.

If you're interested, you can try out my Flickr mod (using Greasemonkey) to implement endless scrolling on the Flickr results:
http://blog.monstuff.com/archives/000336.html.

I also have an implementation for Google results.

Anonymous said...

Well Google has now a new paging and I HATE IT! So much for the calls for changes.