#114 Endless Page
Jun 16, 2008 | 8 minutes |
Ajax
Ever wondered how some sites seem to have endless scrolling page with no pagination? Find out how easy it is to do this in Rails in this episode.
- Download:
- mp4Full Size H.264 Video (14.3 MB)
- m4vSmaller H.264 Video (9.35 MB)
- webmFull Size VP8 Video (26.8 MB)
- ogvFull Size Theora Video (21.4 MB)
Hi Ryan,
I am always been a great fan of your railscast. Keep up the good work.
Nice implementation. I'll definitly be using this in the near future. Thanks
Hi Ryan.
Small question and answers.
What are advantages of the already created endless page plugin?
1)You don't need to install will_paginate or other page based long list implementation
2)You can configure your settings for each endless page independently. For example, you can set offset of 300px from bottom for one page and 100px for other if you want
3)You will have all your configuration in one place instead of set of 'magic integers' inside JS part of application
4)Workable in the IE, Opera and FF.
@all: we are living on the open source world. If you see something you don't like in the existing variant then just let me know and we can improve/fix it.
@Victor, good points. However, I usually avoid adding plugin dependencies unless it greatly simplifies my code. Here writing the implementation from scratch is nearly as simple as using a plugin. This way I understand the code better, and it's easier for me to customize to my specific needs.
That said, sometimes it's better to not reinvent the wheel. The fact that your plugin works out of the box in IE and Opera is a good example of the power behind using an existing, well tested implementation.
I encourage any developer to look at all the options out there and find the best one that fits the requirements for their application. Here I just give another option.
beautiful Ryan even tho I'm not gonna use this feature in my pages right now..but I know where to find it..
thanks again..
hey ryan, sounds like you've got a cold. if that's the case, feel better soon
that's a brilliant little implementation
I love the idea behind this but I'm concerned with SEO. The only way I can think about getting around it is to still have the pagination links but use css to hide them. Then the bots can follow the links to index the pages.
Any thoughts?
@Mike, yep, got a cold. Thanks. :)
@Jason, a similar concern is graceful degradation. If someone has javascript disabled they should still be able to access the next page. Keeping the pagination links might be a good idea, or at least the "next page" link.
Hi Ryan,
Sometimes knowing which pages are loaded are important from a statistcal pov. Using non-ajax pagination is my preference in those cases largely due to typically using client-side JS site stat tracking like Google Analytics.
Although it's relatively trivial to track statistics for action & param based server-side tracking eg /products?page=2 etc, does someone know if there is anyway to track these AJAX pagination calls using Google Analytics? Like a ping back or a function call in the .rjs response?
@Adam, doesn't Google Analytics provide some javascript to place on your site? Maybe you could send that javascript back in the RJS call. I haven't looked into it, but you'll probably need to add the URL to that JS to point to the requested page.
Hi Ryan,
What do you use to do the syntax coloring for the code samples you post in these examples? Does the Syntax gem do that?
Ah, CodeRay....
View source always helps, sorry bout that... :S
Its a good idea to focus on why auto-pagination is a good idea from a UI perspective. The default of numbered page links, while convenient for coding, imposes an interface using numbers that have no real meaning in terms of the data being reviewed. Page 4 is just an ordinal index to the data being presented. Rarely will you know how to find what you are looking for by using ordinal pagination of this type, particularly for VERY long lists, and for more modest lists, its simply an annoying interference with linear browsing through the table.
Auto paging interfaces, I think pioneered by Aza Raskin in his Humanized Reader, provides a more natural, more humane approach to browsing data. The list, if too long for sequential browsing may require additional effort, but ordinal pagination is not the right vehicle for that. Sorting filters of various kinds, or an index that has some semantic relationship with the data being searched/browsed is the way to go.
The only question is how to get it done. I'm astonished at how easy it was to do this.
Next step is to look at Raskin's admonition against using warning messages when what we really mean is to provide an undo function. Make that easy, and we have a truly killer framework.
Great presentation, Ryan. I hope this approach ris widely adopted, for it is truly A GOOD IDEA.
The window position code does indeed not work in IE6.
Here is some (hopefully) browser agnostic code to calculate how close to the bottom one is (using pageHeight() from the example):
var pos = pageHeight()-(document.viewport.getScrollOffsets()[1]+document.viewport.getHeight())
pos is the number pixels the bottom of the page is from being visible. A Negative number means your page is shorter the your browser window.
Just a follow up on the tracking of the statistics of the ajax pagination and hence more accurately see your site usage... I found an article at http://www.google.com/support/analytics/bin/answer.py?hl=en-nz&answer=55519 that explains how to do it if anyone has the same concerns.
Nice episode, Ryan. But your voice *does* sound strange :)
Someone wants this functionality on Twitter.com? Check out http://userscripts.org/scripts/show/24398
Just... a big up to Ryan for all his very quality AND FREE screencasts ! Not an error in my file or other... just thank you ! ;-)
An Happy RailsCasts Watcher.
Nice!
JQuery:
http://github.com/jney/jquery.pageless/tree/master/jquery.pageless.js
Looks like there is an error in the endless.js file
TypeError: Value undefined (result of expression document.observe) is not object.
Line 24:
document.observe('dom:loaded', checkScroll());
What could be wrong?
Thnx.
Sorry, previous post is not correct, this is what Firebug tells me:
document.observe is not a function
endless_page.js?1215380276()()
[document.observe('dom:loaded', checkScroll);
I ran into a little gotcha, well at least it was a gotcha for a noob like myself.
Results were not as intended, checked dev server and noticed a "406 Not Acceptable" error. A little research on Google provided: "406 Not Acceptable is for when the server cannot return the response body in any of the formats specified in the request's Accept header."
I then guessed that I needed to update my controller (built from scaffolding) to accept rjs and included a: format.js { render :rjs => @products }
Reload, refresh, and viola! Hope this helps any other Ruby & Rails noobies such as myself.
Excellent screencast Ryan
hi ryan,
sweetness once again...
but unfortunately it's not working in the IE because of the window.pageYOffset and the innerHeight. both returns undefined in IE. that's why i need to implement a browser switch in scrollDistanceFromBottom(). anyway. nice.
bless chris
my second impression is, that an endless list is nice, but it hides what we are scrolling. does the list contains bockwursts or plums or whatever... i mean the list header gets lost by scrolling.
an iframe thingie could be a solution?
best regards
chris
How would this work with caching?
Hi, i am implementing this for my applicatino, and seem to be running into some problems because my page is shorter then my browser window and i am getting some negative numbers, which activate the checkScroll function when it doesnt have to be. Anybody run into this same issue? Any ideas on how to solve this? Thanks in advance.
If this screencast is not enough, there is another screen cast over at http://www.railsillustrated.com/screencast-endless-page.html which uses a slightly different technique.
Ryan,
Any update on making this work in IE. It also did not work on safari/widnows for me.
Hi, love your screencast, but I am having trouble getting this to work.
I get the following error:
ActionView::TemplateError (undefined method `intern' for #<WillPaginate::Collection:0x262a7f8>) on line #1 of app/views/clientweb/list.rjs:
1: page.insert_html :bottom, :debtors, :partial => @debtors
2: if @debtors.total_pages > @debtors.current_page
3: page.call 'checkScroll'
4: else
Is this anything to do with WillPaginate versions? Any ideas?
I can't get any further with this, and it seems a shame if I have to abandon it.
Best regards.
Hi, I got past the above by amending the line to:
page.insert_html :bottom, :debtors, :partial => 'debtors', :collection => @debtors.
However, I don't think the checkScroll method is working at all.. it simply starts rendering all pages immediately - which also means its a very slow page load! I have tried altering the ScrollDistanceFromBottom to various values but it makes no difference.
Also the 'loading more results' never gets hidden.
For context, I am listing search results beneath a search form. I think that when the search form is submitted, the scroll is already near the bottom of the page - could this be the problem?
Any suggestions gratefully received.
Further to the above - what it appears to be doing is rendering the first page of results.. over and over again, 10 times.
(there are more than 10 pages of results so I'm not sure why this is).
So somehow the page parameter is being misused, or ignored altogether, by this method. Has anyone else had a similar problem?
What am I missing here?
In case it helps anyone else, here is a jQuery version of endless_page.js The jQuery version fixes the compatibility problem with IE as well.
Thank you willkoehler.
Can I by any chance make the scroll trigger horizontal?
if (nearRightOfPage)
or something similar? My I want my content to load as s but the trigger to be horizontal. Thanks.I got undefined method `javascript' when I follow along. It does not loke <% javascript :defaults, 'endless_page' %>. What is going on?
This episode has been updated to Rails 5 as a blog post Endless Page in Rails 5