will_paginate is the standard pagination plugin for many a Rails-2 site, and it's extremely flexible.
However it has one drawback: it will only show links - if there is more than one page.
This is mostly not a problem, if the links are all you show. But lets say you also use it to show the "Showing 26 to 50 of 342 matches" summary. Then lets say you want it to show "Showing 1 to 16 of 16 matches" - even when there's only a single page (for the sake of UI consistency). will_paginate does not provide an option for this.
There's talk of adding a :show_always => true option to will_paginate, but last I looked it hadn't been dragged into master...
So I wrote my own monkey-patch.
You'll need to put the following two snippets into config/intiializers/will_paginate.rb
The first thing you need to do, is make the "summary" sections public, so they are available to the renderer (which is the thing that generates all the page-links for you). Here's mine (both scavenged and adapted from the web many years ago):
module WillPaginate class LinkRenderer # generates eg: "1 - 15 of 15" or "26 - 50 of 342" def matches_summary if 0 == @collection.total_entries # because "0 - 0 of 0" is a bit much summary_text = "0 Matches" elsif 1 == @collection.total_entries summary_text = "1 Match" else summary_text = "%d - %d of %d" % [ @collection.offset + 1, @collection.offset + @collection.length, @collection.total_entries ] end page_span(1, summary_text, :class => "summary") end # generates "Page 4 of 62" or "Page 1 of 1" def pages_summary if 0 == @collection.total_pages # because "Page 0 of 0" is a bit much summary_text = "0 Pages" elsif 1 == @collection.total_pages summary_text = "1 Page" else summary_text = "Page %d of %d" % [ current_page, @collection.total_pages ] end page_span(1, summary_text, :class => "summary") end end # LinkRenderer class end # WillPaginate module
And this chunk is what makes will_paginate:
- Accept the ":show-always => true" option
- If the above is passed, and there are no page-links... displays the summaries
module WillPaginate module ViewHelpers # This lets us still use any will_paginate passed-in renderers if we want # adapted by code in original will_paginate def fetch_renderer(renderer) case renderer when String renderer.to_s.constantize.new when Class renderer.new else renderer end end # don't lose the old will_paginate alias :old_will_paginate :will_paginate # overload actual will_paginate call to allow us to choose to show the # "number of matches" box even if there is only one page def will_paginate(collection, options = {}) # strip out the show_always option show_always = options.delete(:show_always) # do standard pagination html = old_will_paginate(collection,options) # if we didn't get anything, but we have "show always" = true if html.nil? && show_always # set up the renderer (stolen directly from standard will_paginate) options[:container] = true renderer = fetch_renderer(options[:renderer]) renderer.prepare collection, options, self # produce the "matches" boxes through the renderer links = [renderer.matches_summary, renderer.pages_summary] # generate the html for the pagination links - # default the html-attributes to the plain pagination class html = content_tag(:div, links, (renderer.html_attributes||{}).merge(:class => 'pagination')) end html end end end
Then you can call it with this:
<%= will_paginate @things, :show_always => true %>
No comments:
Post a Comment