Turbolinks Infinite Scroll

Enviornment
Rails 6
Turbolinks
Kaminari
JQuery

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
class ProductsController < ApplicationController
def index
@products = Product.order(:name).page(params[:page])
end
end
class ProductsController < ApplicationController def index @products = Product.order(:name).page(params[:page]) end end
class ProductsController < ApplicationController
  def index
    @products = Product.order(:name).page(params[:page])
  end
end

Products table with pagination

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<table class="table table-bordered table-sm infinite-scroll">
<thead>
<tr>
<th>Name</th>
<th>UPC</th>
<th>Price</th>
</tr>
</thead>
<tbody>
<% @products.each do |product| %>
<tr>
<td>
<%= product.name %>
</td>
<td>
<%= product.upc %>
</td>
<td>
<%= product.retail_price.format %>
</td>
</tr>
<% end %>
</tbody>
</table>
<%= page_entries_info @products %>
<%= paginate @products %>
<table class="table table-bordered table-sm infinite-scroll"> <thead> <tr> <th>Name</th> <th>UPC</th> <th>Price</th> </tr> </thead> <tbody> <% @products.each do |product| %> <tr> <td> <%= product.name %> </td> <td> <%= product.upc %> </td> <td> <%= product.retail_price.format %> </td> </tr> <% end %> </tbody> </table> <%= page_entries_info @products %> <%= paginate @products %>
<table class="table table-bordered table-sm infinite-scroll">
  <thead>
    <tr>
      <th>Name</th>
      <th>UPC</th>
      <th>Price</th>
    </tr>
  </thead>
  <tbody>
    <% @products.each do |product| %>
      <tr>
        <td>
          <%= product.name %>
        </td>
        <td>
          <%= product.upc %>
        </td>
        <td>
          <%= product.retail_price.format %>
        </td>
      </tr>
    <% end %>
  </tbody>
</table>

<%= page_entries_info @products %>
<%= paginate @products %>

Wrapping the contents of #page_entries_info inside a CSS class

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
module ApplicationHelper
def page_entries_info(*)
tag.span(class: 'page-entries-info') { super }
end
end
module ApplicationHelper def page_entries_info(*) tag.span(class: 'page-entries-info') { super } end end
module ApplicationHelper
  def page_entries_info(*)
    tag.span(class: 'page-entries-info') { super }
  end
end

infinite-scroll.js

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
initInfiniteScroll = ->
$table = $('.infinite-scroll')
return if $table.length == 0
# Flag for request status
loading = false
# Hide the pagination
$('.page-entries-info, .pagination').hide()
# Add loading message to the bottom of the table
$table.after('<div class="alert alert-light text-center loading">LOADING...</div>')
handleScroll = ->
return if loading
# if next page link exists
if url = $('.pagination .page-link[rel=next]').attr('href')
if $(window).scrollTop() > $(document).height() - $(window).height() - 500
loading = true
ajax(url, {
headers:
# To get HTML response
'Accept' : 'text/html, application/xhtml+xml'
}).then((r) => r.text()).then (html) ->
$html = $('<html />').append(html)
# Append new records to the table
$table.find('tbody').append $html.find('tbody tr')
# Update pagination
$('.pagination').html $html.find('.pagination')
loading = false
else # no more pages to load
$(window).off('scroll', handleScroll)
$('.loading').remove()
$('.page-entries-info').show()
# show a message, when all the records are loaded
if $('.pagination').length > 0
pageTitle = document.getElementsByClassName('page-title')[0].innerText.toLowerCase()
totalRecords = $('.page-entries-info b:last').text()
$('.page-entries-info').html "Displaying <b>all #{totalRecords}</b> #{pageTitle}"
$(window).on('scroll', handleScroll)
handleScroll()
window.addEventListener 'turbolinks:load', ->
initInfiniteScroll()
# To prevent multiple scroll events on turbolinks:load
document.addEventListener 'turbolinks:before-render', ->
$(window).off('scroll')
initInfiniteScroll = -> $table = $('.infinite-scroll') return if $table.length == 0 # Flag for request status loading = false # Hide the pagination $('.page-entries-info, .pagination').hide() # Add loading message to the bottom of the table $table.after('<div class="alert alert-light text-center loading">LOADING...</div>') handleScroll = -> return if loading # if next page link exists if url = $('.pagination .page-link[rel=next]').attr('href') if $(window).scrollTop() > $(document).height() - $(window).height() - 500 loading = true ajax(url, { headers: # To get HTML response 'Accept' : 'text/html, application/xhtml+xml' }).then((r) => r.text()).then (html) -> $html = $('<html />').append(html) # Append new records to the table $table.find('tbody').append $html.find('tbody tr') # Update pagination $('.pagination').html $html.find('.pagination') loading = false else # no more pages to load $(window).off('scroll', handleScroll) $('.loading').remove() $('.page-entries-info').show() # show a message, when all the records are loaded if $('.pagination').length > 0 pageTitle = document.getElementsByClassName('page-title')[0].innerText.toLowerCase() totalRecords = $('.page-entries-info b:last').text() $('.page-entries-info').html "Displaying <b>all #{totalRecords}</b> #{pageTitle}" $(window).on('scroll', handleScroll) handleScroll() window.addEventListener 'turbolinks:load', -> initInfiniteScroll() # To prevent multiple scroll events on turbolinks:load document.addEventListener 'turbolinks:before-render', -> $(window).off('scroll')
initInfiniteScroll = ->
  $table = $('.infinite-scroll')
  return if $table.length == 0

  # Flag for request status
  loading = false
  
  # Hide the pagination
  $('.page-entries-info, .pagination').hide()
  
  # Add loading message to the bottom of the table
  $table.after('<div class="alert alert-light text-center loading">LOADING...</div>')

  handleScroll = ->
    return if loading

    # if next page link exists
    if url = $('.pagination .page-link[rel=next]').attr('href')
      if $(window).scrollTop() > $(document).height() - $(window).height() - 500
        loading = true

        ajax(url, {
          headers:
            # To get HTML response
            'Accept' : 'text/html, application/xhtml+xml'
        }).then((r) => r.text()).then (html) ->
          $html = $('<html />').append(html)
          # Append new records to the table
          $table.find('tbody').append $html.find('tbody tr')
          # Update pagination
          $('.pagination').html $html.find('.pagination')

          loading = false

    else # no more pages to load
      $(window).off('scroll', handleScroll)
      $('.loading').remove()
      $('.page-entries-info').show()

      # show a message, when all the records are loaded
      if $('.pagination').length > 0
        pageTitle = document.getElementsByClassName('page-title')[0].innerText.toLowerCase()
        totalRecords = $('.page-entries-info b:last').text()
        $('.page-entries-info').html "Displaying <b>all #{totalRecords}</b> #{pageTitle}"

  $(window).on('scroll', handleScroll)
  handleScroll()

window.addEventListener 'turbolinks:load', ->
  initInfiniteScroll()

# To prevent multiple scroll events on turbolinks:load
document.addEventListener 'turbolinks:before-render', ->
  $(window).off('scroll')

🙂