views:

480

answers:

2

So I'm doing this in PHP but it is a logic issue so I'll try to write it as generically as possible.

To start here's how this pagination script works:

  1. for (draw first three pages links)
  2. if (draw ellipsis (...) if there are pages between #1's pages and #3's pages)
  3. for (draw current page and two pages on each side of it links)
  4. if (draw elipsis (...) if there are pages between #3's pages and #5's pages)
  5. for (draw final three pages links)

The problem is that when there are low amounts of pages (I noticed this when the page count was at 10) there should be an ellipsis but none is drawn.

Onto the code:

$page_count = 10; //in actual code this is set properly
$current_page = 1; //in actual code this is set properly

for ($i = 1;$i <= 3;$i++)
{
    if ($page_count >= $i)
        echo $i;
}

if ($page_count > 3 && $current_page >= 7)
    echo "...";

for ($i = $current_page - 2;$i <= current_page + 2;$i++)
{
    if ($i > 3 && $i < $page_count - 2)
        echo $i;
}

if ($page_count > 13 && $current_page < $page_count - 5)
    echo "...";

for ($i = $page_count - 2;$i <= $page_count;$i++)
{
    if ($page_count > 3)
        echo $i;
}

So I figure the best idea would to be to modify one of the two ellipsis if statements to include a case like this, however I've tried and am stumped.

Also please note that I condensed this code for readability sake so please don't give tips like "those for loops are ineffective because they will recalculate current_page - 2 for each iteration" because I know :)


For those whom want to see a breakdown of how this logic currently works, here is example output ( modified ) with iterating $page_count and $current_page. http://rafb.net/p/TNa56h71.html

+2  A: 

This is probably an overcomplicated solution, but it works.

I've used an array here instead of just printing, which lets me "do-over" the logic.

Part of the problem occurs when "left and right of page" happens to coincide with left-and-right shoulders.

function cdotinator ( $current_page, $page_count ) 
{
  $stepsize = 3; 
  $elipse = '...';
  # Simple Case. 
  if ( $page_count <= 2 * $stepsize )
  {
    $out = range( 1, $page_count );
    $out[$current_page - 1 ] = '*' . $current_page . '*';
    return $out;
  }
  #Complex Case
  # 1) Create All Pages
  $out = range( 1, $page_count ); 
  # 2 ) Replace "middle" pages with "." placeholder elements 
  for( $i = $stepsize+1 ; $i <= ( $page_count - $stepsize ) ; $i ++ )
  {
    $out[ $i - 1 ] = '.' ; 
  }
  # 3.1 ) Insert the pages around the current page 
  for( $i =  max(1,( $current_page - floor($stepsize / 2) )) ;
       $i <= min( $page_count,( $current_page + floor( $stepsize/2))); 
       $i ++ )
  {
    $out[ $i - 1] = $i;
  }
  # 3.2 Bold Current Item
  $out[ $current_page - 1 ] = '*' . $current_page . '*' ; 

  # 4 ) Grep out repeated '.' sequences and replace them with elipses 
  $out2 = array(); 
  foreach( $out as $i => $v )
  {
    #  end, current  == peek() 
    end($out2);
    if( current($out2) == $elipse and $v == '.' )
    {
        continue;
    }
    if( $v == '.' )
    {
      $out2[] = $elipse; 
      continue;
    }
    $out2[]= $v;
  }

  return $out2;

}

Output can be seen here: http://dpaste.com/92648/

Kent Fredric
+3  A: 
<?php

/**
 * windowsize must be odd
 *
 * @param int $totalItems 
 * @param int $currentPage 
 * @param int $windowSize 
 * @param int $anchorSize 
 * @param int $itemsPerPage 
 * @return void
 */
function paginate($totalItems, $currentPage=1, $windowSize=3, $anchorSize=3, $itemsPerPage=10) {
    $halfWindowSize = ($windowSize-1)/2;

    $totalPages = ceil($totalItems / $itemsPerPage);
    $elipsesCount = 0;
    for ($page = 1; $page <= $totalPages; $page++) {
        // do we display a link for this page or not?
        if ( $page <= $anchorSize ||  
            $page > $totalPages - $anchorSize ||
            ($page >= $currentPage - $halfWindowSize &&
            $page <= $currentPage + $halfWindowSize) ||
            ($page == $anchorSize + 1 &&
             $page == $currentPage - $halfWindowSize - 1) ||
            ($page == $totalPages - $anchorSize &&  
             $page == $currentPage + $halfWindowSize + 1 ))
        {
            $elipsesCount = 0;
            if ($page == $currentPage)
                echo ">$page< ";
            else
                echo "[$page] ";
        // if not, have we already shown the elipses?
        } elseif ($elipsesCount == 0) {
            echo "... ";
            $elipsesCount+=1; // make sure we only show it once
        }
    }
    echo "\n";
}

//
// Examples and output
//

paginate(1000, 1, 3, 3);
// >1< [2] [3] ... [98] [99] [100] 

paginate(1000, 7, 3, 3);
// [1] [2] [3] ... [6] >7< [8] ... [98] [99] [100] 

paginate(1000, 4, 3, 3);
// [1] [2] [3] >4< [5] ... [98] [99] [100] 

paginate(1000, 32, 3, 3);
// [1] [2] [3] ... [31] >32< [33] ... [98] [99] [100] 

paginate(1000, 42, 7, 2);
// [1] [2] ... [39] [40] [41] >42< [43] [44] [45] ... [99] [100]
Great answer -- I'm now using a slightly watered down version as I don't need it as a function seeing as some of your variables are constants in mine. Note that there is a bug; you need to change "- 1" and "+ 1" on lines 25 and 27 respectively to "- 2" and "+ 2"
Andrew G. Johnson