Limiting Pagination to a certain number (range) of links.

9 posts by 3 authors in: Forums > CMS Builder
Last Post: May 9, 2013   (RSS)

By dwellingproductions - March 20, 2013

I have put together a working pagination (next and prev page links) setup for list pages.  The only problem with its current configuration is that at some point (when enough records are added to the database) it will run out of room when displaying page links because there is no limit to how many page links will be displayed.  Ultimately, I'd like the following functionality:

When 5 or less pages of information are listed, it will display: ← 1 2 3 4 5 →
When more than five pages are displayed, page numbers being displayed are limited to five: 1 2 3 4 5 ... →
When in the middle of the range of five page numbers, it will look like: ← ... 7 8 9 10 11 ... →

On the following page, I have three pagination examples.  The first (top) version is my original working pagination, without the range limiting feature.  The second (middle) version is an example of how it should look in the middle of the range containing many listed pages (when properly coded).  The third (bottom) is as far as I've been able to get with this with my limited PHP abilities.  :-)    

http://www.liviaglobal.com/health_articles_list.php

I feel like I'm really close.  I'm limiting the pages to five with a counter, but I can only get it to go from 1-5 and not utilize a range of 5 numbers starting on the current page.  (For example, if the current page is 8, it should display 8 9 10 11 12 with the next and prev arrows.  (The next and prev arrows should only appear when needed.)  

Instead of the way I have it currently set up, I basically need a way to limit the page link output to a range of page numbers that is displayed.  And, I need the "prev" arrow to only display when needed (similar to how I have the "next" arrow working).

Here is my code so far:

<!--  BEGIN PAGINATION  -->
<?php
  list($health_articles_contentRecords, $health_articles_contentMetaData) = getRecords(array(
    'tableName'   => 'health_articles_content',
    'perPage'     => '2',
  )); 
  $blog_contentRecord = @$blog_contentRecords[0]; // get first record
?>
<?php $counter = 0;  // set page counter to zero ?>
<?php $maxPageNumbers = 3;  // maximum number of page numbers to display ?>

 <?php if ($health_articles_contentMetaData['totalPages'] > 1): ?>
   <div class="pagination">
     <ul>
    <li class="prev">
           <?php if ($health_articles_contentMetaData['prevPage']): ?>
              <a href="<?php echo $health_articles_contentMetaData['prevPageLink'] ?>">&#8592;</a>
<?php else: ?>
            <?php endif ?>
          </li>
<?php foreach(range('1',$health_articles_contentMetaData['totalPages']) as $pageNumber): ?>
            <li <?php if($pageNumber == $health_articles_contentMetaData['page']): ?>class="curent"<?php endif; ?>>
              <a href="/health_articles_list.php?page=<?php echo $pageNumber; ?>"><?php echo $pageNumber; ?></a>
            </li>
           <?php if (++$counter == $maxPageNumbers) {break;} ?>
          <?php endforeach; ?>
<?php if ($counter > 1): ?>
              <li><span>...</span></li>
              <li <?php if($health_articles_contentMetaData['totalPages'] == $health_articles_contentMetaData['page']): ?>class="curent"<?php endif; ?>><a href="/health_articles_list.php?page=<?php echo $health_articles_contentMetaData['totalPages']; ?>"><?php echo $health_articles_contentMetaData['totalPages']; ?></a></li><?php endif ?>
     <li class="next">
  <?php if ($health_articles_contentMetaData['nextPage']): ?>
                  <a href="<?php echo $health_articles_contentMetaData['nextPageLink'] ?>">&#8594;</a>
                <?php else: ?>
                <?php endif ?>
              </li>
     </ul>
     </div><!-- .pagination -->
     <?php endif ?> 
<!--  END PAGINATION  -->

I've also attached my page so you can see my other working version (without any limiting in place).

Thanks, in advance, for any assistance.  :-)

- Jeremy

---------------------------

Dwelling Productions

www.dwellingproductions.com

By dwellingproductions - March 21, 2013

