diff options
author | Jean-Philippe Lang <jp_lang@yahoo.fr> | 2012-12-17 18:21:24 +0000 |
---|---|---|
committer | Jean-Philippe Lang <jp_lang@yahoo.fr> | 2012-12-17 18:21:24 +0000 |
commit | 1cf379f370def8e843975b5b7f0610207cac369b (patch) | |
tree | babd21e5bf7fac501dd6e51a849e369bcc21edd3 /lib/redmine/pagination.rb | |
parent | dfe2b6fbe982f1e0f8deb5da52b007634fb06384 (diff) | |
download | redmine-1cf379f370def8e843975b5b7f0610207cac369b.tar.gz redmine-1cf379f370def8e843975b5b7f0610207cac369b.zip |
Replaces the classic_pagination plugin with a simple pagination module.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@11026 e93f8b46-1217-0410-a6f0-8f06a7374b81
Diffstat (limited to 'lib/redmine/pagination.rb')
-rw-r--r-- | lib/redmine/pagination.rb | 221 |
1 files changed, 221 insertions, 0 deletions
diff --git a/lib/redmine/pagination.rb b/lib/redmine/pagination.rb new file mode 100644 index 000000000..055f9bc19 --- /dev/null +++ b/lib/redmine/pagination.rb @@ -0,0 +1,221 @@ +# encoding: utf-8 +# +# Redmine - project management software +# Copyright (C) 2006-2012 Jean-Philippe Lang +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +module Redmine + module Pagination + class Paginator + attr_reader :item_count, :per_page, :page, :page_param + + def initialize(*args) + if args.first.is_a?(ActionController::Base) + args.shift + ActiveSupport::Deprecation.warn "Paginator no longer takes a controller instance as the first argument. Remove it from #new arguments." + end + item_count, per_page, page, page_param = *args + + @item_count = item_count + @per_page = per_page + page = (page || 1).to_i + if page < 1 + page = 1 + end + @page = page + @page_param = page_param || :page + end + + def offset + (page - 1) * per_page + end + + def first_page + if item_count > 0 + 1 + end + end + + def previous_page + if page > 1 + page - 1 + end + end + + def next_page + if last_item < item_count + page + 1 + end + end + + def last_page + if item_count > 0 + (item_count - 1) / per_page + 1 + end + end + + def first_item + item_count == 0 ? 0 : (offset + 1) + end + + def last_item + l = first_item + per_page - 1 + l > item_count ? item_count : l + end + + def linked_pages + pages = [] + if item_count > 0 + pages += [first_page, page, last_page] + pages += ((page-2)..(page+2)).to_a.select {|p| p > first_page && p < last_page} + end + pages = pages.compact.uniq.sort + if pages.size > 1 + pages + else + [] + end + end + + def items_per_page + ActiveSupport::Deprecation.warn "Paginator#items_per_page will be removed. Use #per_page instead." + per_page + end + + def current + ActiveSupport::Deprecation.warn "Paginator#current will be removed. Use .offset instead of .current.offset." + self + end + end + + # Paginates the given scope or model. Returns a Paginator instance and + # the collection of objects for the current page. + # + # Options: + # :parameter name of the page parameter + # + # Examples: + # @user_pages, @users = paginate User.where(:status => 1) + # + def paginate(scope, options={}) + options = options.dup + finder_options = options.extract!( + :conditions, + :order, + :joins, + :include, + :select + ) + if scope.is_a?(Symbol) || finder_options.values.compact.any? + return deprecated_paginate(scope, finder_options, options) + end + + paginator = paginator(scope.count, options) + collection = scope.limit(paginator.per_page).offset(paginator.offset).to_a + + return paginator, collection + end + + def deprecated_paginate(arg, finder_options, options={}) + ActiveSupport::Deprecation.warn "#paginate with a Symbol and/or find options is depreceted and will be removed. Use a scope instead." + klass = arg.is_a?(Symbol) ? arg.to_s.classify.constantize : arg + scope = klass.scoped(finder_options) + paginate(scope, options) + end + + def paginator(item_count, options={}) + options.assert_valid_keys :parameter, :per_page + + page_param = options[:parameter] || :page + page = (params[page_param] || 1).to_i + per_page = options[:per_page] || per_page_option + Paginator.new(self, item_count, per_page, page, page_param) + end + + module Helper + include Redmine::I18n + + # Renders the pagination links for the given paginator. + # + # Options: + # :per_page_links if set to false, the "Per page" links are not rendered + # + def pagination_links_full(paginator, count=nil, options={}) + options.assert_valid_keys :per_page_links + + per_page_links = options.delete(:per_page_links) + per_page_links = false if count.nil? + page_param = paginator.page_param + url_param = params.dup + + html = '' + if paginator.previous_page + # \xc2\xab(utf-8) = « + html << link_to("\xc2\xab " + l(:label_previous), + url_param.merge(page_param => paginator.previous_page)) + ' ' + end + + previous = nil + paginator.linked_pages.each do |page| + if previous && previous != page - 1 + html << ' ... ' + end + if page == paginator.page + html << page.to_s + else + html << link_to(page.to_s, url_param.merge(page_param => page)) + end + html << ' ' + previous = page + end + + if paginator.next_page + # \xc2\xbb(utf-8) = » + html << ' ' + link_to(l(:label_next) + " \xc2\xbb", + url_param.merge(page_param => paginator.next_page)) + end + + html << " (#{paginator.first_item}-#{paginator.last_item}/#{paginator.item_count})" + + if per_page_links != false && links = per_page_links(paginator.per_page, paginator.item_count) + html << " | #{links}" + end + + html.html_safe + end + + # Renders the "Per page" links. + def per_page_links(selected=nil, item_count=nil) + values = Setting.per_page_options_array + if item_count && values.any? + if item_count > values.first + max = values.detect {|value| value >= item_count} || item_count + else + max = item_count + end + values = values.select {|value| value <= max || value == selected} + end + if values.empty? || (values.size == 1 && values.first == selected) + return nil + end + links = values.collect do |n| + n == selected ? n : link_to(n, params.merge(:per_page => n)) + end + l(:label_display_per_page, links.join(', ')) + end + end + end +end |