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