Just FYI, I just changed my sample page to: http://www.liviaglobal.com/health_articles_list_test.php  

(I have to go show the client the site's progress.)  :-)

- Jeremy

---------------------------

Dwelling Productions

www.dwellingproductions.com

By Jason - March 22, 2013

Hi Jeremy,

I've taken a look at your code and have come up with this example.  Please note that this code sample has not been tested:

<?php
  $maxPages       = 5;
  $currentPage    = coalesce($health_articles_contentMetaData['page'], 1);
  $maxDisplayPage = $currentPage + $maxPages - 1;
  $totalPages     = $health_articles_contentMetaData['totalPages'];
?>


  
      
  <?php if ($health_articles_contentMetaData['prevPage']): ?>
    <li class="prev">
      <a href="<?php echo $health_articles_contentMetaData['prevPageLink'] ?>">&#8592;</a>
    </li>
  <?php endif ?>
      
              
  <?php if ($currentPage > 1): // start with ...?>
    <li><span>...</span></li>
  <?php endif ?>
  
  <?php foreach (range($currentPage, $maxDisplayPage) as $page): ?>
    <?php if ($page == $currentPage): ?>
      <li class = "current">
    <?php else: ?>
      <li>
    <?php endif ?>
    <a href="/health_articles_list.php?page=<?php echo $page; ?>"><?php echo $page; ?></a>
      </li>
  <?php endforeach ?>
  
  
  <?php if ($maxDisplayPage > $totalPages): //end with ...?>
    <li><span>...</span></li>
  <?php endif ?>
  
  <?php if ($health_articles_contentMetaData['nextPage']): ?>
    <li class="next">
      <a href="<?php echo $health_articles_contentMetaData['nextPageLink'] ?>">&#8592;</a>
    </li>
  <?php endif ?>
  

Hope this helps get you started.

---------------------------------------------------
Jason Sauchuk - Project Manager
interactivetools.com

Hire me! Save time by getting our experts to help with your project.
http://www.interactivetools.com/consulting/

By dwellingproductions - March 24, 2013

Hi Jason!

That helped a ton!  Thank you very much!

It looks like the last issue I have is that even if there are less than three pages of articles, the pagination shows all five page links (even if there are only, say, 2 pages of articles).  So, two pages of articles, still shows: 1 2 3 4 5  

Similarly, once you get within five pages of the last page, I need to tell it to stop incrementing the page numbers, and simply show only the final five pages.  (Though, I did manage to get it to at least hide the right arrow and ellipsis.)  But, currently, if there are 22 pages of articles, once you hit page 18, the pagination should look like this: 18 19 20 21 22.  And, it should continue to look this way all the way up to page 22.  But, right now, when you get to page 22, it actually looks like this: 22 23 24 25 26

For an example of how it is currently functioning, you can see the very bottom pagination example on this page: http://www.liviaglobal.com/health_articles_list_test.php?page=19

I'll keep working with it.  But, if you have any ideas, I'm definitely all ears.  :-)

- Jeremy

---------------------------

Dwelling Productions

www.dwellingproductions.com

By Jason - March 27, 2013

Hi Jeremy,

Okay, I think I see the problem.  Try this change:

<?php
  $maxPages       = 5;
  $currentPage    = coalesce($health_articles_contentMetaData['page'], 1);
  $maxDisplayPage = min( ($currentPage + $maxPages - 1), $health_articles_contentMetaData['totalPages']);
  $totalPages     = $health_articles_contentMetaData['totalPages'];
?>

That should set maxDisplayPage to be the lowest of those 2 values, so you should never go beyond the totalPages number.

Hope this helps

---------------------------------------------------
Jason Sauchuk - Project Manager
interactivetools.com

Hire me! Save time by getting our experts to help with your project.
http://www.interactivetools.com/consulting/

By dwellingproductions - March 27, 2013 - edited: March 31, 2013

Hey Jason!

Thank you!  That took care of the issue with too many pages being displayed.  I've made a few more modifications and I now have one last question to get this exactly where it needs to be.

