Return to Snippet

Revision: 3465
at July 28, 2007 12:04 by Agent


Initial Code
class ActionController::AbstractRequest
  def get_post_params
    self.parameters.reject {|k,v| k == 'controller' || k == 'action'}
  end
end

def pagerBar(paginator, anchor)
  page = paginator.current_page;
  pageParam = 'page';
  firstPage = 1;
  lastPage = paginator.page_count;
  prevStr = '←';
  nextStr = '→';
  elideStr = '… ';   # Include trailing space.
  pageSpan = 3;      # How many pages to the left and right of current.
  
  # The central group of pages.
  window = page.window(pageSpan);
  windowFirst = window.first.number;
  windowLast = window.last.number;
  
  # These define the halfway pages.
  prevHalfway = (windowFirst / 2.0).floor;
  prevHalfway = 2 if prevHalfway == 1;
  nextHalfway = ((windowLast + lastPage) / 2.0).ceil;
  nextHalfway = lastPage - 1 if nextHalfway == lastPage;
  
  # Need to show first/last pages separate from range?
  showFirst = (windowFirst > 1);
  showLast = (windowLast < lastPage);
  
  # Need to show half-way pages?
  showPrevHalfway = (prevHalfway > 1 && prevHalfway < windowFirst);
  showNextHalfway = (nextHalfway < lastPage && nextHalfway > windowLast);
  
  # Pages missing before/after half-way pages?
  elideBeforePrevHalf = (showPrevHalfway && (prevHalfway - firstPage) > 1);
  elideAfterPrevHalf = (showPrevHalfway && (windowFirst - prevHalfway) > 1);
  elideBeforeNextHalf = (showNextHalfway && (nextHalfway - windowLast) > 1);
  elideAfterNextHalf = (showNextHalfway && (lastPage - nextHalfway) > 1);
  
  # No half-way pages, but pages missing before/after range?
  elideBeforeRange = (!showPrevHalfway && (windowFirst - firstPage) > 1);
  elideAfterRange = (!showNextHalfway && (lastPage - windowLast) > 1);
  
  # Do prev arrow.
  html = link_to_unless(page.first?, prevStr,
    request.get_post_params.merge(
      { pageParam => page.previous, :anchor => anchor }));
  html += ' ';
  
  # Do first page.
  if (showFirst)
    html += link_to(paginator.first_page.number.to_s,
      request.get_post_params.merge(
        { pageParam => paginator.first_page.number, :anchor => anchor }));
    html += ' ';
  end
  
  # Do prev halfway point.
  html += elideStr if elideBeforePrevHalf;
  if (showPrevHalfway)
    html += link_to(paginator[prevHalfway].number.to_s,
      request.get_post_params.merge(
        { pageParam => paginator[prevHalfway].number, :anchor => anchor }));
    html += ' ';
  end
  html += elideStr if elideAfterPrevHalf;
  
  # Do range.
  html += elideStr if elideBeforeRange;
  window.pages.each do |windowPage|
    html += link_to_unless (page == windowPage, windowPage.number.to_s,
      request.get_post_params.merge(
        { pageParam => windowPage.number, :anchor => anchor }));
    html += ' ';
  end
  html += elideStr if elideAfterRange;
  
  # Do next halfway point.
  html += elideStr if elideBeforeNextHalf;
  if (showNextHalfway)
    html += link_to(paginator[nextHalfway].number.to_s,
      request.get_post_params.merge(
        { pageParam => paginator[nextHalfway].number, :anchor => anchor }));
    html += ' ';
  end
  html += elideStr if elideAfterNextHalf;
  
  # Do last page.
  if (showLast)
    html += link_to(paginator.last_page.number.to_s,
      request.get_post_params.merge(
        { pageParam => paginator.last_page.number, :anchor => anchor }));
    html += ' ';
  end
      
  # Do next arrow.
  html += link_to_unless(page.last?, nextStr,
    request.get_post_params.merge(
      { pageParam => page.next, :anchor => anchor }));
    
  # Return
  html
end

Initial URL


Initial Description
This function (intended to be an application or view helper) creates a pager bar useful for navigating many pages. It shows the first, last, current, nearby, and halfway-to-end pages. It looks like this (where the current page is 11):

< 1 ... 5 ... 10 11 12 ... 14 15 >

The pagerBar function takes two parameters: a RoR paginator, and an anchor that will be attached to all the links.

Initial Title
Pager for lots o' data

Initial Tags
html, rails

Initial Language
Ruby