Paged Scopes, Part III: Paginating Your Views
In my two previous articles, I’ve been describing my new Paged Scopes pagination gem for ActiveRecord and Rails. In this final installment I’ll describe how to use the library to render pagination links in your views.
Pagination Links
The basic idea is to render a row of numbered links for a few pages either side of the one being viewed. This is referred to as the inner window. An outer window is often also included – this shows links for the first and last few pages at the start and end of the list. Usually, next page and previous page links are also sandwiched around the numbered links.
The will_paginate rdoc has some good links to articles on pagination UI design:
- a Yahoo Design Pattern Library article describing two styles of pagination;
- a Smashing Magazine article with good practices and examples; and
- another article with heaps of examples, both good and bad.
In the will_paginate gem, the eponymous will_paginate view helper is provided to render these links in your view. It works well, but one look at the method’s options gives you an idea what you’ll be up for if you want to customize the HTML structure of your pagination links. Want to render your pagination links as a list? You’ll have to write your own LinkRenderer subclass.
There has to be a better way. There is of course, and it comes from a less-is-more approach.
Using the Window Helper
With the PagedScopes gem, each page has an associated paginator which provides some simple methods for generating page links. First, we need to call set_path to tell the paginator how to generate links for a pages:
@page.paginator.set_path { |page| page_articles_path(page) }The block we supply will be used by the paginator to generate a paged URL whenever one is needed. (Alternately, we can set this in the controller using the :path option in the paginate method.)
Next, we use the window method to render the page links. We supply a block which the paginator will call for each page in the window, allowing us to render the link exactly as we want to. Let’s render that list we were talking about:
<ul> <% @page.paginator.window(:inner => 2, :outer => 1) do |page, path, classes| %> <% content_tag_for :li, page, :class => classes.join(" ") do %> <%= link_to_if path, page.number, path %> <% end %> <% end %> </ul>
Here we’ve specified an inner window of size 2 (meaning we want links for two pages either side of the current page) and an outer window of size 1 (meaning we want links for just the first and last pages).
The window helper passes a succession of pages to our block for us to render. The block arguments are:
- The page itself, from which we can get the page number.
- The path for the page, produced using the set_path proc we’ve already specified. If the page is the current page, then nil is passed as the path – this is because we shouldn’t render a link for the current page. (Hence our use of link_to_if.)
- An optional array of classes describing the link. Possible values for the classes are :selected if the page is the current page, :gap_before if there’s a gap in the numbering before the page, and :gap_after if there’s a gap after. You can use these as you see fit, but they’re intended to be passed through to your link container as classes for styling. (We’ve done this above with the :class => classes.join(" ") option.)
Within the block, the page link can be rendered as we please. In our example we’re putting it inside an <li> element. For page 7, the window function would produce the following markup:
<ul> <li class="page gap_after" id="page_1"> <span><a href="/pages/1/articles">1</a></span> </li> <li class="page gap_before" id="page_5"> <span><a href="/pages/5/articles">5</a></span> </li> <li class="page" id="page_6"> <span><a href="/pages/6/articles">6</a></span> </li> <li class="page selected" id="page_7"> <span>7</span> </li> <li class="page" id="page_8"> <span><a href="/pages/8/articles">8</a></span> </li> <li class="page gap_after" id="page_9"> <span><a href="/pages/9/articles">9</a></span> </li> <li class="page gap_before" id="page_12"> <span><a href="/pages/12/articles">12</a></span> </li> </ul>
Styling the Output
Add some styling, using our classes to distinguish the currently selected pages and to add a separator where there are numbering gaps:
li.page { display: inline } li.page a { text-decoration: none } li.page span { border: 1px solid gray; padding: 0.2em 0.5em } li.page.selected span, li.page span:hover { background: gray; color: white } li.page.gap_before:before { content: "..." }
The result: a nice-looking set of page links.
Too easy!
Adding Extra Controls
How do we get add previous and next links? This is pretty easy, too – just specify the :extras we want as an option. (Choose from :first, :previous, :next and :last.) Those symbols will be passed to our block as the page when they need to be rendered.
We’ll move our pagination links to a helper for clarity:
module ArticlesHelper MARKER = { :previous => "< newer", :next => "older >" } def article_page_links @page.paginator.window(:inner => 2, :outer => 1, :extras => [ :previous, :next ]) do |page, path, classes| content_tag :li, :class => (classes << :page).join(" ") do content_tag :li, link_to_if(path, MARKER[page] || page.number, path) end end end end
Which renders as follows (for page 4 this time):
Just what we want!
Links for the :first and :last pages can also be specified as extras; these will appear outside the previous and next links. (If you use these extras, you’ll want to omit the :outer window option.)
Wrap-Up
Finally! That’s just about it for the Paged Scopes pagination gem. There’s a few small bits and pieces I haven’t described, but you’ll find them in the code if you need them.
Once again, to install:
gem sources -a http://gems.github.com # just once sudo gem install mholling-paged_scopes
Enjoy! And comment away. (But be nice while you do.)
There are a lot of convenient, fast and powerful products.
DVD Ripper http://www.audiotoolsfactory.com/
Blu-ray Cloner http://www.audiotoolsfactory.com/
DVD Cloner http://www.audiotoolsfactory.com/
Blu-ray Ripper http://www.audiotoolsfactory.com/
DVD to AVI http://www.audiotoolsfactory.com/dvd-to-avi.html
DVD to iPod http://www.audiotoolsfactory.com/dvd-to-ipod.html
DVD to MP3 http://www.audiotoolsfactory.com/dvd-to-mp3.html
DVD to MP4 http://www.audiotoolsfactory.com/dvd-to-mp4.html
blu-ray converter http://www.audiotoolsfactory.com/blu-ray-converter.html
convert blu-ray http://www.audiotoolsfactory.com/blu-ray-converter.html
blu-ray to ipod http://www.audiotoolsfactory.com/blu-ray-to-ipod.html
rip blu-ray http://www.audiotoolsfactory.com/blu-ray-ripper.html
blu-ray ripper http://www.audiotoolsfactory.com/blu-ray-ripper.html
Mac DVD Ripper http://www.audiotoolsfactory.com/dvd-ripper-mac.html
mac video converter http://www.audiotoolsfactory.com/video-converter-mac.html
mac dvd to ipod http://www.audiotoolsfactory.com/dvd-ipod-mac.html
Video Converter http://www.audiotoolsfactory.com/video-converter.html
mac video to apple tv http://www.audiotoolsfactory.com/apple-tv-video-mac.html
mac video to apple tv converter http://www.audiotoolsfactory.com/apple-tv-video-mac.html
mac avi to iphone http://www.audiotoolsfactory.com/avi-iphone-mac.html
mac avi to ipod http://www.audiotoolsfactory.com/avi-ipod-mac.html
video to avi http://www.audiotoolsfactory.com/avi-video.html
blu-ray to avi http://www.audiotoolsfactory.com/blu-ray-to-avi.html
blu-ray to hd http://www.audiotoolsfactory.com/blu-ray-to-hd-video.html
blu-ray to mp3 http://www.audiotoolsfactory.com/blu-ray-to-mp3.html
blu-ray to mp4 http://www.audiotoolsfactory.com/blu-ray-to-mp4.html
blu-ray to mpeg http://www.audiotoolsfactory.com/blu-ray-to-mpeg.html
blu-ray to psp http://www.audiotoolsfactory.com/blu-ray-to-psp.html
blu-ray to wmv http://www.audiotoolsfactory.com/blu-ray-to-wmv.html
mac dvd to apple tv http://www.audiotoolsfactory.com/dvd-appletv-mac.html
mac dvd to avi http://www.audiotoolsfactory.com/dvd-avi-mac.html
mac dvd to flv http://www.audiotoolsfactory.com/dvd-flv-mac.html
mac dvd to gphone http://www.audiotoolsfactory.com/dvd-gphone-mac.html
mac dvd to iphone http://www.audiotoolsfactory.com/dvd-iphone-mac.html
mac dvd to ipod http://www.audiotoolsfactory.com/dvd-ipod-mac.html
mac dvd to mp3 http://www.audiotoolsfactory.com/dvd-mp3-mac.html
mac dvd to mp4 http://www.audiotoolsfactory.com/dvd-mp4-mac.html
mac dvd to mpeg http://www.audiotoolsfactory.com/dvd-mpeg-mac.html
mac dvd to psp http://www.audiotoolsfactory.com/dvd-psp-mac.html
mp3 cutter http://www.audiotoolsfactory.com/mp3cutter/mp3cutter.htm
mp3 splitter http://www.audiotoolsfactory.com/mp3cutter/mp3cutter.htm
We can provide you with convenient, fast and powerful products.
http://www.blurayrippers.net/bluraycloner.htm // Blu ray cloner
http://www.blurayrippers.net/blu_ray_ripper_for_mac.htm // Blu ray ripper for mac
http://www.blurayrippers.net/blurayconverter.htm // Blu ray converter
http://www.blurayrippers.net/bluraydisccopy.htm / Blu ray copy
Blu ray ripper http://www.blurayrippers.net
http://www.blurayrippers.net/bluraymaker.htm \\ Blu ray maker
http://www.blurayrippers.net/bestblurayburner.htm // Blu ray burner
http://www.blurayrippers.net/bluraybackup.htm // Blu ray backup
http://www.blurayrippers.net/howtoripabluray.htm // Rip Blu ray
http://www.blurayrippers.net/bluraytoavi.htm // Blu ray to AVI
http://www.blurayrippers.net/howtobackupbluray.htm // backup Blu ray
http://www.blurayrippers.net/howtomakebluray.htm // make Blu ray
http://www.blurayrippers.net/howtoburnbluray.htm // burn Blu ray
http://www.blurayrippers.net/howtoconvertbluray.htm // convert Blu ray
http://www.blurayrippers.net/bluraytohd.htm // Blu ray to HD
http://www.blurayrippers.net/Convert-blu-ray-to-ipad.htm blu ray to ipad
http://www.ripbd.net/blu-ray-converter.htm blu ray converter
http://www.ripbd.net/blu-ray-maker.htm blu ray maker
http://www.ripbd.net/blu-ray-copy.htm blu ray copy
http://www.ripbd.net blu ray ripper
http://www.videotoipadconverter.net ipad converter