openstreetmap-website/lib/classic_pagination/pagination_helper.rb

194 lines
7.9 KiB
Ruby

module ActionView
module Helpers
# Provides methods for linking to ActionController::Pagination objects using a simple generator API. You can optionally
# also build your links manually using ActionView::Helpers::AssetHelper#link_to like so:
#
# <%= link_to "Previous page", { :page => paginator.current.previous } if paginator.current.previous %>
# <%= link_to "Next page", { :page => paginator.current.next } if paginator.current.next %>
module PaginationHelper
unless const_defined?(:DEFAULT_OPTIONS)
DEFAULT_OPTIONS = {
:name => :page,
:window_size => 2,
:always_show_anchors => true,
:link_to_current_page => false,
:params => {}
}.freeze
end
# Creates a basic HTML link bar for the given +paginator+. Links will be created
# for the next and/or previous page and for a number of other pages around the current
# pages position. The +html_options+ hash is passed to +link_to+ when the links are created.
#
# ==== Options
# <tt>:name</tt>:: the routing name for this paginator
# (defaults to +page+)
# <tt>:prefix</tt>:: prefix for pagination links
# (i.e. Older Pages: 1 2 3 4)
# <tt>:suffix</tt>:: suffix for pagination links
# (i.e. 1 2 3 4 <- Older Pages)
# <tt>:window_size</tt>:: the number of pages to show around
# the current page (defaults to <tt>2</tt>)
# <tt>:always_show_anchors</tt>:: whether or not the first and last
# pages should always be shown
# (defaults to +true+)
# <tt>:link_to_current_page</tt>:: whether or not the current page
# should be linked to (defaults to
# +false+)
# <tt>:params</tt>:: any additional routing parameters
# for page URLs
#
# ==== Examples
# # We'll assume we have a paginator setup in @person_pages...
#
# pagination_links(@person_pages)
# # => 1 <a href="/?page=2/">2</a> <a href="/?page=3/">3</a> ... <a href="/?page=10/">10</a>
#
# pagination_links(@person_pages, :link_to_current_page => true)
# # => <a href="/?page=1/">1</a> <a href="/?page=2/">2</a> <a href="/?page=3/">3</a> ... <a href="/?page=10/">10</a>
#
# pagination_links(@person_pages, :always_show_anchors => false)
# # => 1 <a href="/?page=2/">2</a> <a href="/?page=3/">3</a>
#
# pagination_links(@person_pages, :window_size => 1)
# # => 1 <a href="/?page=2/">2</a> ... <a href="/?page=10/">10</a>
#
# pagination_links(@person_pages, :params => { :viewer => "flash" })
# # => 1 <a href="/?page=2&amp;viewer=flash/">2</a> <a href="/?page=3&amp;viewer=flash/">3</a> ...
# # <a href="/?page=10&amp;viewer=flash/">10</a>
def pagination_links(paginator, options = {}, html_options = {})
name = options[:name] || DEFAULT_OPTIONS[:name]
params = (options[:params] || DEFAULT_OPTIONS[:params]).clone
prefix = options[:prefix] || ""
suffix = options[:suffix] || ""
pagination_links_each(paginator, options, prefix, suffix) do |n|
params[name] = n
link_to(n.to_s, params, html_options)
end
end
# Iterate through the pages of a given +paginator+, invoking a
# block for each page number that needs to be rendered as a link.
#
# ==== Options
# <tt>:window_size</tt>:: the number of pages to show around
# the current page (defaults to +2+)
# <tt>:always_show_anchors</tt>:: whether or not the first and last
# pages should always be shown
# (defaults to +true+)
# <tt>:link_to_current_page</tt>:: whether or not the current page
# should be linked to (defaults to
# +false+)
#
# ==== Example
# # Turn paginated links into an Ajax call
# pagination_links_each(paginator, page_options) do |link|
# options = { :url => {:action => 'list'}, :update => 'results' }
# html_options = { :href => url_for(:action => 'list') }
#
# link_to_remote(link.to_s, options, html_options)
# end
def pagination_links_each(paginator, options, prefix = nil, suffix = nil)
options = DEFAULT_OPTIONS.merge(options)
link_to_current_page = options[:link_to_current_page]
always_show_anchors = options[:always_show_anchors]
current_page = paginator.current_page
window_pages = current_page.window(options[:window_size]).pages
return unless link_to_current_page || window_pages.length > 1
first = paginator.first
last = paginator.last
html = ""
html << prefix if prefix
if always_show_anchors && !(wp_first = window_pages[0]).first?
html << yield(first.number)
html << " ... " if wp_first.number - first.number > 1
html << " "
end
window_pages.each do |page|
html << if current_page == page && !link_to_current_page
page.number.to_s
else
yield(page.number)
end
html << " "
end
if always_show_anchors && !(wp_last = window_pages[-1]).last?
html << " ... " if last.number - wp_last.number > 1
html << yield(last.number)
end
html << suffix if suffix
html
end
# Same as above, but
# - with bootstrap classes
# - no list wrapper
# - invoked block returns the page url
def pagination_links_bootstrap(paginator, options)
options = DEFAULT_OPTIONS.merge(options)
link_to_current_page = options[:link_to_current_page]
always_show_anchors = options[:always_show_anchors]
current_page = paginator.current_page
window_pages = current_page.window(options[:window_size]).pages
return unless link_to_current_page || window_pages.length > 1
first = paginator.first
last = paginator.last
html = ""
if always_show_anchors && !(wp_first = window_pages[0]).first?
html << bootstrap_page_item_link(first.number.to_s, yield(first.number))
html << bootstrap_page_item_disabled("...") if wp_first.number - first.number > 1
end
window_pages.each do |page|
html << if current_page == page && !link_to_current_page
bootstrap_page_item_active(page.number.to_s)
else
bootstrap_page_item_link(page.number.to_s, yield(page.number))
end
end
if always_show_anchors && !(wp_last = window_pages[-1]).last?
html << bootstrap_page_item_disabled("...") if last.number - wp_last.number > 1
html << bootstrap_page_item_link(last.number.to_s, yield(last.number))
end
html
end
private
def bootstrap_page_item_disabled(body)
content_tag "li", :class => "page-item disabled" do
content_tag "span", body, :class => "page-link"
end
end
def bootstrap_page_item_active(body)
content_tag "li", :class => "page-item active", :'aria-current' => "page" do
content_tag "span", body, :class => "page-link"
end
end
def bootstrap_page_item_link(body, url)
content_tag "li", :class => "page-item" do
link_to body, url, :class => "page-link"
end
end
end
end
end