Everything works perfectly, displaying a maximum of 5 page numbers (when needed).  However, is there a way to set a minimum number of pages to display as well?  This is because when you are within 5 pages of the total number of pages, displayed page numbers begin dropping out.  So, for instance, if you have 22 pages, when on page 18, you see all 5 page numbers (18, 19, 20, 21, 22).  However, when you move to page 19, you now only see 4 page numbers (19, 20, 21, 22).  This continues until, on page 22, it only displays its own number.  However, on all those 5 final pages, all five page numbers should be visible (18, 19, 20, 21, 22).

Thanks for sticking with me this long.  Any ideas on this last item?  I sure appreciate it.  I tried a few things, but nothing even remotely worked.  :-)

- Jeremy

UPDATE: I figured out how to accomplish this.  See post below...

---------------------------

Dwelling Productions

www.dwellingproductions.com

By dwellingproductions - March 31, 2013

Hello all!  I just wanted to report back and let you know that I figured out how to achieve the desired effect.  I'm also posting the code below in case anyone tries to do this in the future.

Here's how it works:

     1 2 3 (Only 3 pages of articles, viewing any page 1-3 - the currently viewed list page will be highlighted)

     1 2 3 4 5 ... 16 (16 pages of articles, viewing page 1 of list results)

     1 ... 8 9 10 11 12 ... 16 (16 pages of articles, viewing page 8)

     1 ... 12 13 14 15 16 (16 pages of articles, viewing any page 12-16 - the currently viewed list page will be highlighted)

Here's the code:

Place in head section after loading viewer library (change information in red to match your CMSB configuration).  For some reason, I found it necessary to duplicate this information below also.

  // load records from 'blog_content'
  list($blog_contentRecords, $blog_contentMetaData) = getRecords(array(
    'tableName'   => 'blog_content',
    'perPage'     => '15',
  ));

Place in body section, wherever you want to include pagination.

<?php /* -- BEGIN PAGINATION  -- */ ?>

<?php
$sectionName = 'blog_content'; // ** CHANGE TO MATCH CMSB SECTION **
$pageLink = 'blog_list.php'; // ** CHANGE TO MATCH LIST PAGE **
  $maxPages       = 5; // ** Maximum amount of page numbers to display

  list($sectionNameRecords, $sectionNameMetaData) = getRecords(array(
    'tableName'   => $sectionName,
    'perPage'     => '15',
  )); 

  $currentPage    = coalesce($sectionNameMetaData['page'], 1);
  $maxDisplayPage = min( ($currentPage + $maxPages - 1), $sectionNameMetaData['totalPages']);
  $totalPages     = $sectionNameMetaData['totalPages'];
?>


<?php if ($totalPages <= $maxPages): //run this code if less total pages than maxPages ?>
 <?php if ($sectionNameMetaData['totalPages'] > 1): ?>
   <div class="pagination">
     <ul>
    <li class="prev">
           <?php if ($sectionNameMetaData['prevPage']): ?>
              <a href="<?php echo $sectionNameMetaData['prevPageLink'] ?>">&#8592;</a>
<?php else: ?>
            <?php endif ?>
          </li>
<?php foreach(range('1',$sectionNameMetaData['totalPages']) as $pageNumber): ?>
            <li <?php if($pageNumber == $sectionNameMetaData['page']): ?>class="current"<?php endif; ?>>
              <a href="<?php echo $pageLink; ?>?page=<?php echo $pageNumber; ?>"><?php echo $pageNumber; ?></a>
            </li>
          <?php endforeach; ?>
    <li class="next">
           <?php if ($sectionNameMetaData['nextPage']): ?>
           <a href="<?php echo $sectionNameMetaData['nextPageLink'] ?>">&#8594;</a>
            <?php else: ?>
            <?php endif ?>
          </li>
     </ul>
     </div><?php /* .pagination */ ?>
     <?php endif ?> 

