Drop the arrows, already got arrows. Up version again.
[gitorious:just_paginate.git] / lib / just_paginate.rb
1 # -*- coding: utf-8 -*-
2 module JustPaginate
3
4   VERSION = "0.0.7"
5
6   def self.page_value(page)
7     if page.nil?
8       1
9     else 
10       page.to_i
11     end
12   end
13
14   def self.paginate(curr_page, per_page, total_entry_count,  &selection_strategy)
15     raise "Pagination just supplies index range, expects a selection strategy" if selection_strategy.nil? 
16     
17     entries = yield(index_range(curr_page, per_page, total_entry_count)) || []    
18     return entries, total_page_number(total_entry_count, per_page)
19   end
20
21   def self.total_page_number(total_entry_count, per_page)
22     (total_entry_count.to_f / per_page).ceil
23   end
24   
25   def self.index_range(curr_page, per_page, total_entry_count)
26     start_index = ((curr_page-1)*per_page)
27     end_index = (start_index+per_page)-1
28     
29     if(start_index>total_entry_count)
30       raise "Pagination is out of bounds, beyond total entry size"
31     end
32     
33     if end_index>total_entry_count
34       end_index = total_entry_count
35     end
36     
37     Range.new(start_index, end_index)
38   end
39
40   def self.page_navigation(curr_page, total_page_count, &page_link_constructor)   
41     links = page_links(curr_page.to_i, total_page_count, &page_link_constructor)
42     return "<div class='pagination'>#{links}</div>"
43   end
44
45 # Create gitorous-style-pagination until we move to Bootstrap
46 # <div class="pagination">
47 # <a href="/projects?page=24" class="prev_page" rel="prev">Previous</a> 
48 # <a href="/projects?page=1" rel="start">1</a> 
49 # <span class="gap">…</span> 
50 # <a href="/projects?page=21">21</a> 
51 # <a href="/projects?page=22">22</a> 
52 # <a href="/projects?page=23">23</a> 
53 # <a href="/projects?page=24" rel="prev">24</a> <span class="current">25</span> 
54 # <a href="/projects?page=26" rel="next">26</a> 
55 # <a href="/projects?page=27">27</a> 
56 # <a href="/projects?page=28">28</a> 
57 # <a href="/projects?page=29">29</a> 
58 # <span class="gap">…</span> 
59 # <a href="/projects?page=1446">1446</a> 
60 # <a href="/projects?page=26" class="next_page" rel="next">Next</a>
61 # </div>
62
63
64   def self.page_links(curr_page, total_page_count, &page_link_constructor)
65     page_labels(curr_page, total_page_count).map do |label|
66       page_element = ""
67       
68       if label == "..."
69         page_element = "<span class='gap'>#{label}</span>"
70       elsif label == "<"
71         page_url = yield(curr_page-1)
72         page_element = "<a rel='prev' href='#{page_url}'>#{label}</a>"
73       elsif label == ">"
74         page_url = yield(curr_page+1)
75         page_element = "<a rel='next' href='#{page_url}'>#{label}</a>"
76       else
77         page_url = yield(label)
78         if label.to_i == curr_page
79           page_element = "<span class='current'>#{label}</span>"
80         else
81           page_element = "<a href='#{page_url}'>#{label}</a>"
82         end
83       end
84
85     end.join(" ")
86   end
87   
88   def self.page_labels(current, total)
89     max_visible = 10
90     labels = []
91
92     if total <= max_visible
93       1.upto(total).each {|n| labels.push(n.to_s)}
94     else 
95       if current > max_visible
96         labels = ["<", "1", "..."]
97       else
98         current = 1
99       end
100
101       if (current > (total-max_visible))
102         current = (total-max_visible)+1
103       end
104
105       current.upto(current+(max_visible-1)).each {|n| labels.push(n.to_s)}
106
107       if (current <= (total-max_visible))
108         labels.concat ["...", "#{total}", ">"]
109       end 
110     end
111
112     return labels
113   end  
114   
115 end