Mercurial > hg > soundsoftware-site
comparison lib/redmine/pagination.rb @ 1298:4f746d8966dd redmine_2.3_integration
Merge from redmine-2.3 branch to create new branch redmine-2.3-integration
| author | Chris Cannam |
|---|---|
| date | Fri, 14 Jun 2013 09:28:30 +0100 |
| parents | 622f24f53b42 |
| children | e248c7af89ec |
comparison
equal
deleted
inserted
replaced
| 1297:0a574315af3e | 1298:4f746d8966dd |
|---|---|
| 1 # encoding: utf-8 | |
| 2 # | |
| 3 # Redmine - project management software | |
| 4 # Copyright (C) 2006-2013 Jean-Philippe Lang | |
| 5 # | |
| 6 # This program is free software; you can redistribute it and/or | |
| 7 # modify it under the terms of the GNU General Public License | |
| 8 # as published by the Free Software Foundation; either version 2 | |
| 9 # of the License, or (at your option) any later version. | |
| 10 # | |
| 11 # This program is distributed in the hope that it will be useful, | |
| 12 # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 14 # GNU General Public License for more details. | |
| 15 # | |
| 16 # You should have received a copy of the GNU General Public License | |
| 17 # along with this program; if not, write to the Free Software | |
| 18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |
| 19 | |
| 20 module Redmine | |
| 21 module Pagination | |
| 22 class Paginator | |
| 23 attr_reader :item_count, :per_page, :page, :page_param | |
| 24 | |
| 25 def initialize(*args) | |
| 26 if args.first.is_a?(ActionController::Base) | |
| 27 args.shift | |
| 28 ActiveSupport::Deprecation.warn "Paginator no longer takes a controller instance as the first argument. Remove it from #new arguments." | |
| 29 end | |
| 30 item_count, per_page, page, page_param = *args | |
| 31 | |
| 32 @item_count = item_count | |
| 33 @per_page = per_page | |
| 34 page = (page || 1).to_i | |
| 35 if page < 1 | |
| 36 page = 1 | |
| 37 end | |
| 38 @page = page | |
| 39 @page_param = page_param || :page | |
| 40 end | |
| 41 | |
| 42 def offset | |
| 43 (page - 1) * per_page | |
| 44 end | |
| 45 | |
| 46 def first_page | |
| 47 if item_count > 0 | |
| 48 1 | |
| 49 end | |
| 50 end | |
| 51 | |
| 52 def previous_page | |
| 53 if page > 1 | |
| 54 page - 1 | |
| 55 end | |
| 56 end | |
| 57 | |
| 58 def next_page | |
| 59 if last_item < item_count | |
| 60 page + 1 | |
| 61 end | |
| 62 end | |
| 63 | |
| 64 def last_page | |
| 65 if item_count > 0 | |
| 66 (item_count - 1) / per_page + 1 | |
| 67 end | |
| 68 end | |
| 69 | |
| 70 def first_item | |
| 71 item_count == 0 ? 0 : (offset + 1) | |
| 72 end | |
| 73 | |
| 74 def last_item | |
| 75 l = first_item + per_page - 1 | |
| 76 l > item_count ? item_count : l | |
| 77 end | |
| 78 | |
| 79 def linked_pages | |
| 80 pages = [] | |
| 81 if item_count > 0 | |
| 82 pages += [first_page, page, last_page] | |
| 83 pages += ((page-2)..(page+2)).to_a.select {|p| p > first_page && p < last_page} | |
| 84 end | |
| 85 pages = pages.compact.uniq.sort | |
| 86 if pages.size > 1 | |
| 87 pages | |
| 88 else | |
| 89 [] | |
| 90 end | |
| 91 end | |
| 92 | |
| 93 def items_per_page | |
| 94 ActiveSupport::Deprecation.warn "Paginator#items_per_page will be removed. Use #per_page instead." | |
| 95 per_page | |
| 96 end | |
| 97 | |
| 98 def current | |
| 99 ActiveSupport::Deprecation.warn "Paginator#current will be removed. Use .offset instead of .current.offset." | |
| 100 self | |
| 101 end | |
| 102 end | |
| 103 | |
| 104 # Paginates the given scope or model. Returns a Paginator instance and | |
| 105 # the collection of objects for the current page. | |
| 106 # | |
| 107 # Options: | |
| 108 # :parameter name of the page parameter | |
| 109 # | |
| 110 # Examples: | |
| 111 # @user_pages, @users = paginate User.where(:status => 1) | |
| 112 # | |
| 113 def paginate(scope, options={}) | |
| 114 options = options.dup | |
| 115 finder_options = options.extract!( | |
| 116 :conditions, | |
| 117 :order, | |
| 118 :joins, | |
| 119 :include, | |
| 120 :select | |
| 121 ) | |
| 122 if scope.is_a?(Symbol) || finder_options.values.compact.any? | |
| 123 return deprecated_paginate(scope, finder_options, options) | |
| 124 end | |
| 125 | |
| 126 paginator = paginator(scope.count, options) | |
| 127 collection = scope.limit(paginator.per_page).offset(paginator.offset).to_a | |
| 128 | |
| 129 return paginator, collection | |
| 130 end | |
| 131 | |
| 132 def deprecated_paginate(arg, finder_options, options={}) | |
| 133 ActiveSupport::Deprecation.warn "#paginate with a Symbol and/or find options is depreceted and will be removed. Use a scope instead." | |
| 134 klass = arg.is_a?(Symbol) ? arg.to_s.classify.constantize : arg | |
| 135 scope = klass.scoped(finder_options) | |
| 136 paginate(scope, options) | |
| 137 end | |
| 138 | |
| 139 def paginator(item_count, options={}) | |
| 140 options.assert_valid_keys :parameter, :per_page | |
| 141 | |
| 142 page_param = options[:parameter] || :page | |
| 143 page = (params[page_param] || 1).to_i | |
| 144 per_page = options[:per_page] || per_page_option | |
| 145 Paginator.new(item_count, per_page, page, page_param) | |
| 146 end | |
| 147 | |
| 148 module Helper | |
| 149 include Redmine::I18n | |
| 150 | |
| 151 # Renders the pagination links for the given paginator. | |
| 152 # | |
| 153 # Options: | |
| 154 # :per_page_links if set to false, the "Per page" links are not rendered | |
| 155 # | |
| 156 def pagination_links_full(*args) | |
| 157 pagination_links_each(*args) do |text, parameters, options| | |
| 158 if block_given? | |
| 159 yield text, parameters, options | |
| 160 else | |
| 161 link_to text, params.merge(parameters), options | |
| 162 end | |
| 163 end | |
| 164 end | |
| 165 | |
| 166 # Yields the given block with the text and parameters | |
| 167 # for each pagination link and returns a string that represents the links | |
| 168 def pagination_links_each(paginator, count=nil, options={}, &block) | |
| 169 options.assert_valid_keys :per_page_links | |
| 170 | |
| 171 per_page_links = options.delete(:per_page_links) | |
| 172 per_page_links = false if count.nil? | |
| 173 page_param = paginator.page_param | |
| 174 | |
| 175 html = '' | |
| 176 if paginator.previous_page | |
| 177 # \xc2\xab(utf-8) = « | |
| 178 text = "\xc2\xab " + l(:label_previous) | |
| 179 html << yield(text, {page_param => paginator.previous_page}, :class => 'previous') + ' ' | |
| 180 end | |
| 181 | |
| 182 previous = nil | |
| 183 paginator.linked_pages.each do |page| | |
| 184 if previous && previous != page - 1 | |
| 185 html << content_tag('span', '...', :class => 'spacer') + ' ' | |
| 186 end | |
| 187 if page == paginator.page | |
| 188 html << content_tag('span', page.to_s, :class => 'current page') | |
| 189 else | |
| 190 html << yield(page.to_s, {page_param => page}, :class => 'page') | |
| 191 end | |
| 192 html << ' ' | |
| 193 previous = page | |
| 194 end | |
| 195 | |
| 196 if paginator.next_page | |
| 197 # \xc2\xbb(utf-8) = » | |
| 198 text = l(:label_next) + " \xc2\xbb" | |
| 199 html << yield(text, {page_param => paginator.next_page}, :class => 'next') + ' ' | |
| 200 end | |
| 201 | |
| 202 html << content_tag('span', "(#{paginator.first_item}-#{paginator.last_item}/#{paginator.item_count})", :class => 'items') + ' ' | |
| 203 | |
| 204 if per_page_links != false && links = per_page_links(paginator, &block) | |
| 205 html << content_tag('span', links.to_s, :class => 'per-page') | |
| 206 end | |
| 207 | |
| 208 html.html_safe | |
| 209 end | |
| 210 | |
| 211 # Renders the "Per page" links. | |
| 212 def per_page_links(paginator, &block) | |
| 213 values = per_page_options(paginator.per_page, paginator.item_count) | |
| 214 if values.any? | |
| 215 links = values.collect do |n| | |
| 216 if n == paginator.per_page | |
| 217 content_tag('span', n.to_s) | |
| 218 else | |
| 219 yield(n, :per_page => n, paginator.page_param => nil) | |
| 220 end | |
| 221 end | |
| 222 l(:label_display_per_page, links.join(', ')).html_safe | |
| 223 end | |
| 224 end | |
| 225 | |
| 226 def per_page_options(selected=nil, item_count=nil) | |
| 227 options = Setting.per_page_options_array | |
| 228 if item_count && options.any? | |
| 229 if item_count > options.first | |
| 230 max = options.detect {|value| value >= item_count} || item_count | |
| 231 else | |
| 232 max = item_count | |
| 233 end | |
| 234 options = options.select {|value| value <= max || value == selected} | |
| 235 end | |
| 236 if options.empty? || (options.size == 1 && options.first == selected) | |
| 237 [] | |
| 238 else | |
| 239 options | |
| 240 end | |
| 241 end | |
| 242 end | |
| 243 end | |
| 244 end |
