├── .gitignore ├── CHANGELOG.md ├── Gemfile ├── LICENSE ├── README.md ├── app └── assets │ └── javascripts │ └── jquery.infinite-pages.js.coffee ├── jquery-infinite-pages.gemspec └── lib ├── jquery-infinite-pages.rb └── jquery └── infinite_pages ├── engine.rb └── version.rb /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | *.gem 3 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | Ch-Ch-Ch-Changes 2 | ================ 3 | 4 | #### 0.2.0 (February 12, 2015) 5 | 6 | * Add context option to define scrolling container (thanks @pdw207) 7 | * Added coffee-script gem dependency (thanks @stgeneral) 8 | 9 | #### 0.1.2 (August 7, 2014) 10 | 11 | * Corrected possibly ambiguous coffeescript (thanks @crystalneth) 12 | 13 | #### 0.1.1 (April 14, 2014) 14 | 15 | * First release 16 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # Specify your gem's dependencies in redactor-rails.gemspec 4 | gemspec 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2014 Magoosh, Inc. http://magoosh.com 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | jQuery Infinite Pages 2 | ===================== 3 | 4 | [![Gem Version](https://badge.fury.io/rb/jquery-infinite-pages.svg)](http://badge.fury.io/rb/jquery-infinite-pages) 5 | 6 | A light-weight jQuery plugin for adding infinite scrolling to paginated HTML views 7 | that tastes great with [Rails](https://github.com/rails/rails) and 8 | [Kaminari](https://github.com/amatsuda/kaminari). 9 | 10 | This project was originally designed for Rails, but the core plugin is flexible 11 | enough to use anywhere. 12 | 13 | Installation 14 | ------------ 15 | 16 | Add this line to your application's `Gemfile`: 17 | ```ruby 18 | gem 'jquery-infinite-pages' 19 | ``` 20 | 21 | And then execute: 22 | ``` 23 | bundle install 24 | ``` 25 | 26 | Add to your `application.js` file: 27 | ```javascript 28 | //= require jquery.infinite-pages 29 | ``` 30 | 31 | ### Non-Rails 32 | 33 | Just copy the `jquery.infinite-pages.js.coffee` file from `app/assets/javascripts` to 34 | wherever you want it. 35 | 36 | Usage 37 | ----- 38 | jQuery Infinite Pages binds to an element containing a `rel="next"` pagination link and 39 | watches for scroll events. 40 | 41 | When the link is close to the bottom of the screen, an async request to the next page 42 | is triggered. The server's response should then append the new page and update the 43 | pagination link. 44 | 45 | ```coffeescript 46 | # Setup plugin and define optional event callbacks 47 | $('.infinite-table').infinitePages 48 | debug: true 49 | buffer: 200 # load new page when within 200px of nav link 50 | context: '.pane' # define the scrolling container (defaults to window) 51 | loading: -> 52 | # jQuery callback on the nav element 53 | $(this).text("Loading...") 54 | success: -> 55 | # called after successful ajax call 56 | error: -> 57 | # called after failed ajax call 58 | $(this).text("Trouble! Please drink some coconut water and click again") 59 | ``` 60 | 61 | You can also manually control the firing of load events: 62 | 63 | ```coffeescript 64 | # Force load of the next page 65 | $('.infinite-table').infinitePages('next') 66 | 67 | # Pause firing of events on scroll 68 | $('.infinite-table').infinitePages('pause') 69 | 70 | # Resume... 71 | $('.infinite-table').infinitePages('resume') 72 | ``` 73 | 74 | Rails/Kaminari Example 75 | ---------------------- 76 | 77 | The following is an example of how to integrate this plugin into your Rails app 78 | using Kaminari. 79 | 80 | Set up pagination in `lessons_controller.rb`: 81 | 82 | ```ruby 83 | class LessonsController 84 | def index 85 | @lessons = Lesson.order('lessons.name ASC').page(params[:page]) 86 | end 87 | end 88 | ``` 89 | 90 | Write the template for your list of lessons in `app/views/lessons/index.html.erb`: 91 | 92 | ```erb 93 |
94 | 95 | 96 | 97 | 98 | 99 | <%= render :partial => 'lessons', :object => @lessons %> 100 |
Lesson
101 |

