Transform traditional pagination into infinite scrolling which will automatically fetch more records when the user scrolls down to the bottom of the page.
Great screencast as usual, wondering though the following:
1) This is similar to the approach you showed in the sharing mustache templates screencast, wondering given that it essentially achieves the same objective when you would choose to use this simpler jquery approach vs using mustache template, ie what are the pros and cons of each.
2) any hints how one can test endless scrolling in rspec/capybara integration tests, specifically, any ideas as to how you would simulate a scroll near the bottom in capybara?
Nice revision. In fact, I am creating a web app for my company (unbeknownst to them) that connects to a legacy DB and one of our tables has hundreds of rows. This is going to look good on that page!
I am so glad I signed up for your Railscasts. Keep them coming!
I tried this for some reason. my index.js.erb is not being listened to but i see it on my terminal " Processing by BusinessesController#index as HTML" .
All the products (businesses) are being loaded at once. I am not sure what i'm missing, any ideas?
Nice an neat except for this trick with multiple scroll events being triggered. I think it would be much cleaner to unbind the scroll event till we get the results and once more products are loaded, bind it again.
You are right. Sometimes there where multiple ajax requests.
This script only fires one time, removes the eventlistener on scroll end adds it when finished.
I've wanted to implement this for some time now but had a few questions:
1) Should the URL change? i.e. /?page=2
2) What happens when you click a product then click back, are all the same products still loaded? I have seen this problem with a couple websites that use Endless Page.
Some people use pop-ups rather than going to another page. That seems to work fine. But if you really need to go to another page, then I'm not sure. I'll try this tonight.
I like endless scrolling except for one gotcha - it makes it very hard for users to access links on the page footer. One way to work around this is to use the jQuery Waypoints plugin to ensure that the footer is always displayed (despite the endless scrolling).
Thanks for sharing this ! It turns out there is a transition between the paginator pages line is being shown and removed for adding next page results. And my client complained a lot for this.
I have a respond_to block in the index action of my controller, so I had to add format.js to render the RJS template associated with this action (i.e. /app/views/products/index.js.erb):
Wow thank you @Barwin! I've been wrestling with this for the past 2 days and just couldn't figure out what I was doing wrong. I also had a respond_to block and just needed to pop in a format.js. Works like a champ.
I decided against the Endless Page feature, and instead slightly adapted this RailsCast's code to provide a "Show more results" link, which would append results in much the same manner, but instead by click rather than reached-bottom-of-page detection.
The main change is the addition of the prepend line in products.js.coffee:
products.js.coffee
jQuery ->
if $('.pagination').length
$('#append_and_paginate').prepend('<a id="append_more_results" href="javascript:void(0);">Show more products</a>');
$('#append_more_results').click ->
url = $('.pagination .next_page').attr('href')
if url
$('.pagination').text('Fetching more products...')
$.getScript(url)
Regarding the view, I only added a surrounding div:
And in products/index.js.erb I just changed the remove line to $('#append_and_paginate').remove(); so that both the "Show more results" link and pagination is removed when no more results are available.
Of course some css had to be added to make things look nice.
But anyway, the cool thing about this approach is that the "Show more products" link is only added by Javascript (hence only if Javascript is present and enabled). The click handler is bound to the DOM element with id="append_more_results", which is the id of the link tag that is prepended.
your method is really nice ,,,I tried it ,,but with internationalization ,,,its not working ,,,on console it gives me the get method for url is ok ..but no appending happens for pagination ...I am using kaminari so I replaced .next_page with .next a , and I used
your method is really nice ,,,I tried it ,,but with internationalization ,,,its not working ,,,on console it gives me the get method for url is ok ..but no appending happens for pagination ...I am using kaminari so , and I used
Thanks for this ryan, amazing as always!
I used this with Kaminari along with using a script to see if the pagination links are in the window view area (since I was working with a table that is in the middle of the page)
Coffee Script below:
I used @pages.current_page < @pages.num_pages since I couldn't get the @pages.next? method working with collections. Hopefully it will work in a future release.
Is there any way to use jQuery to filter items that are on next page or subsequent pages before you have scrolled to them? The use case would be a view of thumbnails that the user can scroll through with a list of tags above them that the user could use to narrow down the set of results. The problem I am having is not being able to return the correct results if the user has not scrolled down the page.
I guess Google would index the endless page as multiple pages (products?page=1, products?page=2) by following the links in the will_paginate nav.
If Google then directs a user to, say, /products?page=2 then that user would have no way to conveniently navigate to the content on page 1. Has anyone tried addressing this, perhaps with two-directional endless scrolling (when user scrolls near top of page we load in previous records if they exist), or by redirecting to page 1 if a JavaScript-enabled browser requests any other page?
@brucepom: Add rel="nofollow" to the pagination links, so Google will not index the paginated list. In addition, add a sitemap.xml to your site to tell Google the single pages.
I keep getting weird errors in rails 3 when using the render method. Also I don't have access to the instance variable. I wrote my issue on stack overflow if any you guys would have the time to have a look at my code. Please
Is there an issue with using render in rails 3 in js files?
Works great!
In chrome however it seems to 'stutter' or 'jump' when it loads more. I've removed all other css, trying to rule any wierdness out.
It does work perfectly in Firefox however. I disabled any extensions as well. Other sites like facebook.com or fab.com are super smooth in chrome, is this normal using this method?
Great screencast as usual, wondering though the following:
1) This is similar to the approach you showed in the sharing mustache templates screencast, wondering given that it essentially achieves the same objective when you would choose to use this simpler jquery approach vs using mustache template, ie what are the pros and cons of each.
2) any hints how one can test endless scrolling in rspec/capybara integration tests, specifically, any ideas as to how you would simulate a scroll near the bottom in capybara?
Nice revision. In fact, I am creating a web app for my company (unbeknownst to them) that connects to a legacy DB and one of our tables has hundreds of rows. This is going to look good on that page!
I am so glad I signed up for your Railscasts. Keep them coming!
I tried this for some reason. my index.js.erb is not being listened to but i see it on my terminal " Processing by BusinessesController#index as HTML" .
All the products (businesses) are being loaded at once. I am not sure what i'm missing, any ideas?
Interesting, i was appending a class instead on an id and that was causing the problem. I didn't think this mattered at all. Strange.
Nice an neat except for this trick with multiple scroll events being triggered. I think it would be much cleaner to unbind the scroll event till we get the results and once more products are loaded, bind it again.
You are right. Sometimes there where multiple ajax requests.
This script only fires one time, removes the eventlistener on scroll end adds it when finished.
This works with turbolinks.
onEndless = -> $(window).off 'scroll', onEndless url = $('.paginator .next a').attr('href') $('.paginator').hide() if url && $(window).scrollTop() > $(document).height() - $(window).height() - 150 $('.loader').show() $.getScript url, -> $(window).on 'scroll', onEndless else $(window).on 'scroll', onEndless $(window).on 'scroll', onEndless $(window).scroll()Railscast is the best $9 I spend every month. I would love to pay $50 and get one episode each weekday.
9$ is best for one month for me.. :) I assume that the price will be same in 10 years ;) But you should also denote Ryan for 50$.
Excellent episode Ryan, I really love the fallback functionality remaining intact. Definitely going to use this.
Couldn't agree more - love the thought that's gone into the fallback. Will be on my current project soon! :)
The main problem - how can i give a link to a some comment?
See http://railscasts.com/episodes/114-endless-page-revised?view=comments#comment_161528
I've wanted to implement this for some time now but had a few questions:
1) Should the URL change? i.e. /?page=2
2) What happens when you click a product then click back, are all the same products still loaded? I have seen this problem with a couple websites that use Endless Page.
Thanks
great question jDeppen; Ryan, or other commenters come across any solutions for question #2?
Id love to know as well.. the back button is problematic
Back button ... I'd like to know as well!
Some people use pop-ups rather than going to another page. That seems to work fine. But if you really need to go to another page, then I'm not sure. I'll try this tonight.
You can implement it with the history object, and it will solve problems with the back button, bookmarks etc.
I like endless scrolling except for one gotcha - it makes it very hard for users to access links on the page footer. One way to work around this is to use the jQuery Waypoints plugin to ensure that the footer is always displayed (despite the endless scrolling).
Static footers...if you really want it.
See this page about performance impacts of adding attaching a handler to window scroll: http://ejohn.org/blog/learning-from-twitter/
this is a good read on the subject, thanks for posting!
Thanks for sharing this ! It turns out there is a transition between the paginator pages line is being shown and removed for adding next page results. And my client complained a lot for this.
I have a
respond_toblock in the index action of my controller, so I had to addformat.jsto render the RJS template associated with this action (i.e./app/views/products/index.js.erb):Wow thank you @Barwin! I've been wrestling with this for the past 2 days and just couldn't figure out what I was doing wrong. I also had a respond_to block and just needed to pop in a
format.js. Works like a champ.+1
Thanks from me too! I wasn't close to finding a solution for this issue until I read your comment.
I decided against the Endless Page feature, and instead slightly adapted this RailsCast's code to provide a "Show more results" link, which would append results in much the same manner, but instead by click rather than reached-bottom-of-page detection.
The main change is the addition of the prepend line in
products.js.coffee:jQuery -> if $('.pagination').length $('#append_and_paginate').prepend('<a id="append_more_results" href="javascript:void(0);">Show more products</a>'); $('#append_more_results').click -> url = $('.pagination .next_page').attr('href') if url $('.pagination').text('Fetching more products...') $.getScript(url)Regarding the view, I only added a surrounding div:
And in
products/index.js.erbI just changed theremoveline to$('#append_and_paginate').remove();so that both the "Show more results" link and pagination is removed when no more results are available.Of course some css had to be added to make things look nice.
But anyway, the cool thing about this approach is that the "Show more products" link is only added by Javascript (hence only if Javascript is present and enabled). The click handler is bound to the DOM element with id="append_more_results", which is the id of the link tag that is prepended.
I like your approach. Thanks for sharing.
+1. nice alternative. Still prefer the endless scrolling feature for image heavy sites. So much easier to handle.
ah I was looking for this for half a day! :) Thank you!!
Thanks for posting this. Very useul.
your method is really nice ,,,I tried it ,,but with internationalization ,,,its not working ,,,on console it gives me the get method for url is ok ..but no appending happens for pagination ...I am using kaminari so I replaced .next_page with .next a , and I used
your method is really nice ,,,I tried it ,,but with internationalization ,,,its not working ,,,on console it gives me the get method for url is ok ..but no appending happens for pagination ...I am using kaminari so , and I used
I knew my problem now ...your idea is really cool and saved many days of search...
I used next_page with a ,,,but after adding 'a' its working now
Simple and useful.
Only feedback is that the products/index.js.erb in show notes is missing the sleep call.
Thanks for this ryan, amazing as always!
I used this with Kaminari along with using a script to see if the pagination links are in the window view area (since I was working with a table that is in the middle of the page)
Coffee Script below:
jQuery -> isScrolledIntoView = (elem) -> docViewTop = $(window).scrollTop() docViewBottom = docViewTop + $(window).height() elemTop = $(elem).offset().top elemBottom = elemTop + $(elem).height() (elemTop >= docViewTop) && (elemTop <= docViewBottom) if $('.pagination').length $(window).scroll -> url = $('.pagination .next_page a').attr('href') if url && isScrolledIntoView('.pagination') $('.pagination').text('Fetching more...') $.getScript(url) $(window).scroll()And in the index.js.erb file:
I used
@pages.current_page < @pages.num_pagessince I couldn't get the@pages.next?method working with collections. Hopefully it will work in a future release.Cheers Pranay.
In case anyone else is using Kaminari - you might need to change '.next_page' to '.next' :)
This was extremely helpful, @Pranay. Thanks!
I posted a question on Stack Overflow that is related to this episode. I'd be much obliged if anyone could provide some insight.
rails infinite scroll ajax actions on page > 1 items
Is there any way to use jQuery to filter items that are on next page or subsequent pages before you have scrolled to them? The use case would be a view of thumbnails that the user can scroll through with a list of tags above them that the user could use to narrow down the set of results. The problem I am having is not being able to return the correct results if the user has not scrolled down the page.
I guess Google would index the endless page as multiple pages (products?page=1, products?page=2) by following the links in the will_paginate nav.
If Google then directs a user to, say, /products?page=2 then that user would have no way to conveniently navigate to the content on page 1. Has anyone tried addressing this, perhaps with two-directional endless scrolling (when user scrolls near top of page we load in previous records if they exist), or by redirecting to page 1 if a JavaScript-enabled browser requests any other page?
@brucepom: Add rel="nofollow" to the pagination links, so Google will not index the paginated list. In addition, add a sitemap.xml to your site to tell Google the single pages.
I keep getting weird errors in rails 3 when using the render method. Also I don't have access to the instance variable. I wrote my issue on stack overflow if any you guys would have the time to have a look at my code. Please
Is there an issue with using render in rails 3 in js files?
Stackoverflow question
How can u get rid of the "page=1" on the url link?
Getting an error on this line (in the coffeescript file)
puts " if ($('.pagination').length) {"The error message says: Uncaught TypeError: Cannot read property 'length' of null
What could have gone wrong? The div exists in my index :(
Solved it...
Had to set jQuery to noConflict(), convert the script to jQuery and add it to a javascript file. Dunno why this happens though...
This approach doesn't seem to work on all mobile browsers. It worked in Chrome for iPhone, but not in Safari.
This was very helpful. Thanks!
Can partials be cached with this approach?
Works great!
In chrome however it seems to 'stutter' or 'jump' when it loads more. I've removed all other css, trying to rule any wierdness out.
It does work perfectly in Firefox however. I disabled any extensions as well. Other sites like facebook.com or fab.com are super smooth in chrome, is this normal using this method?
My mistake, I found that I was pulling an association in the partial, which wasn't included on the order method.
Updated to Book.order("name").includes(:authors) and it works like a charm! Way smoother.
doesnt work, wasted $9
sorry about my comment, I was very angry that day; it works fine and the vids are great
First sign in through GitHub to post a comment.