<?php elseif ($currentPage >= ($totalPages - ($maxPages - 1))): //run this code if viewing one of last few pages as defined by maxPages ?>
 <?php if ($sectionNameMetaData['totalPages'] > 1): ?>
   <div class="pagination">
     <ul>
    <li class="prev">
           <?php if ($sectionNameMetaData['prevPage']): ?>
              <a href="<?php echo $sectionNameMetaData['prevPageLink'] ?>">&#8592;</a>
<?php else: ?>
            <?php endif ?>
            
<?php if ($currentPage > 1 && $maxDisplayPage > $maxPages): // show first page number ?>
              <li><a href="<?php echo $pageLink; ?>?page=1">1</a></li>
            <?php endif ?>
                          
            <?php if ($currentPage > 1 && $maxDisplayPage > $maxPages): // start with "..." ?>
              <li><span>...</span></li>
            <?php endif ?>
            
          </li>
<?php foreach(range(($totalPages - ($maxPages - 1)),$sectionNameMetaData['totalPages']) as $pageNumber): ?>
            <li <?php if($pageNumber == $sectionNameMetaData['page']): ?>class="current"<?php endif; ?>>
              <a href="<?php echo $pageLink; ?>?page=<?php echo $pageNumber; ?>"><?php echo $pageNumber; ?></a>
            </li>
          <?php endforeach; ?>
    <li class="next">
           <?php if ($sectionNameMetaData['nextPage']): ?>
           <a href="<?php echo $sectionNameMetaData['nextPageLink'] ?>">&#8594;</a>
            <?php else: ?>
            <?php endif ?>
          </li>
     </ul>
     </div><?php /* .pagination */ ?>
     <?php endif ?> 

<?php else: //run this code if more total pages than $maxPages ?>
 <?php if ($sectionNameMetaData['totalPages'] > 1): ?>
     <div class="pagination">
       <ul>
<?php if ($sectionNameMetaData['prevPage']): ?>
          <li class="prev">
            <a href="<?php echo $sectionNameMetaData['prevPageLink'] ?>">&#8592;</a>
          </li>
        <?php endif ?>
        
    <?php if ($currentPage > 1 && $maxDisplayPage > $maxPages): // show first page number ?>
      <li><a href="<?php echo $pageLink; ?>?page=1">1</a></li>
    <?php endif ?>
                  
    <?php if ($currentPage > 1 && $maxDisplayPage > $maxPages): // start with "..." ?>
      <li><span>...</span></li>
    <?php endif ?>
    
    <?php foreach (range($currentPage, $maxDisplayPage) as $page): ?>
      <?php if ($page == $currentPage): ?>
        <li class = "current">
      <?php else: ?>
        <li>
      <?php endif ?>
      <a href="<?php echo $pageLink; ?>?page=<?php echo $page; ?>"><?php echo $page; ?></a>
        </li>
    <?php endforeach ?>
    
    
    <?php if ($maxDisplayPage < $totalPages): //end with "..." ?>
      <li><span>...</span></li>
      
<?php if ($currentPage < $totalPages): // show last page number ?>
        <li><a href="<?php echo $pageLink; ?>?page=<?php echo $totalPages; ?>"><?php echo $totalPages; ?></a></li>
      <?php endif ?>
      
      <?php if ($sectionNameMetaData['nextPage']): ?>
        <li class="next">
          <a href="<?php echo $sectionNameMetaData['nextPageLink'] ?>">&#8594;</a>
        </li>
      <?php endif ?>
    <?php endif ?>
    
       </ul>
       </div><?php /* .pagination */ ?>
   <?php endif ?> 
  <?php endif ?>  

<?php /* -- /END PAGINATION  -- */ ?>

And, if you're interested, here's the CSS I used:

<style>