102 | <%= link_to_next_page(@lessons, 'Next Page', :remote => true) %> 103 |

104 |
105 | ``` 106 | 107 | ...and `app/views/lessons/_lessons.html.erb`: 108 | 109 | ```erb 110 | <% @lessons.each do |lesson| %> 111 | 112 | <%= lesson.name %> (<%= lesson.length.format %>) 113 | <%= link_to "watch", lesson_path(lesson) %> 114 | 115 | <% end %> 116 | ``` 117 | 118 | Append new data to the table in `app/views/lessons/index.js.erb`: 119 | 120 | ```javascript 121 | // Append new data 122 | $("<%=j render(:partial => 'lessons', :object => @lessons) %>") 123 | .appendTo($(".infinite-table table")); 124 | 125 | // Update pagination link 126 | <% if @lessons.last_page? %> 127 | $('.pagination').html("That's all, folks!"); 128 | <% else %> 129 | $('.pagination') 130 | .html("<%=j link_to_next_page(@lessons, 'Next Page', :remote => true) %>"); 131 | <% end %> 132 | ``` 133 | 134 | At this point, the pagination link at the bottom of your table should allow you 135 | to load the next page without refreshing. Finally, we trigger the next page load 136 | with the `infinitePages` plugin in `app/assets/javascripts/lessons.js.coffee`: 137 | 138 | ```coffee 139 | $ -> 140 | # Configure infinite table 141 | $('.infinite-table').infinitePages 142 | # debug: true 143 | loading: -> 144 | $(this).text('Loading next page...') 145 | error: -> 146 | $(this).button('There was an error, please try again') 147 | ``` 148 | 149 | Voila! You should now have an infinitely long list of lessons. 150 | -------------------------------------------------------------------------------- /app/assets/javascripts/jquery.infinite-pages.js.coffee: -------------------------------------------------------------------------------- 1 | ### 2 | jQuery Infinite Pages v0.2.0 3 | https://github.com/magoosh/jquery-infinite-pages 4 | 5 | Released under the MIT License 6 | ### 7 | 8 | # 9 | # Built with a class-based template for jQuery plugins in Coffeescript: 10 | # https://gist.github.com/rjz/3610858 11 | # 12 | 13 | (($, window) -> 14 | # Define the plugin class 15 | class InfinitePages 16 | 17 | # Default settings 18 | defaults: 19 | debug: false # set to true to log messages to the console 20 | navSelector: 'a[rel=next]' 21 | buffer: 1000 # 1000px buffer by default 22 | loading: null # optional callback when next-page request begins 23 | success: null # optional callback when next-page request finishes 24 | error: null # optional callback when next-page request fails 25 | context: window # context to define the scrolling container 26 | state: 27 | paused: false 28 | loading: false 29 | 30 | # Constructs the new InfinitePages object 31 | # 32 | # container - the element containing the infinite table and pagination links 33 | constructor: (container, options) -> 34 | @options = $.extend({}, @defaults, options) 35 | @$container = $(container) 36 | @$table = $(container).find('table') 37 | @$context = $(@options.context) 38 | @init() 39 | 40 | # Setup and bind to related events 41 | init: -> 42 | 43 | # Debounce scroll event to improve performance 44 | scrollTimeout = null 45 | scrollHandler = (=> @check()) 46 | 47 | @$context.scroll -> 48 | if scrollTimeout 49 | clearTimeout(scrollTimeout) 50 | scrollTimeout = null 51 | scrollTimeout = setTimeout(scrollHandler, 250) 52 | 53 | # Internal helper for logging messages 54 | _log: (msg) -> 55 | console?.log(msg) if @options.debug 56 | 57 | # Check the distance of the nav selector from the bottom of the window and fire 58 | # load event if close enough 59 | check: -> 60 | nav = @$container.find(@options.navSelector) 61 | if nav.size() == 0 62 | @_log "No more pages to load" 63 | else 64 | windowBottom = @$context.scrollTop() + @$context.height() 65 | distance = nav.offset().top - windowBottom 66 | 67 | if @options.state.paused 68 | @_log "Paused" 69 | else if @options.state.loading 70 | @_log "Waiting..." 71 | else if (distance > @options.buffer) 72 | @_log "#{distance - @options.buffer}px remaining..." 73 | else 74 | @next() # load the next page 75 | 76 | # Load the next page 77 | next: -> 78 | if @options.state.done 79 | @_log "Loaded all pages" 80 | else 81 | @_loading() 82 | 83 | $.getScript(@$container.find(@options.navSelector).attr('href')) 84 | .done(=> @_success()) 85 | .fail(=> @_error()) 86 | 87 | _loading: -> 88 | @options.state.loading = true 89 | @_log "Loading next page..." 90 | if typeof @options.loading is 'function' 91 | @$container.find(@options.navSelector).each(@options.loading) 92 | 93 | _success: -> 94 | @options.state.loading = false 95 | @_log "New page loaded!" 96 | if typeof @options.success is 'function' 97 | @$container.find(@options.navSelector).each(@options.success) 98 | 99 | _error: -> 100 | @options.state.loading = false 101 | @_log "Error loading new page :(" 102 | if typeof @options.error is 'function' 103 | @$container.find(@options.navSelector).each(@options.error) 104 | 105 | # Pause firing of events on scroll 106 | pause: -> 107 | @options.state.paused = true 108 | @_log "Scroll checks paused" 109 | 110 | # Resume firing of events on scroll 111 | resume: -> 112 | @options.state.paused = false 113 | @_log "Scroll checks resumed" 114 | @check() 115 | 116 | # Define the plugin 117 | $.fn.extend infinitePages: (option, args...) -> 118 | @each -> 119 | $this = $(this) 120 | data = $this.data('infinitepages') 121 | 122 | if !data 123 | $this.data 'infinitepages', (data = new InfinitePages(this, option)) 124 | if typeof option == 'string' 125 | data[option].apply(data, args) 126 | 127 | ) window.jQuery, window 128 | -------------------------------------------------------------------------------- /jquery-infinite-pages.gemspec: -------------------------------------------------------------------------------- 1 | # -*- encoding: utf-8 -*- 2 | require File.expand_path('../lib/jquery/infinite_pages/version', __FILE__) 3 | 4 | Gem::Specification.new do |s| 5 | s.name = "jquery-infinite-pages" 6 | s.version = JqueryInfinitePages::VERSION 7 | s.licenses = ["MIT"] 8 | s.summary = "Infinite pages for jQuery + Rails" 9 | s.description = "A light-weight infinite scrolling jQuery plugin, wrapped in a gem for Rails" 10 | s.authors = ["Zach Millman"] 11 | s.email = ["zach@magoosh.com"] 12 | s.homepage = "https://github.com/magoosh/jquery-infinite-pages" 13 | s.files = Dir["{lib,app}/**/*"] + ["LICENSE", "README.md"] 14 | 15 | s.add_dependency "jquery-rails" 16 | s.add_dependency "coffee-script" 17 | s.add_dependency "railties", ">= 3.1" 18 | end 19 | -------------------------------------------------------------------------------- /lib/jquery-infinite-pages.rb: -------------------------------------------------------------------------------- 1 | require 'jquery/infinite_pages/version' 2 | require 'jquery/infinite_pages/engine' 3 | -------------------------------------------------------------------------------- /lib/jquery/infinite_pages/engine.rb: -------------------------------------------------------------------------------- 1 | module Jquery 2 | module InfinitePages 3 | class Engine < ::Rails::Engine 4 | end 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /lib/jquery/infinite_pages/version.rb: -------------------------------------------------------------------------------- 1 | module JqueryInfinitePages 2 | VERSION = "0.2.0" 3 | end 4 | --------------------------------------------------------------------------------