summaryrefslogtreecommitdiffstats
path: root/vendor/plugins/classic_pagination/lib/pagination_helper.rb
blob: 069d775668654fbf3704b3d49421bb5576804171 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
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 => {}
        }
      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 if window_pages.length <= 1 unless link_to_current_page
        
        first, last = paginator.first, paginator.last
        
        html = ''

        html << prefix if prefix

        if always_show_anchors and not (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|
          if current_page == page && !link_to_current_page
            html << page.number.to_s
          else
            html << yield(page.number)
          end
          html << ' '
        end
        
        if always_show_anchors and not (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
      
    end # PaginationHelper
  end # Helpers
end # ActionView