Permalink
Browse files

Create a paging solution to avoid loading everything at once

  • Loading branch information...
1 parent e0df724 commit 4327b3dd37809ae4b271a7fa2feeedff0a86aeb9 Matthew Ling committed Jul 31, 2011
View
2 .rvmrc
@@ -1 +1 @@
-rvm use ruby-1.9.2-p180@peopleofneworleans --create
+ rvm use ruby-1.9.2-p290@peopleofneworleans --create
View
@@ -14,6 +14,7 @@ gem "kaminari"
gem 'authlogic', :git => 'https://github.com/kreetitech/authlogic.git'
gem 'formtastic'
gem 'haml'
+gem 'will_paginate', '~> 3.0.pre4'
# Bundle gems for the local environment. Make sure to
# put test-only gems in this group so their generators
View
@@ -113,6 +113,7 @@ GEM
treetop (1.4.9)
polyglot (>= 0.3.1)
tzinfo (0.3.29)
+ will_paginate (3.0.pre4)
xml-simple (1.1.0)
PLATFORMS
@@ -138,3 +139,4 @@ DEPENDENCIES
ruby-openid
shoulda
sqlite3
+ will_paginate (~> 3.0.pre4)
@@ -3,16 +3,22 @@ class UsersController < ApplicationController
before_filter :require_user, :only => [:edit, :update, :destroy]
def index
- if params[:category]
- @users = User.find_by_category(params[:category]).shuffle
+ displayed_user_ids = params[:selected].blank? ? "()" : "(#{params[:selected]})"
+ unless params[:category].blank?
+ @users = User.get_page_by_category(params[:category], displayed_user_ids).shuffle.paginate(:page => 1, :per_page => Noladex::Application.config.page_size)
+ @number_of_users = User.find_by_category(params[:category]).size
else
- @users = User.includes(:missions => :category).all.shuffle
+ @number_of_users = User.count
+ @users = User.includes(:missions => :category).where("users.id not in #{displayed_user_ids}").shuffle.paginate(:page => 1, :per_page => Noladex::Application.config.page_size)
end
-
- respond_to do |format|
- format.html
- format.js
- format.xml { render :xml => @users }
+ if request.xhr?
+ render :partial => @users and return
+ else
+ respond_to do |format|
+ format.html
+ format.js
+ format.xml { render :xml => @users }
+ end
end
end
@@ -1,2 +1,3 @@
module ApplicationHelper
-end
+
+end
View
@@ -1,10 +1,13 @@
class User < ActiveRecord::Base
+ cattr_reader :per_page
+ @@per_page = Noladex::Application.config.page_size
+
acts_as_authentic do |c|
c.login_field :email
c.require_password_confirmation = false
end
-
+
has_many :missions
has_attached_file :avatar, {
:styles => { :medium => "300x300#" },
@@ -26,8 +29,16 @@ class User < ActiveRecord::Base
accepts_nested_attributes_for :missions, :reject_if => proc {|attributes| attributes['statement'].blank? }
- def self.find_by_category(category_id)
- includes(:missions => :category).where(["categories.id = ?", category_id])
+ class << self
+
+ def find_by_category(category_id)
+ includes(:missions => :category).where(["categories.id = ?", category_id])
+ end
+
+ def get_page_by_category(category_id, displayed_user_ids)
+ find_by_category(category_id).where("users.id not in #{displayed_user_ids}")
+ end
+
end
private
@@ -70,7 +70,7 @@
if params[:category]
@category = Category.find(params[:category])
@category_name = @category.name if !@category.nil?
- @count = User.find_by_category(params[:category]).size
+ @count = @number_of_users
else
@count = User.all().size
end
@@ -106,7 +106,8 @@
</div>
</footer>
- <%= javascript_include_tag "jquery.min", "jquery_ujs", "plugins", "noladex.js" %>
+ <%= javascript_include_tag "jquery.min", "jquery_ujs", "plugins", "noladex.js", "jquery.pageless" %>
+ <%= yield :javascript %>
</body>
</html>
@@ -1 +0,0 @@
-<%= render @users %>
@@ -0,0 +1,27 @@
+- content_for :javascript do
+ :javascript
+ opts = {
+ totalPages : "#{(@number_of_users % Noladex::Application.config.page_size) > 0 ? (@number_of_users / Noladex::Application.config.page_size) + 1 : (@number_of_users / Noladex::Application.config.page_size)}",
+ url : '/users',
+ loaderMsg : 'Getting more noladexers',
+ params : {
+ selected : $('#selected_noladexers').val(),
+ category : "#{params[:category]}"
+ },
+ scrape : function(data) {
+ alreadySelected = $('#selected_noladexers').val().split(',')
+ $(data).siblings("div.person").each(function(index) {
+ newId = parseInt($(this).attr("id").split("-")[1]);
+ alreadySelected.push(newId);
+ });
+ $('#selected_noladexers').val(alreadySelected.join(','));
+ }
+ }
+ $('#people').pageless(opts);
+
+= semantic_form_for :selected do |f|
+ = f.hidden_field :noladexers, :value => @users.map {|u| u.id}.join(',')
+
+= render @users
+
+= will_paginate @users
View
@@ -44,6 +44,7 @@ class Application < Rails::Application
config.middleware.use 'Rack::OpenID'
config.mailer_host = "http://localhost:3000"
+
+ config.page_size = 9
end
-end
-
+end
View
Binary file not shown.
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
@@ -0,0 +1,180 @@
+// =======================================================================
+// PageLess - endless page
+//
+// Pageless is a jQuery plugin.
+// As you scroll down you see more results coming back at you automatically.
+// It provides an automatic pagination in an accessible way : if javascript
+// is disabled your standard pagination is supposed to work.
+//
+// Licensed under the MIT:
+// http://www.opensource.org/licenses/mit-license.php
+//
+// Parameters:
+// currentPage: current page (params[:page])
+// distance: distance to the end of page in px when ajax query is fired
+// loader: selector of the loader div (ajax activity indicator)
+// loaderHtml: html code of the div if loader not used
+// loaderImage: image inside the loader
+// loaderMsg: displayed ajax message
+// pagination: selector of the paginator divs.
+// if javascript is disabled paginator is provided
+// params: paramaters for the ajax query, you can pass auth_token here
+// totalPages: total number of pages
+// url: URL used to request more data
+//
+// Callback Parameters:
+// scrape: A function to modify the incoming data.
+// complete: A function to call when a new page has been loaded (optional)
+// end: A function to call when the last page has been loaded (optional)
+//
+// Usage:
+// $('#results').pageless({ totalPages: 10
+// , url: '/articles/'
+// , loaderMsg: 'Loading more results'
+// });
+//
+// Requires: jquery
+//
+// Author: Jean-Sébastien Ney (https://github.com/jney)
+//
+// Contributors:
+// Alexander Lang (https://github.com/langalex)
+// Lukas Rieder (https://github.com/Overbryd)
+//
+// Thanks to:
+// * codemonky.com/post/34940898
+// * www.unspace.ca/discover/pageless/
+// * famspam.com/facebox
+// =======================================================================
+
+(function($) {
+
+ var FALSE = !1
+ , TRUE = !FALSE
+ , element
+ , isLoading = FALSE
+ , loader
+ , namespace = '.pageless'
+ , SCROLL = 'scroll' + namespace
+ , RESIZE = 'resize' + namespace
+ , settings = { container: window
+ , currentPage: 1
+ , distance: 100
+ , pagination: '.pagination'
+ , params: {}
+ , url: location.href
+ , loaderImage: "/images/load.gif"
+ }
+ , container
+ , $container;
+
+ $.pageless = function(opts) {
+ $.isFunction(opts) ? settings.call() : init(opts);
+ };
+
+ var loaderHtml = function () {
+ return settings.loaderHtml || '\
+<div id="pageless-loader" style="display:none;text-align:center;width:100%;">\
+ <div class="msg" style="color:#e9e9e9;font-size:2em"></div>\
+ <img src="' + settings.loaderImage + '" alt="loading more results" style="margin:10px auto" />\
+</div>';
+ };
+
+ // settings params: totalPages
+ var init = function (opts) {
+ if (settings.inited) return;
+ settings.inited = TRUE;
+
+ if (opts) $.extend(settings, opts);
+
+ container = settings.container;
+ $container = $(container);
+
+ // for accessibility we can keep pagination links
+ // but since we have javascript enabled we remove pagination links
+ if(settings.pagination) $(settings.pagination).remove();
+
+ // start the listener
+ startListener();
+ };
+
+ $.fn.pageless = function (opts) {
+ var $el = $(this)
+ , $loader = $(opts.loader, $el);
+
+ init(opts);
+ element = $el;
+
+ // loader element
+ if (opts.loader && $loader.length) {
+ loader = $loader;
+ } else {
+ loader = $(loaderHtml());
+ $el.append(loader);
+ // if we use the default loader, set the message
+ if (!opts.loaderHtml) {
+ $('#pageless-loader .msg').html(opts.loaderMsg);
+ }
+ }
+ };
+
+ //
+ var loading = function (bool) {
+ (isLoading = bool)
+ ? (loader && loader.fadeIn('normal'))
+ : (loader && loader.fadeOut('normal'));
+ };
+
+ // distance to end of the container
+ var distanceToBottom = function () {
+ return (container === window)
+ ? $(document).height()
+ - $container.scrollTop()
+ - $container.height()
+ : $container[0].scrollHeight
+ - $container.scrollTop()
+ - $container.height();
+ };
+
+ var stopListener = function() {
+ $container.unbind(namespace);
+ };
+
+ // * bind a scroll event
+ // * trigger is once in case of reload
+ var startListener = function() {
+ $container.bind(SCROLL+' '+RESIZE, watch)
+ .trigger(SCROLL);
+ };
+
+ var watch = function() {
+ // listener was stopped or we've run out of pages
+ if (settings.totalPages <= settings.currentPage) {
+ stopListener();
+ // if there is a afterStopListener callback we call it
+ if (settings.end) settings.end.call();
+ return;
+ }
+
+ // if slider past our scroll offset, then fire a request for more data ...
+ if(!isLoading && (distanceToBottom() < settings.distance)) {
+ loading(TRUE);
+ // move to next page
+ settings.currentPage++;
+ // set up ajax query params
+ $.extend(settings.params, {selected: $('#selected_noladexers').val()});
+ $.extend( settings.params
+ , { page: settings.currentPage });
+ // finally ajax query
+ $.get( settings.url
+ , settings.params
+ , function (data) {
+ $.isFunction(settings.scrape) ? settings.scrape(data) : data;
+ loader ? loader.before(data) : element.append(data);
+ loading(FALSE);
+ // if there is a complete callback we call it
+ if (settings.complete) settings.complete.call();
+ }, 'html');
+ }
+ };
+})(jQuery);

0 comments on commit 4327b3d

Please sign in to comment.