will_paginate 2.3.17 → 3.0.pre
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of will_paginate might be problematic. Click here for more details.
- data/CHANGELOG.rdoc +24 -80
- data/LICENSE +1 -1
- data/README.rdoc +125 -0
- data/Rakefile +26 -22
- data/lib/will_paginate.rb +10 -84
- data/lib/will_paginate/array.rb +25 -8
- data/lib/will_paginate/collection.rb +15 -28
- data/lib/will_paginate/core_ext.rb +26 -0
- data/lib/will_paginate/deprecation.rb +50 -0
- data/lib/will_paginate/finders.rb +9 -0
- data/lib/will_paginate/finders/active_record.rb +158 -0
- data/lib/will_paginate/finders/active_resource.rb +51 -0
- data/lib/will_paginate/finders/base.rb +112 -0
- data/lib/will_paginate/finders/data_mapper.rb +30 -0
- data/lib/will_paginate/finders/sequel.rb +23 -0
- data/lib/will_paginate/railtie.rb +26 -0
- data/lib/will_paginate/version.rb +5 -5
- data/lib/will_paginate/view_helpers.rb +25 -436
- data/lib/will_paginate/view_helpers/action_view.rb +142 -0
- data/lib/will_paginate/view_helpers/base.rb +126 -0
- data/lib/will_paginate/view_helpers/link_renderer.rb +130 -0
- data/lib/will_paginate/view_helpers/link_renderer_base.rb +83 -0
- data/lib/will_paginate/view_helpers/merb.rb +13 -0
- data/spec/collection_spec.rb +147 -0
- data/spec/console +8 -0
- data/spec/console_fixtures.rb +8 -0
- data/spec/database.yml +22 -0
- data/spec/finders/active_record_spec.rb +377 -0
- data/spec/finders/active_resource_spec.rb +52 -0
- data/spec/finders/activerecord_test_connector.rb +114 -0
- data/spec/finders/data_mapper_spec.rb +62 -0
- data/spec/finders/data_mapper_test_connector.rb +20 -0
- data/spec/finders/sequel_spec.rb +53 -0
- data/spec/finders/sequel_test_connector.rb +9 -0
- data/spec/finders_spec.rb +76 -0
- data/{test → spec}/fixtures/admin.rb +0 -0
- data/{test → spec}/fixtures/developer.rb +2 -3
- data/{test → spec}/fixtures/developers_projects.yml +0 -0
- data/{test → spec}/fixtures/project.rb +2 -6
- data/{test → spec}/fixtures/projects.yml +1 -1
- data/{test → spec}/fixtures/replies.yml +0 -0
- data/{test → spec}/fixtures/reply.rb +1 -1
- data/{test → spec}/fixtures/schema.rb +0 -0
- data/spec/fixtures/topic.rb +7 -0
- data/{test → spec}/fixtures/topics.yml +0 -0
- data/{test → spec}/fixtures/user.rb +0 -0
- data/{test → spec}/fixtures/users.yml +0 -0
- data/spec/rcov.opts +2 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +74 -0
- data/spec/tasks.rake +60 -0
- data/spec/view_helpers/action_view_spec.rb +345 -0
- data/spec/view_helpers/base_spec.rb +64 -0
- data/spec/view_helpers/link_renderer_base_spec.rb +84 -0
- data/spec/view_helpers/view_example_group.rb +103 -0
- metadata +60 -65
- data/README.md +0 -53
- data/lib/will_paginate/finder.rb +0 -269
- data/lib/will_paginate/i18n.rb +0 -29
- data/lib/will_paginate/locale/en.yml +0 -33
- data/lib/will_paginate/named_scope.rb +0 -170
- data/lib/will_paginate/named_scope_patch.rb +0 -37
- data/lib/will_paginate/per_page.rb +0 -27
- data/test/ci.rb +0 -60
- data/test/collection_test.rb +0 -160
- data/test/console +0 -8
- data/test/database.yml +0 -16
- data/test/finder_test.rb +0 -527
- data/test/fixtures/topic.rb +0 -12
- data/test/gemfiles/Gemfile.1.2 +0 -13
- data/test/gemfiles/Gemfile.1.2.lock +0 -39
- data/test/gemfiles/Gemfile.2.0 +0 -16
- data/test/gemfiles/Gemfile.2.0.lock +0 -28
- data/test/gemfiles/Gemfile.2.1 +0 -16
- data/test/gemfiles/Gemfile.2.1.lock +0 -28
- data/test/gemfiles/Gemfile.2.2 +0 -16
- data/test/gemfiles/Gemfile.2.2.lock +0 -28
- data/test/helper.rb +0 -34
- data/test/lib/activerecord_test_case.rb +0 -38
- data/test/lib/activerecord_test_connector.rb +0 -86
- data/test/lib/load_fixtures.rb +0 -12
- data/test/lib/view_test_process.rb +0 -186
- data/test/view_test.rb +0 -380
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'will_paginate/finders/base'
|
2
|
+
require 'dm-core'
|
3
|
+
|
4
|
+
module WillPaginate::Finders
|
5
|
+
module DataMapper
|
6
|
+
include WillPaginate::Finders::Base
|
7
|
+
|
8
|
+
protected
|
9
|
+
|
10
|
+
def wp_query(options, pager, args, &block) #:nodoc
|
11
|
+
find_options = options.except(:count).update(:offset => pager.offset, :limit => pager.per_page)
|
12
|
+
|
13
|
+
pager.replace all(find_options, &block)
|
14
|
+
|
15
|
+
unless pager.total_entries
|
16
|
+
pager.total_entries = wp_count(options)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def wp_count(options) #:nodoc
|
21
|
+
count_options = options.except(:count, :order)
|
22
|
+
# merge the hash found in :count
|
23
|
+
count_options.update options[:count] if options[:count]
|
24
|
+
|
25
|
+
count_options.empty?? count() : count(count_options)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
DataMapper::Model.send(:include, WillPaginate::Finders::DataMapper)
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'will_paginate/core_ext'
|
2
|
+
require 'sequel'
|
3
|
+
require 'sequel/extensions/pagination'
|
4
|
+
|
5
|
+
existing_methods = Sequel::Dataset::Pagination.instance_methods
|
6
|
+
|
7
|
+
Sequel::Dataset::Pagination.module_eval do
|
8
|
+
# it should quack like a WillPaginate::Collection
|
9
|
+
|
10
|
+
alias :total_pages :page_count unless existing_methods.include_method? :total_pages
|
11
|
+
alias :per_page :page_size unless existing_methods.include_method? :per_page
|
12
|
+
alias :previous_page :prev_page unless existing_methods.include_method? :previous_page
|
13
|
+
alias :total_entries :pagination_record_count unless existing_methods.include_method? :total_entries
|
14
|
+
|
15
|
+
def out_of_bounds?
|
16
|
+
current_page > total_pages
|
17
|
+
end
|
18
|
+
|
19
|
+
# Current offset of the paginated collection
|
20
|
+
def offset
|
21
|
+
(current_page - 1) * per_page
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'will_paginate'
|
2
|
+
require 'will_paginate/collection'
|
3
|
+
|
4
|
+
module WillPaginate
|
5
|
+
class Railtie < Rails::Railtie
|
6
|
+
railtie_name :will_paginate
|
7
|
+
|
8
|
+
initializer "will_paginate.active_record" do |app|
|
9
|
+
if defined? ::ActiveRecord
|
10
|
+
require 'will_paginate/finders/active_record'
|
11
|
+
WillPaginate::Finders::ActiveRecord.enable!
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
initializer "will_paginate.action_dispatch" do |app|
|
16
|
+
if defined? ::ActionDispatch::ShowExceptions
|
17
|
+
ActionDispatch::ShowExceptions.rescue_responses['WillPaginate::InvalidPage'] = :not_found
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
initializer "will_paginate.action_view" do |app|
|
22
|
+
require 'will_paginate/view_helpers/action_view'
|
23
|
+
ActionView::Base.send(:include, WillPaginate::ViewHelpers::ActionView)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -1,453 +1,42 @@
|
|
1
|
-
require 'will_paginate/
|
2
|
-
require 'will_paginate/i18n'
|
1
|
+
require 'will_paginate/deprecation'
|
3
2
|
|
4
3
|
module WillPaginate
|
5
4
|
# = Will Paginate view helpers
|
6
5
|
#
|
7
|
-
# The main view helper
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
6
|
+
# The main view helper is +will_paginate+. It renders the pagination links
|
7
|
+
# for the given collection. The helper itself is lightweight and serves only
|
8
|
+
# as a wrapper around LinkRenderer instantiation; the renderer then does
|
9
|
+
# all the hard work of generating the HTML.
|
11
10
|
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
# Options for pagination helpers are optional and get their default values from the
|
15
|
-
# <tt>WillPaginate::ViewHelpers.pagination_options</tt> hash. You can write to this hash to
|
16
|
-
# override default options on the global level:
|
17
|
-
#
|
18
|
-
# WillPaginate::ViewHelpers.pagination_options[:previous_label] = 'Previous page'
|
19
|
-
#
|
20
|
-
# By putting this into "config/initializers/will_paginate.rb" (or simply environment.rb in
|
21
|
-
# older versions of Rails) you can easily translate link texts to previous
|
22
|
-
# and next pages, as well as override some other defaults to your liking.
|
11
|
+
# Read more in WillPaginate::ViewHelpers::Base
|
23
12
|
module ViewHelpers
|
24
|
-
|
25
|
-
|
26
|
-
#
|
27
|
-
|
13
|
+
# ==== Global options for helpers
|
14
|
+
#
|
15
|
+
# Options for pagination helpers are optional and get their default values
|
16
|
+
# from the WillPaginate::ViewHelpers.pagination_options hash. You can write
|
17
|
+
# to this hash to override default options on the global level:
|
18
|
+
#
|
19
|
+
# WillPaginate::ViewHelpers.pagination_options[:previous_label] = 'Previous page'
|
20
|
+
#
|
21
|
+
# By putting this into your environment.rb you can easily translate link
|
22
|
+
# texts to previous and next pages, as well as override some other defaults
|
23
|
+
# to your liking.
|
24
|
+
def self.pagination_options() @pagination_options; end
|
25
|
+
# Overrides the default +pagination_options+
|
26
|
+
def self.pagination_options=(value) @pagination_options = value; end
|
27
|
+
|
28
|
+
self.pagination_options = {
|
28
29
|
:class => 'pagination',
|
29
|
-
:previous_label =>
|
30
|
-
:next_label =>
|
30
|
+
:previous_label => '← Previous',
|
31
|
+
:next_label => 'Next →',
|
31
32
|
:inner_window => 4, # links around the current page
|
32
33
|
:outer_window => 1, # links around beginning and end
|
33
34
|
:separator => ' ', # single space is friendly to spiders and non-graphic browsers
|
34
35
|
:param_name => :page,
|
35
36
|
:params => nil,
|
36
|
-
:renderer => 'WillPaginate::LinkRenderer',
|
37
|
+
:renderer => 'WillPaginate::ViewHelpers::LinkRenderer',
|
37
38
|
:page_links => true,
|
38
39
|
:container => true
|
39
40
|
}
|
40
|
-
mattr_reader :pagination_options
|
41
|
-
|
42
|
-
# Renders Digg/Flickr-style pagination for a WillPaginate::Collection
|
43
|
-
# object. Nil is returned if there is only one page in total; no point in
|
44
|
-
# rendering the pagination in that case...
|
45
|
-
#
|
46
|
-
# ==== Options
|
47
|
-
# Display options:
|
48
|
-
# * <tt>:previous_label</tt> -- default: "« Previous" (this parameter is called <tt>:prev_label</tt> in versions <b>2.3.2</b> and older!)
|
49
|
-
# * <tt>:next_label</tt> -- default: "Next »"
|
50
|
-
# * <tt>:page_links</tt> -- when false, only previous/next links are rendered (default: true)
|
51
|
-
# * <tt>:inner_window</tt> -- how many links are shown around the current page (default: 4)
|
52
|
-
# * <tt>:outer_window</tt> -- how many links are around the first and the last page (default: 1)
|
53
|
-
# * <tt>:separator</tt> -- string separator for page HTML elements (default: single space)
|
54
|
-
#
|
55
|
-
# HTML options:
|
56
|
-
# * <tt>:class</tt> -- CSS class name for the generated DIV (default: "pagination")
|
57
|
-
# * <tt>:container</tt> -- toggles rendering of the DIV container for pagination links, set to
|
58
|
-
# false only when you are rendering your own pagination markup (default: true)
|
59
|
-
# * <tt>:id</tt> -- HTML ID for the container (default: nil). Pass +true+ to have the ID
|
60
|
-
# automatically generated from the class name of objects in collection: for example, paginating
|
61
|
-
# ArticleComment models would yield an ID of "article_comments_pagination".
|
62
|
-
#
|
63
|
-
# Advanced options:
|
64
|
-
# * <tt>:param_name</tt> -- parameter name for page number in URLs (default: <tt>:page</tt>)
|
65
|
-
# * <tt>:params</tt> -- additional parameters when generating pagination links
|
66
|
-
# (eg. <tt>:controller => "foo", :action => nil</tt>)
|
67
|
-
# * <tt>:renderer</tt> -- class name, class or instance of a link renderer (default:
|
68
|
-
# <tt>WillPaginate::LinkRenderer</tt>)
|
69
|
-
#
|
70
|
-
# All options not recognized by will_paginate will become HTML attributes on the container
|
71
|
-
# element for pagination links (the DIV). For example:
|
72
|
-
#
|
73
|
-
# <%= will_paginate @posts, :style => 'font-size: small' %>
|
74
|
-
#
|
75
|
-
# ... will result in:
|
76
|
-
#
|
77
|
-
# <div class="pagination" style="font-size: small"> ... </div>
|
78
|
-
#
|
79
|
-
# ==== Using the helper without arguments
|
80
|
-
# If the helper is called without passing in the collection object, it will
|
81
|
-
# try to read from the instance variable inferred by the controller name.
|
82
|
-
# For example, calling +will_paginate+ while the current controller is
|
83
|
-
# PostsController will result in trying to read from the <tt>@posts</tt>
|
84
|
-
# variable. Example:
|
85
|
-
#
|
86
|
-
# <%= will_paginate :id => true %>
|
87
|
-
#
|
88
|
-
# ... will result in <tt>@post</tt> collection getting paginated:
|
89
|
-
#
|
90
|
-
# <div class="pagination" id="posts_pagination"> ... </div>
|
91
|
-
#
|
92
|
-
def will_paginate(collection = nil, options = {})
|
93
|
-
options, collection = collection, nil if collection.is_a? Hash
|
94
|
-
unless collection or !controller
|
95
|
-
collection_name = "@#{controller.controller_name}"
|
96
|
-
collection = instance_variable_get(collection_name)
|
97
|
-
raise ArgumentError, "The #{collection_name} variable appears to be empty. Did you " +
|
98
|
-
"forget to pass the collection object for will_paginate?" unless collection
|
99
|
-
end
|
100
|
-
# early exit if there is nothing to render
|
101
|
-
return nil unless WillPaginate::ViewHelpers.total_pages_for_collection(collection) > 1
|
102
|
-
|
103
|
-
options = options.symbolize_keys.reverse_merge WillPaginate::ViewHelpers.pagination_options
|
104
|
-
if options[:prev_label]
|
105
|
-
WillPaginate::Deprecation::warn(":prev_label view parameter is now :previous_label; the old name has been deprecated", caller)
|
106
|
-
options[:previous_label] = options.delete(:prev_label)
|
107
|
-
end
|
108
|
-
|
109
|
-
options[:previous_label] ||= will_paginate_translate(:previous_label) { '« Previous' }
|
110
|
-
options[:next_label] ||= will_paginate_translate(:next_label) { 'Next »' }
|
111
|
-
|
112
|
-
# get the renderer instance
|
113
|
-
renderer = case options[:renderer]
|
114
|
-
when String
|
115
|
-
options[:renderer].to_s.constantize.new
|
116
|
-
when Class
|
117
|
-
options[:renderer].new
|
118
|
-
else
|
119
|
-
options[:renderer]
|
120
|
-
end
|
121
|
-
# render HTML for pagination
|
122
|
-
renderer.prepare collection, options, self
|
123
|
-
renderer.to_html
|
124
|
-
end
|
125
|
-
|
126
|
-
# Wrapper for rendering pagination links at both top and bottom of a block
|
127
|
-
# of content.
|
128
|
-
#
|
129
|
-
# <% paginated_section @posts do %>
|
130
|
-
# <ol id="posts">
|
131
|
-
# <% for post in @posts %>
|
132
|
-
# <li> ... </li>
|
133
|
-
# <% end %>
|
134
|
-
# </ol>
|
135
|
-
# <% end %>
|
136
|
-
#
|
137
|
-
# will result in:
|
138
|
-
#
|
139
|
-
# <div class="pagination"> ... </div>
|
140
|
-
# <ol id="posts">
|
141
|
-
# ...
|
142
|
-
# </ol>
|
143
|
-
# <div class="pagination"> ... </div>
|
144
|
-
#
|
145
|
-
# Arguments are passed to a <tt>will_paginate</tt> call, so the same options
|
146
|
-
# apply. Don't use the <tt>:id</tt> option; otherwise you'll finish with two
|
147
|
-
# blocks of pagination links sharing the same ID (which is invalid HTML).
|
148
|
-
def paginated_section(*args, &block)
|
149
|
-
pagination = will_paginate(*args).to_s
|
150
|
-
|
151
|
-
if respond_to? :output_buffer
|
152
|
-
concat pagination
|
153
|
-
yield
|
154
|
-
concat pagination
|
155
|
-
else
|
156
|
-
content = pagination + capture(&block) + pagination
|
157
|
-
concat(content, block.binding)
|
158
|
-
end
|
159
|
-
end
|
160
|
-
|
161
|
-
# Renders a helpful message with numbers of displayed vs. total entries.
|
162
|
-
# You can use this as a blueprint for your own, similar helpers.
|
163
|
-
#
|
164
|
-
# <%= page_entries_info @posts %>
|
165
|
-
# #-> Displaying posts 6 - 10 of 26 in total
|
166
|
-
#
|
167
|
-
# By default, the message will use the humanized class name of objects
|
168
|
-
# in collection: for instance, "project types" for ProjectType models.
|
169
|
-
# Override this with the <tt>:model</tt> parameter:
|
170
|
-
#
|
171
|
-
# <%= page_entries_info @posts, :model => 'item' %>
|
172
|
-
# #-> Displaying items 6 - 10 of 26 in total
|
173
|
-
def page_entries_info(collection, options = {})
|
174
|
-
if options.key? :entry_name
|
175
|
-
WillPaginate::Deprecation::warn(":entry_name parameter is now called :model", caller)
|
176
|
-
end
|
177
|
-
model = options[:model] || options[:entry_name]
|
178
|
-
model = collection.first.class unless model or collection.empty?
|
179
|
-
model ||= 'entry'
|
180
|
-
|
181
|
-
if html = options.fetch(:html, true)
|
182
|
-
b, eb = '<b>', '</b>'
|
183
|
-
sp = ' '
|
184
|
-
html_key = '_html'
|
185
|
-
else
|
186
|
-
b = eb = html_key = ''
|
187
|
-
sp = ' '
|
188
|
-
end
|
189
|
-
|
190
|
-
model_key = model.to_s.underscore
|
191
|
-
model_count = collection.total_pages > 1 ? 5 : collection.size
|
192
|
-
model_name = will_paginate_translate "models.#{model_key}", :count => model_count do |_, opts|
|
193
|
-
name = model_key.to_s.tr('_/', ' ')
|
194
|
-
raise "can't pluralize model name: #{model.inspect}" unless name.respond_to? :pluralize
|
195
|
-
opts[:count] == 1 ? name : name.pluralize
|
196
|
-
end
|
197
|
-
|
198
|
-
output = if collection.total_pages < 2
|
199
|
-
i18n_key = :"page_entries_info.single_page#{html_key}"
|
200
|
-
keys = [:"#{model_key}.#{i18n_key}", i18n_key]
|
201
|
-
|
202
|
-
will_paginate_translate keys, :count => collection.size, :model => model_name do |_, opts|
|
203
|
-
case opts[:count]
|
204
|
-
when 0; "No #{opts[:model]} found"
|
205
|
-
when 1; "Displaying #{b}1#{eb} #{opts[:model]}"
|
206
|
-
else "Displaying #{b}all#{sp}#{opts[:count]}#{eb} #{opts[:model]}"
|
207
|
-
end
|
208
|
-
end
|
209
|
-
else
|
210
|
-
i18n_key = :"page_entries_info.multi_page#{html_key}"
|
211
|
-
keys = [:"#{model_key}.#{i18n_key}", i18n_key]
|
212
|
-
params = {
|
213
|
-
:model => model_name, :count => collection.total_entries,
|
214
|
-
:from => collection.offset + 1, :to => collection.offset + collection.length
|
215
|
-
}
|
216
|
-
will_paginate_translate keys, params do |_, opts|
|
217
|
-
%{Displaying %s #{b}%d#{sp}-#{sp}%d#{eb} of #{b}%d#{eb} in total} %
|
218
|
-
[ opts[:model], opts[:from], opts[:to], opts[:count] ]
|
219
|
-
end
|
220
|
-
end
|
221
|
-
|
222
|
-
if html and output.respond_to?(:html_safe)
|
223
|
-
output.html_safe
|
224
|
-
else
|
225
|
-
output
|
226
|
-
end
|
227
|
-
end
|
228
|
-
|
229
|
-
def self.total_pages_for_collection(collection) #:nodoc:
|
230
|
-
if collection.respond_to?('page_count') and !collection.respond_to?('total_pages')
|
231
|
-
WillPaginate::Deprecation.warn %{
|
232
|
-
You are using a paginated collection of class #{collection.class.name}
|
233
|
-
which conforms to the old API of WillPaginate::Collection by using
|
234
|
-
`page_count`, while the current method name is `total_pages`. Please
|
235
|
-
upgrade yours or 3rd-party code that provides the paginated collection}, caller
|
236
|
-
class << collection
|
237
|
-
def total_pages; page_count; end
|
238
|
-
end
|
239
|
-
end
|
240
|
-
collection.total_pages
|
241
|
-
end
|
242
|
-
end
|
243
|
-
|
244
|
-
# This class does the heavy lifting of actually building the pagination
|
245
|
-
# links. It is used by the <tt>will_paginate</tt> helper internally.
|
246
|
-
class LinkRenderer
|
247
|
-
|
248
|
-
# * +collection+ is a WillPaginate::Collection instance or any other object
|
249
|
-
# that conforms to that API
|
250
|
-
# * +options+ are forwarded from +will_paginate+ view helper
|
251
|
-
# * +template+ is the reference to the template being rendered
|
252
|
-
def prepare(collection, options, template)
|
253
|
-
@collection = collection
|
254
|
-
@options = options
|
255
|
-
@template = template
|
256
|
-
|
257
|
-
# reset values in case we're re-using this instance
|
258
|
-
@total_pages = @param_name = @url_string = nil
|
259
|
-
end
|
260
|
-
|
261
|
-
# Process it! This method returns the complete HTML string which contains
|
262
|
-
# pagination links. Feel free to subclass LinkRenderer and change this
|
263
|
-
# method as you see fit.
|
264
|
-
def to_html
|
265
|
-
links = @options[:page_links] ? windowed_links : []
|
266
|
-
# previous/next buttons
|
267
|
-
links.unshift page_link_or_span(@collection.previous_page, 'disabled prev_page', @options[:previous_label])
|
268
|
-
links.push page_link_or_span(@collection.next_page, 'disabled next_page', @options[:next_label])
|
269
|
-
|
270
|
-
html = links.join(@options[:separator])
|
271
|
-
html = html.html_safe if html.respond_to? :html_safe
|
272
|
-
@options[:container] ? @template.content_tag(:div, html, html_attributes) : html
|
273
|
-
end
|
274
|
-
|
275
|
-
# Returns the subset of +options+ this instance was initialized with that
|
276
|
-
# represent HTML attributes for the container element of pagination links.
|
277
|
-
def html_attributes
|
278
|
-
return @html_attributes if @html_attributes
|
279
|
-
@html_attributes = @options.except *(WillPaginate::ViewHelpers.pagination_options.keys - [:class])
|
280
|
-
# pagination of Post models will have the ID of "posts_pagination"
|
281
|
-
if @options[:container] and @options[:id] === true
|
282
|
-
@html_attributes[:id] = @collection.first.class.name.underscore.pluralize + '_pagination'
|
283
|
-
end
|
284
|
-
@html_attributes
|
285
|
-
end
|
286
|
-
|
287
|
-
attr_writer :gap_marker
|
288
|
-
|
289
|
-
# The gap in page links is represented by:
|
290
|
-
#
|
291
|
-
# <span class="gap">…</span>
|
292
|
-
def gap_marker
|
293
|
-
@gap_marker ||= begin
|
294
|
-
gap_text = @template.will_paginate_translate(:page_gap) { '…' }
|
295
|
-
%(<span class="gap">#{gap_text}</span>)
|
296
|
-
end
|
297
|
-
end
|
298
|
-
|
299
|
-
protected
|
300
|
-
|
301
|
-
# Collects link items for visible page numbers.
|
302
|
-
def windowed_links
|
303
|
-
prev = nil
|
304
|
-
|
305
|
-
visible_page_numbers.inject [] do |links, n|
|
306
|
-
# detect gaps:
|
307
|
-
links << gap_marker if prev and n > prev + 1
|
308
|
-
links << page_link_or_span(n, 'current')
|
309
|
-
prev = n
|
310
|
-
links
|
311
|
-
end
|
312
|
-
end
|
313
|
-
|
314
|
-
# Calculates visible page numbers using the <tt>:inner_window</tt> and
|
315
|
-
# <tt>:outer_window</tt> options.
|
316
|
-
def visible_page_numbers
|
317
|
-
inner_window, outer_window = @options[:inner_window].to_i, @options[:outer_window].to_i
|
318
|
-
window_from = current_page - inner_window
|
319
|
-
window_to = current_page + inner_window
|
320
|
-
|
321
|
-
# adjust lower or upper limit if other is out of bounds
|
322
|
-
if window_to > total_pages
|
323
|
-
window_from -= window_to - total_pages
|
324
|
-
window_to = total_pages
|
325
|
-
end
|
326
|
-
if window_from < 1
|
327
|
-
window_to += 1 - window_from
|
328
|
-
window_from = 1
|
329
|
-
window_to = total_pages if window_to > total_pages
|
330
|
-
end
|
331
|
-
|
332
|
-
visible = (1..total_pages).to_a
|
333
|
-
left_gap = (2 + outer_window)...window_from
|
334
|
-
right_gap = (window_to + 1)...(total_pages - outer_window)
|
335
|
-
visible -= left_gap.to_a if left_gap.last - left_gap.first > 1
|
336
|
-
visible -= right_gap.to_a if right_gap.last - right_gap.first > 1
|
337
|
-
|
338
|
-
visible
|
339
|
-
end
|
340
|
-
|
341
|
-
def page_link_or_span(page, span_class, text = nil)
|
342
|
-
text ||= page.to_s
|
343
|
-
text = text.html_safe if text.respond_to? :html_safe
|
344
|
-
|
345
|
-
if page and page != current_page
|
346
|
-
classnames = span_class && span_class.index(' ') && span_class.split(' ', 2).last
|
347
|
-
page_link page, text, :rel => rel_value(page), :class => classnames
|
348
|
-
else
|
349
|
-
page_span page, text, :class => span_class
|
350
|
-
end
|
351
|
-
end
|
352
|
-
|
353
|
-
def page_link(page, text, attributes = {})
|
354
|
-
@template.link_to text, url_for(page), attributes
|
355
|
-
end
|
356
|
-
|
357
|
-
def page_span(page, text, attributes = {})
|
358
|
-
@template.content_tag :span, text, attributes
|
359
|
-
end
|
360
|
-
|
361
|
-
# Returns URL params for +page_link_or_span+, taking the current GET params
|
362
|
-
# and <tt>:params</tt> option into account.
|
363
|
-
def url_for(page)
|
364
|
-
page_one = page == 1
|
365
|
-
unless @url_string and !page_one
|
366
|
-
@url_params = {}
|
367
|
-
# page links should preserve GET parameters
|
368
|
-
stringified_merge @url_params, @template.params if @template.request.get?
|
369
|
-
stringified_merge @url_params, @options[:params] if @options[:params]
|
370
|
-
|
371
|
-
if complex = param_name.index(/[^\w-]/)
|
372
|
-
page_param = parse_query_parameters("#{param_name}=#{page}")
|
373
|
-
|
374
|
-
stringified_merge @url_params, page_param
|
375
|
-
else
|
376
|
-
@url_params[param_name] = page_one ? 1 : 2
|
377
|
-
end
|
378
|
-
|
379
|
-
url = @template.url_for(@url_params)
|
380
|
-
return url if page_one
|
381
|
-
|
382
|
-
if complex
|
383
|
-
@url_string = url.sub(%r!((?:\?|&)#{CGI.escape param_name}=)#{page}!, "\\1\0")
|
384
|
-
return url
|
385
|
-
else
|
386
|
-
@url_string = url
|
387
|
-
@url_params[param_name] = 3
|
388
|
-
@template.url_for(@url_params).split(//).each_with_index do |char, i|
|
389
|
-
if char == '3' and url[i, 1] == '2'
|
390
|
-
@url_string[i] = "\0"
|
391
|
-
break
|
392
|
-
end
|
393
|
-
end
|
394
|
-
end
|
395
|
-
end
|
396
|
-
# finally!
|
397
|
-
@url_string.sub "\0", page.to_s
|
398
|
-
end
|
399
|
-
|
400
|
-
private
|
401
|
-
|
402
|
-
def rel_value(page)
|
403
|
-
case page
|
404
|
-
when @collection.previous_page; 'prev' + (page == 1 ? ' start' : '')
|
405
|
-
when @collection.next_page; 'next'
|
406
|
-
when 1; 'start'
|
407
|
-
end
|
408
|
-
end
|
409
|
-
|
410
|
-
def current_page
|
411
|
-
@collection.current_page
|
412
|
-
end
|
413
|
-
|
414
|
-
def total_pages
|
415
|
-
@total_pages ||= WillPaginate::ViewHelpers.total_pages_for_collection(@collection)
|
416
|
-
end
|
417
|
-
|
418
|
-
def param_name
|
419
|
-
@param_name ||= @options[:param_name].to_s
|
420
|
-
end
|
421
|
-
|
422
|
-
# Recursively merge into target hash by using stringified keys from the other one
|
423
|
-
def stringified_merge(target, other)
|
424
|
-
other.each do |key, value|
|
425
|
-
key = key.to_s # this line is what it's all about!
|
426
|
-
existing = target[key]
|
427
|
-
|
428
|
-
if value.is_a?(Hash) and (existing.is_a?(Hash) or existing.nil?)
|
429
|
-
stringified_merge(existing || (target[key] = {}), value)
|
430
|
-
else
|
431
|
-
target[key] = value
|
432
|
-
end
|
433
|
-
end
|
434
|
-
end
|
435
|
-
|
436
|
-
def parse_query_parameters(params)
|
437
|
-
if defined? Rack::Utils
|
438
|
-
# For Rails > 2.3
|
439
|
-
Rack::Utils.parse_nested_query(params)
|
440
|
-
elsif defined?(ActionController::AbstractRequest) and
|
441
|
-
ActionController::AbstractRequest.respond_to? :parse_query_parameters
|
442
|
-
ActionController::AbstractRequest.parse_query_parameters(params)
|
443
|
-
elsif defined?(ActionController::UrlEncodedPairParser)
|
444
|
-
# For Rails > 2.2
|
445
|
-
ActionController::UrlEncodedPairParser.parse_query_parameters(params)
|
446
|
-
elsif defined?(CGIMethods)
|
447
|
-
CGIMethods.parse_query_parameters(params)
|
448
|
-
else
|
449
|
-
raise "unsupported ActionPack version"
|
450
|
-
end
|
451
|
-
end
|
452
41
|
end
|
453
42
|
end
|