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