3 # Provides methods for linking to ActionController::Pagination objects using a simple generator API. You can optionally
4 # also build your links manually using ActionView::Helpers::AssetHelper#link_to like so:
6 # <%= link_to "Previous page", { :page => paginator.current.previous } if paginator.current.previous %>
7 # <%= link_to "Next page", { :page => paginator.current.next } if paginator.current.next %>
8 module PaginationHelper
9 unless const_defined?(:DEFAULT_OPTIONS)
13 :always_show_anchors => true,
14 :link_to_current_page => false,
19 # Creates a basic HTML link bar for the given +paginator+. Links will be created
20 # for the next and/or previous page and for a number of other pages around the current
21 # pages position. The +html_options+ hash is passed to +link_to+ when the links are created.
24 # <tt>:name</tt>:: the routing name for this paginator
25 # (defaults to +page+)
26 # <tt>:prefix</tt>:: prefix for pagination links
27 # (i.e. Older Pages: 1 2 3 4)
28 # <tt>:suffix</tt>:: suffix for pagination links
29 # (i.e. 1 2 3 4 <- Older Pages)
30 # <tt>:window_size</tt>:: the number of pages to show around
31 # the current page (defaults to <tt>2</tt>)
32 # <tt>:always_show_anchors</tt>:: whether or not the first and last
33 # pages should always be shown
34 # (defaults to +true+)
35 # <tt>:link_to_current_page</tt>:: whether or not the current page
36 # should be linked to (defaults to
38 # <tt>:params</tt>:: any additional routing parameters
42 # # We'll assume we have a paginator setup in @person_pages...
44 # pagination_links(@person_pages)
45 # # => 1 <a href="/?page=2/">2</a> <a href="/?page=3/">3</a> ... <a href="/?page=10/">10</a>
47 # pagination_links(@person_pages, :link_to_current_page => true)
48 # # => <a href="/?page=1/">1</a> <a href="/?page=2/">2</a> <a href="/?page=3/">3</a> ... <a href="/?page=10/">10</a>
50 # pagination_links(@person_pages, :always_show_anchors => false)
51 # # => 1 <a href="/?page=2/">2</a> <a href="/?page=3/">3</a>
53 # pagination_links(@person_pages, :window_size => 1)
54 # # => 1 <a href="/?page=2/">2</a> ... <a href="/?page=10/">10</a>
56 # pagination_links(@person_pages, :params => { :viewer => "flash" })
57 # # => 1 <a href="/?page=2&viewer=flash/">2</a> <a href="/?page=3&viewer=flash/">3</a> ...
58 # # <a href="/?page=10&viewer=flash/">10</a>
59 def pagination_links(paginator, options = {}, html_options = {})
60 name = options[:name] || DEFAULT_OPTIONS[:name]
61 params = (options[:params] || DEFAULT_OPTIONS[:params]).clone
63 prefix = options[:prefix] || ""
64 suffix = options[:suffix] || ""
66 pagination_links_each(paginator, options, prefix, suffix) do |n|
68 link_to(n.to_s, params, html_options)
72 # Iterate through the pages of a given +paginator+, invoking a
73 # block for each page number that needs to be rendered as a link.
76 # <tt>:window_size</tt>:: the number of pages to show around
77 # the current page (defaults to +2+)
78 # <tt>:always_show_anchors</tt>:: whether or not the first and last
79 # pages should always be shown
80 # (defaults to +true+)
81 # <tt>:link_to_current_page</tt>:: whether or not the current page
82 # should be linked to (defaults to
86 # # Turn paginated links into an Ajax call
87 # pagination_links_each(paginator, page_options) do |link|
88 # options = { :url => {:action => 'list'}, :update => 'results' }
89 # html_options = { :href => url_for(:action => 'list') }
91 # link_to_remote(link.to_s, options, html_options)
93 def pagination_links_each(paginator, options, prefix = nil, suffix = nil)
94 options = DEFAULT_OPTIONS.merge(options)
95 link_to_current_page = options[:link_to_current_page]
96 always_show_anchors = options[:always_show_anchors]
98 current_page = paginator.current_page
99 window_pages = current_page.window(options[:window_size]).pages
100 return unless link_to_current_page || window_pages.length > 1
102 first = paginator.first
103 last = paginator.last
107 html << prefix if prefix
109 if always_show_anchors && !(wp_first = window_pages[0]).first?
110 html << yield(first.number)
111 html << " ... " if wp_first.number - first.number > 1
115 window_pages.each do |page|
116 html << if current_page == page && !link_to_current_page
124 if always_show_anchors && !(wp_last = window_pages[-1]).last?
125 html << " ... " if last.number - wp_last.number > 1
126 html << yield(last.number)
129 html << suffix if suffix
135 # - with bootstrap classes
136 # - invoked block returns the page url
137 def pagination_links_bootstrap(paginator, options)
138 options = DEFAULT_OPTIONS.merge(options)
139 link_to_current_page = options[:link_to_current_page]
140 always_show_anchors = options[:always_show_anchors]
142 current_page = paginator.current_page
143 window_pages = current_page.window(options[:window_size]).pages
144 return unless link_to_current_page || window_pages.length > 1
146 first = paginator.first
147 last = paginator.last
151 html << "<ul class='pagination pagination-sm mb-1'>"
153 if always_show_anchors && !(wp_first = window_pages[0]).first?
154 html << bootstrap_page_item_link(first.number.to_s, yield(first.number))
155 html << bootstrap_page_item_disabled("...") if wp_first.number - first.number > 1
158 window_pages.each do |page|
159 html << if current_page == page && !link_to_current_page
160 bootstrap_page_item_active(page.number.to_s)
162 bootstrap_page_item_link(page.number.to_s, yield(page.number))
166 if always_show_anchors && !(wp_last = window_pages[-1]).last?
167 html << bootstrap_page_item_disabled("...") if last.number - wp_last.number > 1
168 html << bootstrap_page_item_link(last.number.to_s, yield(last.number))
178 def bootstrap_page_item_disabled(body)
179 content_tag "li", :class => "page-item disabled" do
180 content_tag "span", body, :class => "page-link"
184 def bootstrap_page_item_active(body)
185 content_tag "li", :class => "page-item active", :'aria-current' => "page" do
186 content_tag "span", body, :class => "page-link"
190 def bootstrap_page_item_link(body, url)
191 content_tag "li", :class => "page-item" do
192 link_to body, url, :class => "page-link"