.pagination{
height: 39px;
border-top: 1px solid #e0e0e0;
border-bottom: 1px solid #e0e0e0;
text-align: center;
}
.pagination li{
display: inline-block;
border-right: 1px solid #e0e0e0;
}
.pagination li a,
.pagination li span{
display: block;
height: 39px;
padding: 0 15px;
margin: 0 0 0 -3px;
color: #777;
font:normal 13px/39px Arial, Verdana, serif;
text-decoration: none;
}
.pagination li.prev a,
.pagination li.next a{
font:normal 20px/32px Arial, Verdana, serif;
color: #444;
}
.pagination li.prev span,
.pagination li.next span{
font:normal 20px/32px Arial, Verdana, serif;
}
.pagination li.next {border: 0 none;}
.pagination li a:hover{
background: #eff7ff;
text-decoration: none;
}
.pagination li.current a{
background: #f3f4fa;
color: #444;
font-weight: bold;
text-decoration: none;
}
.pagination_info{
margin: 15px  0!important;
color: #777;
text-align: center;
font:italic 11px/11px Arial, Verdana, serif;
}

</style>

That's it!  Even though I'm sure some of this could be cleaner, I'm really happy with the way it turned out.  Hope it can be of some use to someone.  Thanks again to the wonderful help from the team at Interactive Tools!  :-)

- Jeremy

---------------------------

Dwelling Productions

www.dwellingproductions.com

By weblm - May 9, 2013 - edited: May 9, 2013

Here's some code I'm using to achieve a similar effect.  For mine, I always want to show the start and end numbers.  I also have a prev/next links if they apply.  Finally, you can control how many numbers show in the middle.

In the HEAD:

  // load records from 'press_room'
  list($press_roomRecords, $press_roomMetaData) = getRecords(array(
    'tableName'   => 'press_room',
    'perPage'     => '5',
    'loadUploads' => true,
    'allowSearch' => true,
    'orderBy'   => 'date DESC',
    //'debugSql'           => true,
  ));

Where you want the pagination code to be shown.  Change the numbers in red to control how many additional numbers you see on either side of the current page.

<!-- START PAGINATION CODE --> 
<div class="pagelinks">
<?php  
if (@!$_GET['page']): $current_page = "1"; 
else: $current_page = $_GET['page'];    
endif;  ?> 

<?php 
$startNumber = max($current_page - 2, 1); 
$endNumber   = min($current_page + 2, $press_roomMetaData['totalPages']); 
?>

<?php if ($press_roomMetaData['prevPage']): ?>
<a href="<?php echo $press_roomMetaData['prevPageLink'] ?>"><img src="/images/arrow-left.png" border="0" /> prev</a>&nbsp;&nbsp;&nbsp;
<?php if ($startNumber > '1'): ?>
<a href="?<?php echo http_build_query(array_merge($_REQUEST, array( 'page' => '1' ))) ?> ">1</a> ...
<?php endif ?> 
<?php else: ?>
&nbsp;  
<?php endif ?>

<?php foreach (range($startNumber,$endNumber) as $page): ?>

<?php if ($page == $current_page): ?> 
 <b>[<?php echo $page; ?>]</b> 
<?php else: ?> 
 <a href="?<?php echo http_build_query(array_merge($_REQUEST, array( 'page' => $page ))) ?>"><?php echo $page; ?></a> 
<?php endif ?> 

<?php endforeach; ?> 


<?php if ($press_roomMetaData['nextPage']): ?>
<?php if ($press_roomMetaData['totalPages'] > $endNumber): ?>
... <a href="?<?php echo http_build_query(array_merge($_REQUEST, array( 'page' => $press_roomMetaData['totalPages'] ))) ?> "><?php echo $press_roomMetaData['totalPages'];?></a> 
<?php endif ?> 
&nbsp;&nbsp;&nbsp;<a href="<?php echo $press_roomMetaData['nextPageLink'] ?>">next <img src="/images/arrow-right.png" border="0" /></a>  
<?php else: ?>   
&nbsp;  
<?php endif ?>
</div>
<!-- /END PAGINATION CODE -->

BTW....many thanks to this forum and Jason from Interactive tools for the help with this code.  My original post: http://www.interactivetools.com/forum/forum-posts.php?postNum=2216522

-Kevin

LM