Skip to content

Commit

Permalink
Add :fixed_page_links option
Browse files Browse the repository at this point in the history
When set to true, the number of links displayed (including gaps) will
always equal 3 (first, current_page, last) + 2 (to allow for gaps) +
2*inner_window + 2*outer_window.

This means that the width of the pagination bar does not substantially
change as a user browses through pages.
  • Loading branch information
mattjbray committed Nov 9, 2012
1 parent 71f793e commit 0b6e5b0
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 12 deletions.
22 changes: 12 additions & 10 deletions lib/will_paginate/view_helpers.rb
Expand Up @@ -21,16 +21,18 @@ class << self

# default view options
self.pagination_options = Deprecation::Hash.new \
:class => 'pagination',
:previous_label => nil,
:next_label => nil,
:inner_window => 4, # links around the current page
:outer_window => 1, # links around beginning and end
:link_separator => ' ', # single space is friendly to spiders and non-graphic browsers
:param_name => :page,
:params => nil,
:page_links => true,
:container => true
:class => 'pagination',
:previous_label => nil,
:next_label => nil,
:inner_window => 4, # links around the current page
:outer_window => 1, # links around beginning and end
:fixed_page_links => false, # if set to true, the number of link items
# displayed will be constant
:link_separator => ' ', # single space is friendly to spiders and non-graphic browsers
:param_name => :page,
:params => nil,
:page_links => true,
:container => true

label_deprecation = Proc.new { |key, value|
"set the 'will_paginate.#{key}' key in your i18n locale instead of editing pagination_options" if defined? Rails
Expand Down
21 changes: 19 additions & 2 deletions lib/will_paginate/view_helpers/link_renderer_base.rb
Expand Up @@ -31,12 +31,29 @@ def windowed_page_numbers
window_to = current_page + inner_window

# adjust lower or upper limit if other is out of bounds
if window_to > total_pages

# if <tt>:fixed_page_links</tt> is set, out of bounds means
# window_to + outer_window + 2 > total_pages or
# window_from - outer_window - 2 < 1
window_to_bound = @options[:fixed_page_links] ? window_to + outer_window + 2 : window_to
window_from_bound = @options[:fixed_page_links] ? window_from - outer_window - 2 : window_from

if window_to_bound > total_pages
window_from -= window_to - total_pages

# allow for the outer_window size, the first link and a possible gap
# to ensure items.length is always the same, regardless of whether
# current_page is near the middle or near an edge
window_from -= outer_window + 2 if @options[:fixed_page_links]

window_to = total_pages
end
if window_from < 1
if window_from_bound < 1
window_to += 1 - window_from

# allow for the outer_window size, the last link and a possible gap
window_to += outer_window + 2 if @options[:fixed_page_links]

window_from = 1
window_to = total_pages if window_to > total_pages
end
Expand Down
51 changes: 51 additions & 0 deletions spec/view_helpers/link_renderer_base_spec.rb
Expand Up @@ -63,6 +63,57 @@
prepare({ :page => 10, :total_pages => 10 }, :inner_window => 2, :outer_window => 1)
showing_pages 1, 2, :gap, 6, 7, 8, 9, 10
end

context "with a fixed number of visible page links" do
it "should adjust upper limit if lower is out of bounds" do
prepare({ :page => 1, :total_pages => 10 }, :fixed_page_links => true, :inner_window => 2, :outer_window => 1)
showing_pages 1..10
end

it "should adjust lower limit if upper is out of bounds" do
prepare({ :page => 10, :total_pages => 10 }, :fixed_page_links => true, :inner_window => 2, :outer_window => 1)
showing_pages 1..10
end

context "with a large number of pages" do
it "should adjust upper limit if lower is out of bounds" do
prepare({ :page => 1, :total_pages => 21 }, :fixed_page_links => true, :inner_window => 4, :outer_window => 1)
showing_pages 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, :gap, 20, 21
end

it "should adjust upper limit if lower is out of bounds" do
prepare({ :page => 5, :total_pages => 21 }, :fixed_page_links => true, :inner_window => 4, :outer_window => 1)
showing_pages 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, :gap, 20, 21
end

it "should adjust upper limit if lower is out of bounds" do
prepare({ :page => 6, :total_pages => 21 }, :fixed_page_links => true, :inner_window => 4, :outer_window => 1)
showing_pages 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, :gap, 20, 21
end

it "should adjust upper limit if lower is out of bounds" do
prepare({ :page => 7, :total_pages => 21 }, :fixed_page_links => true, :inner_window => 4, :outer_window => 1)
showing_pages 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, :gap, 20, 21
end

it "should adjust lower limit if upper is out of bounds" do
prepare({ :page => 17, :total_pages => 21 }, :fixed_page_links => true, :inner_window => 4, :outer_window => 1)
showing_pages 1, 2, :gap, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21
end

it "should adjust lower limit if upper is out of bounds" do
prepare({ :page => 21, :total_pages => 21 }, :fixed_page_links => true, :inner_window => 4, :outer_window => 1)
showing_pages 1, 2, :gap, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21
end
end

context "with a small number of pages" do
it "should show all of the pages" do
prepare({ :page => 2, :total_pages => 5 }, :fixed_page_links => true, :inner_window => 4, :outer_window => 2)
showing_pages 1..5
end
end
end

def showing_pages(*pages)
pages = pages.first.to_a if Array === pages.first or Range === pages.first
Expand Down

0 comments on commit 0b6e5b0

Please sign in to comment.