I recently ran into a problem with my pagination, it happens that there are like a 100 pages, so obviously my pagination becomes way to long.
Now I want to prevent this by removing some links, so instead of
1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10
I want to show it as
1 - 2 - 3 - 4 - 5 - ... - 10
Or when you're on page 4
1 - ... - 4 - 5 - 6 - ... 10
At the moment the script that displays my pagination goes like this:
$links = array();
for($i = 0; $i < $totalPages; $i++) {
array_push($links, $i);
}
foreach($links as $pageLink) {
if($pageLink == $page) {
$pagination .= "<li><a href='" . BASE_URL . $url . $pageLink . ".html' class='active'>" . ($pageLink + 1) . "</a></li>";
} else {
if($pageLink === '...') {
$pagination .= "<li><a href='#'>...</a></li>";
} else {
$pagination .= "<li><a href='" . BASE_URL . $url . $pageLink . ".html'>" . ($pageLink + 1) . "</a></li>";
}
}
}
I added all the links in an array so it would be easy to adjust this, but I can't figure out how I can get the pagination like that.
Somehow you can get the current page number and the last page number. The pager item which represents your current page should be somewhat different from your other pages. If your page number is smaller or equal than 3 you show 1 2 3 ... LastPageNumber and if your current page is greater or equal than LastPageNumber - 2 then your paging should look like 1 ... 67 68 69. Otherwise your paging should look like 1 ... 30 31 32 33 34 ... 69 (in this example your current page is 32).
Related
I have an pagination code:
//pagination
$result1=$mysqli->query("SELECT * FROM product");
$row_per_page=10 ;
$rows=$result1->num_rows;
if ($rows>$row_per_page) $page=ceil($rows/$row_per_page);
else $page=1;
if(isset($_GET['start']) && (int)$_GET['start'])
$start=$_GET['start'];
else
$start=0;
$result=$mysqli->query("SELECT * FROM product limit $start,$row_per_page");
//End pagination
while ($rows = $result->fetch_assoc()) {
echo $rows['name'];
}
$page_cr=($start/$row_per_page)+1;
for($i=1;$i<=$page;$i++)
{
if ($page_cr!=$i) echo "<div class='pagination'>"."<a href='index.php?go=product&start=".$row_per_page*($i-1)."'>$i </a>"."</div>";
else echo "<div class='pagination'>".$i." "."</div>";
}
This code create pagination like this
Yeah, i want to remove 6 7 8 9 ect... and replace with "...". When i click to page 6, it will remove 1 2 3 4 5 - 10 11 12 13 etc..,it only show 6 7 8 9 as image below
[![Pagination][2]][2]
I hope you can understand my ideal, i try the best to show you.
Thank you so much
Here's a solution to your pagination problem, the kind of solution Google uses to paginate it's search results. Basically, the idea behind this solution is this:
At any point of time, at most 5 pagination links will be displayed i.e. from the current page's perspective, display two predecessor and successor pages. Let me explain this thing using two scenarios,
Case(1): When the number of pages is equal to or less than 5 (Lets say we have 4 pages)
In this case, we have to display all pagination links without any preceding or succeeding dots, like this:
// User is on page 1
1 2 3 4
- - -
// User is on page 3
1 2 3 4
- - -
// User is on page 4
1 2 3 4
- - -
Case(2): When the number of pages is greater than 5 (Lets say we have 10 pages)
In this case, we have to display both the pagination links and dots accordingly, like this:
// User is on page 1
1 2 3 4 5 ...
- - - -
// User is on page 5
... 3 4 5 6 7 ...
- - - -
// User is on page 10
... 6 7 8 9 10
- - - -
So after getting the current page number using $page_cr=($start/$row_per_page)+1;, the algorithm of this custom pagination system would be like this:
Check whether the number of pages is greater than 5 or not. If it's greater than 5, go to step 2 otherwise go to step 5.
Find the superset range of pages, like 1-10, or 1-20 etc. For example, if $page = 10 then this superset range would be 1-10. The code for this step is this:
// Superset range of pages
$superset_range = range(1, $page);
Find the subset range of pages to display, like 1-5, or 3-7 etc. For example, if $page = 10 then this subset range would be 1-5, or 3-7, or 6-10 etc., it can be any consecutive five page between 1 and 10. Also, adjust this range whenever necessary. The code for this step is this:
// Subset range of pages to display
$subset_range = range($page_cr - 2, $page_cr + 2);
// Adjust the range
foreach($subset_range as $p){
if($p <= 0){
array_shift($subset_range);
$subset_range[] = $subset_range[count($subset_range) - 1] + 1;
}elseif($p > $page){
array_pop($subset_range);
array_unshift($subset_range, $subset_range[0] - 1);
}
}
Display the pagination links and dots accordingly. The code for this step is this:
// Display pagination links and dots
if($subset_range[0] > $superset_range[0]){
echo "<div class='pagination'>... </div>";
}
foreach($subset_range as $p){
if($page_cr != $p){
echo "<div class='pagination'>"."<a href='index.php?go=product&start=".$row_per_page*($p-1)."'>$p </a>"."</div>";
}else{
echo "<div class='pagination'>".$p." "."</div>";
}
}
if($subset_range[count($subset_range) - 1] < $superset_range[count($superset_range) - 1]){
echo "<div class='pagination'> ...</div>";
}
Display all pagination links using your old code, like this:
// Display all page links
for($i = 1; $i <= $page; $i++){
if($page_cr != $i){
echo "<div class='pagination'>"."<a href='index.php?go=product&start=".$row_per_page*($i-1)."'>$i </a>"."</div>";
}else{
echo "<div class='pagination'>".$i." "."</div>";
}
}
So here's the complete code:
$result1 = $mysqli->query("SELECT * FROM product");
$row_per_page= 10;
$rows=$result1->num_rows;
if ($rows > $row_per_page){
$page=ceil($rows/$row_per_page);
}else{
$page=1;
}
if(isset($_GET['start']) && (int)$_GET['start']){
$start=$_GET['start'];
}else{
$start=0;
}
$result=$mysqli->query("SELECT * FROM product limit $start,$row_per_page");
while ($rows = $result->fetch_assoc()) {
echo $rows['name'];
}
$page_cr=($start / $row_per_page) + 1; // Page number
if($page > 5){
// From the current page's perspective, display two predecessor and successor pages
// Superset range of pages
$superset_range = range(1, $page);
// Subset range of pages to display
$subset_range = range($page_cr - 2, $page_cr + 2);
// Adjust the range
foreach($subset_range as $p){
if($p <= 0){
array_shift($subset_range);
$subset_range[] = $subset_range[count($subset_range) - 1] + 1;
}elseif($p > $page){
array_pop($subset_range);
array_unshift($subset_range, $subset_range[0] - 1);
}
}
// Display pagination links and dots
if($subset_range[0] > $superset_range[0]){
echo "<div class='pagination'>... </div>";
}
foreach($subset_range as $p){
if($page_cr != $p){
echo "<div class='pagination'>"."<a href='index.php?go=product&start=".$row_per_page*($p-1)."'>$p </a>"."</div>";
}else{
echo "<div class='pagination'>".$p." "."</div>";
}
}
if($subset_range[count($subset_range) - 1] < $superset_range[count($superset_range) - 1]){
echo "<div class='pagination'> ...</div>";
}
}else{
// Display all page links
for($i = 1; $i <= $page; $i++){
if($page_cr != $i){
echo "<div class='pagination'>"."<a href='index.php?go=product&start=".$row_per_page*($i-1)."'>$i </a>"."</div>";
}else{
echo "<div class='pagination'>".$i." "."</div>";
}
}
}
So i have my pagination links like this.
for ( $counter = 0; $counter <= $page_amount; $counter += 1) {
echo "<a href=\"section.php?q=$section&p=$counter\">";
echo $counter+1;
echo "</a>";
}
And the links grows like:
1 2 3 4 5 6 7 and so on.
But i want to limit this so if there is more than 7 pages it shall only show 7 links like this:
1 2 3 ... 10 11 12
where 12 is the last page.
And if you go to next page it will only change the first pages like this:
3 4 5 ... 10 11 12
until you reach the last 7 pages like this:
6 7 8 9 10 11 12
How do i do this ??
please help.
Here is one way to do it.
// Set some presets
$current_page = 0;
$page_amount = 11;
$limiter = 7;
// Set upper and lower number of links
$sides = round(($limiter/2), 0, PHP_ROUND_HALF_DOWN);
for ( $counter = 0; $counter <= $page_amount; $counter++) {
// Start with Current Page
if($counter >= ($current_page)){
// Show page links of upper and lower
if(($counter <($current_page+$sides))||($counter >($page_amount-$sides))){
echo "<a href=\"section.php?q=$section&p=$counter\">";
echo $counter+1;
echo "</a> ";
}
// The middle link
elseif($counter ==($current_page+$sides)){
echo "<a href=\"page.php?p=$counter\">";
// Show number if number of links == $limiter
if(($page_amount-$current_page)==$limiter-1){
echo $counter+1;
}
// Show '...' number of links > $limiter
else {
echo "...";
}
echo "</a> ";
}
}
}
This allows to change the number of links shown, ie. from 7 to 9.
Note, using PHP_ROUND_HALF_DOWN in round() requires php>=5.3
What is the logic behind google's pagination behaviour?
My paginator goes something like this:
[1] 2 3 ... 184 >
< 1 [2] 3 4 ... 184 >
< 1 2 [3] 4 5 ... 184 >
< 1 2 3 [4] 5 6 ... 184 >
< 1 ... 3 4 [5] 6 7 ... 184 >
< 1 ... 4 5 [6] 7 8 ... 184 >
< 1 ... 5 6 [7] 8 9 ... 184 >
< 1 ... 6 7 [8] 9 10 ... 184 >
Here is a live version of the above example: http://www.dev.thomaskile.me/?page=test-zone&module=Paginator.
I know why this is happening; I've set the amount of page numbers to be shown on each side of current page to two (2).
I would rather have the range of numbers to be equal like this:
[1] 2 3 4 5 6 7 8 ... 184 >
< 1 [2] 3 4 5 6 7 ... 184 >
< 1 2 [3] 4 5 6 7 ... 184 >
< 1 2 3 [4] 5 6 7 ... 184 >
< 1 ... 3 4 [5] 6 7 ... 184 >
< 1 ... 4 5 [6] 7 8 ... 184 >
< 1 ... 5 6 [7] 8 9 ... 184 >
< 1 ... 6 7 [8] 9 10 ... 184 >
It's at the beginning and the end I need to make some changes, but can't figure out how to make it an easy operation...
I would like to make it flexible as well. Meaning I would like to be able to change the number of wanted pages on each side, and have the script expand and calculate it all...
Here is my code so far:
/**
* page controller buttons
* #param str $this->querySting href="URL string"
* #param str $this->pageIdentifier $_GET['this-name']
* #param int $this->numPages Total amount of pages
* #param int $this->midRange Number of pages to show on each side of current page
*/
public function prevPage()
{
if ($this->currentPage > 1){
$prevPage = ($this->currentPage - 1);
return 'prev';
}
}
public function nextPage()
{
if ($this->currentPage < $this->numPages) {
$nextPage = $this->currentPage + 1;
return 'next';
}
}
public function firstPage()
{
if ($this->currentPage > ($this->midRange + 1)) { // if number of pages between "currentPage" and "firstPage" exceeds $midRange with 1...
$firstPage .= '1'; // ...show "first page"-link
if ($this->currentPage > ($this->midRange + 2)) { // if number of pages between $currentPage and "first page" exceeds $midRange with more than 1
$firstPage .= '…'; // add "..." between "1st page"-link and first page in $range
}
}
return $firstPage;
}
public function lastPage()
{
if ($this->currentPage < ($this->numPages - $this->midRange)) { // if number of pages between "currentPage" and "last page" is equal to $midRange
if (($this->currentPage < ($this->numPages - $this->midRange) - 1)) { // if number of pages between $currentPage and "last page" exceeds $range with more than two
$lastPage .= '…'; // add "..." between "last page"-link and last page in $range
}
$lastPage .= ''.$this->numPages.''; // show "last page"-link
}
return $lastPage;
}
# Range of pages between (prev first ...) and (... last next)
public function listPages()
{
for ($i = ($this->currentPage - $this->midRange); $i < (($this->currentPage + $this->midRange) + 1); $i++){
if (($i > 0) && ($i <= $this->numPages)) // if page number are within page range
{
if ($i == $this->currentPage) { $listPages .= '<a class="current">'.$i.'</a>'; } // if we're on current page
else { $listPages .= ''.$i.''; } // if not current page
}
}
return $listPages;
}
This is what I do for my Pagination.
$startPage = $currentPage - 4;
$endPage = $currentPage + 4;
if ($startPage <= 0) {
$endPage -= ($startPage - 1);
$startPage = 1;
}
if ($endPage > $totalPage)
$endPage = $totalPage;
if ($startPage > 1) echo " First ... ";
for($i=$startPage; $i<=$endPage; $i++) echo " {$i} ";
if ($endPage < $totalPage) echo " ... Last ";
I believe my code is self-explained, but I will try to explain it in plain English. First of all, you need to know two things before you can generate Pagination: $totalPage and $currentPage.
Step 1: Assuming that the current page is in mid-range. $startPage and $endPage store range of page that pagination try to generate.
Step 2: If $startPage is negative, then you need to make-up for $endPage.
Step 3: If $endPage excess $totalPage, then $endPage is the last page.
Step 4: Generating Pagination into HTML. (it is up to you how you want your pagination to look. I will simply use plain text to represent my pagination)
if ($startPage > 1) echo " First ... ";
for($i=$startPage; $i<=$endPage; $i++) echo " {$i} ";
if ($endPage < $totalPage) echo " ... Last ";
Fixed flaw to my previous logic
$startPage = ($curPage < 5)? 1 : $curPage - 4;
$endPage = 8 + $startPage;
$endPage = ($totalPage < $endPage) ? $totalPage : $endPage;
$diff = $startPage - $endPage + 8;
$startPage -= ($startPage - $diff > 0) ? $diff : 0;
if ($startPage > 1) echo " First ... ";
for($i=$startPage; $i<=$endPage; $i++) echo " {$i} ";
if ($endPage < $totalPage) echo " ... Last ";
This conversation was a great start for me! But I wanted a paginator closer to the intentions of the original question, that:
1) Could be contained in a function with variables to alter the total pages, current page, and number of pages on each side of the current to show.
2) Maintains a constant width, similar to the original post:
< [1] 2 3 4 5 6 7 ... 99 >
< 1 [2] 3 4 5 6 7 ... 99 >
< 1 2 [3] 4 5 6 7 ... 99 >
< 1 2 3 [4] 5 6 7 ... 99 >
< 1 2 3 4 [5] 6 7 ... 99 >
< 1 ... 4 5 [6] 7 8 ... 99 >
< 1 ... 5 6 [7] 8 9 ... 99 >
< 1 ... 92 93 [94] 95 96 ... 99 >
< 1 ... 93 94 [95] 96 97 98 99 >
< 1 ... 93 94 95 [96] 97 98 99 >
< 1 ... 93 94 95 96 [97] 98 99 >
< 1 ... 93 94 95 96 97 [98] 99 >
< 1 ... 93 94 95 96 97 98 [99] >
3) Continues to display the number "2" rather than "..." in cases where you would have 1 ... 3
4) Same thing for the end.
So here's what I did. I am coding in a different language (coffeescript), but it should function as good sudo-code anyway:
get_pages_array = (total_page, each_side, curr_page) ->
if total_page <= (2*each_side)+5
# in this case, too few pages, so display them all
start_page = 1
end_page = total_page
else if curr_page<=each_side+3
# in this case, curr_page is too close to the beginning
start_page = 1
end_page = (2*each_side)+3
else if curr_page >= total_page - (each_side+2)
# in this case, curr_page is too close to the end
start_page = total_page - (2*each_side) - 2
end_page = total_page
else
# regular case
start_page = curr_page - each_side
end_page = curr_page + each_side
return_me = []
if start_page> 1
return_me.push "1"
if start_page>2
return_me.push "..."
for x in [start_page..end_page]
return_me.push x
if end_page<total_page-1
return_me.push "..."
if end_page<total_page
return_me.push total_page
return return_me
I am using this code for each_side = 2, so that's where I'm sure it works.
EDIT: fixed logic as per #Vextil
Here's a Python program that shows how to do this correctly:
def main():
num_pages = 13
page = 12
window = 5
start = page - window
end = page + window - 1
if start <= 0:
end = end - start + 1
start = 1
if end > num_pages:
end = num_pages
start = max(end - (window * 2) + 1, 1)
for no in range(start, end + 1):
print "{}*".format(no) if page == no else no
if __name__ == '__main__':
main()
This is pure awesome! I think I got this paginator to work the way I described.
Please, have a look and try it out here http://dev.thomaskile.me/?page=test-zone&module=Paginator and let me know...
After a lot of logical math studying I finally came to this conclusion:
In order to make this act so differently on different levels, there have to be some if, elsef-s to handle the logic on each level seperatly. I'll try to explain, but find it hard to do in a good way...
These are the levels I'm talking about:
If currentPage == firstPage :
Calculate how many pages to show after currentPage starting from 2nd page.
This calculation needed to be done based on how many page boxes there would be at the most. (midRange value is a key factor here)
[1] 2 3 4 5 6 7 8 ... 184 >
elseif currentPage is in between firstPage and midRange value maxed out.
Reduce pages in range by one to prevent moving the whole paginator to the right once prevPage is added.
Calculate pages to show before and after currentPage to keep the amount of pages equal trough the whole thing.
< 1 [2] 3 4 5 6 7 ... 184 >
< 1 2 [3] 4 5 6 7 ... 184 >
< 1 2 3 [4] 5 6 7 ... 184 >
elseif midRange value is maxed out on each side. Meaning we're in the middle somewhere.
midRange pages + the current page + midRange pages. Quite straight forward i guess...
< 1 ... 3 4 [5] 6 7 ... 184 >
...
...
...
< 1 ... 178 179 [180] 181 182 ... 184 >
elseif currentPage is in between midRange value and lastPage
Almost the same as in the beginning. Difference was to calculate a static pagenumber to start pages from, then calculate pages to show before/after current page...
(this, by the way, has been my headache this weekend)
< 1 ... 178 179 180 [181] 182 183 184 >
< 1 ... 178 179 180 181 [182] 183 184 >
< 1 ... 178 179 180 181 182 [183] 184 >
elseif currentPage == numPages (number of tatal pages).
Pretty much same as firstPage operation... calculating how many pages needed to fill the whole thing up and calculate where to start from...
What I need to do now is to make the code itself better...
< 1 ... 178 179 180 181 182 183 [184] >
The "problem" in my case was that the whole paginator should calculate everything based on the midRange value and nothing else.
For me to execute this paginator in any of my future project, all I have to do is:
$paginator = new paginator((int)); // e.g. number of total results from a db request
I might in most cases need to add a personal querystring to make sure the a href is working:
$paginator->set_queryString('my querystring');
And that's pretty much all. I've set up a couple of optional functions like this:
$paginator->set_resultsPerPage((int));
$paginator->set_midRange((int));
$paginator->set_pageIdentifier('querystring-pageNumber-identifier-name-for-get'); // whatever I needed
Finally i display the paginator page controller like this:
$paginator->pageController('full'); // full, med, min for different styles.
If non of these are good enough, i could just call each button like this:
$paginator->prevPage();
$paginator->firstPage();
$paginator->listPages();
$paginator->lastPage();
$paginator->nextPage();
$paginator->pageJumper();
$paginator->perPageSelector();
I assume your pagination have this structure:
number_of_active_page + separate(...) + page(184) + next_page(>)
You can set number_of_active_page become 8
( include prev_page(<) + pages ( ... and page number )
[1] 2 3 4 5 6 7 8 ... 184 >
[number_of_active_page(set to 8)] + separate + page + next_page
< 1 ... 3 4 [5] 6 7 ... 184 >
import math
size = 3
len = 13
for page in range(1,10):
if(( size*(page-1) ) >len):
startPoint = (size*(page-1)) - (size*(page- math.ceil(len/size)))
else:
startPoint = ( size*(page-1) )
if((startPoint +size)>len):
endPoint = len
else:
endPoint = (startPoint +size -1)
print("Page = "+str(page))
print("start = " +str(startPoint))
print("end = " +str(endPoint))
print()
Hear is a simple example of pagination display:
$paginationDisplay = ""; // Initialize the pagination output variable
// This code runs only if the last page variable is not equal to 1,
// if it is only 1 page we require no paginated links to display
if ($lastPage != "1"){
// This shows the user what page they are on, and the total number of pages
$paginationDisplay .= 'Page <strong>' . $pn .
'</strong> of ' . $lastPage. 'last';
// If we are not on page 1 we can place the Back button
if ($pn != 1) {
$previous = $pn - 1;
$paginationDisplay .= ' <a href="' .
$_SERVER['PHP_SELF'] . '?pn=' . $previous . '"> Back</a> ';
}
// Lay in the clickable numbers display here between the Back and Next links
$paginationDisplay .= '<span>' . $centerPages . '</span>';
// If we are not on the very last page we can place the Next button
if ($pn != $lastPage) {
$nextPage = $pn + 1;
$paginationDisplay .= ' <a href="' .
$_SERVER['PHP_SELF'] . '?pn=' . $nextPage . '"> Next</a> ';
}
}
This is the pagination logic I have
$pLinks = 5; // Links per page
$pMids = 3;
$pTot = 10; // Total page
$pSel = 1 // Selected page
if (($pSel <= $pMids) || ($pTot <= $pLinks)) {
$sPage = 1;
$ePage = ($pTot <= $pLinks) ? $pTot : $pLinks;
} else {
$etPage = $pSel + ($pMids - 1);
$ePage = ($etPage <= $pTot) ? $etPage : $pTot;
$sPage = $ePage - ($pLinks - 1);
}
if ($pSel > $sPage) {
$sL = 'First';
$sN = '«';
} else {
$sL = 'First';
$sN = '«';
}
if ($pSel < $ePage) {
$eL = 'End';
$eN = '»';
} else {
$eL = 'End';
$eN = '»';
}
$pOptions = '';
$pOptions .= '<span class="iPage">'.$pSel.'/'.$pTot.'</span>';
$pOptions .= '<span class="renderFL">'.$sL.'</span>';
$pOptions .= '<span class="renderPN">'.$sN.'</span>';
for ($i = $sPage; $i <= $ePage; $i++) {
if($i != $pSel) {
$pOptions .= '<span>'.$i.'</span>';
} else {
$pOptions .= '<span class="selected">'.$i.'</span>';
}
}
$pOptions .= '<span class="renderPN">'.$eN.'</span>';
$pOptions .= '<span class="renderFL">'.$eL.'</span>';
The result would be look like this:
1 -> [1] 2 3 4 5
2 -> 1 [2] 3 4 5
3 -> 1 2 [3] 4 5
..
5 -> 3 4 [5] 6 7
6 -> 4 5 [6] 7 8
..
8 -> 6 7 [8] 9 10
9 -> 6 7 8 [9] 10
10 -> 6 7 8 9 [10]
I have a pagination script which I have posted below, the problem is I have alot of data so I end with a huge list of pages, I want to make it show only 10 pages at a time and then maybe the last 2 pages like this:
previous 1 2 3 4 5 6 7 8 9...24 25 next
is there anyway I can change the code to do this. Below is the included pagination script I can include the other part of script if needed.
<?php
//source unknown for logic of showPageNumbers()
//modified by drale.com - 1-19-2010
//added query_string reproduction and divs
//added showNext() and showPrev()
class Pagination
{
function getStartRow($page,$limit)
{
$startrow = $page * $limit - ($limit);
return $startrow;
}
function showPageNumbers($totalrows,$page,$limit)
{
$query_string = $this->queryString();
$pagination_links = null;
/*
* PAGINATION SCRIPT
* seperates the list into pages
*/
$numofpages = $totalrows / $limit;
/* We divide our total amount of rows (for example 102) by the limit (25). This
will yield 4.08, which we can round down to 4. In the next few lines, we'll
create 4 pages, and then check to see if we have extra rows remaining for
a 5th page. */
for ($i = 1; $i <= $numofpages; $i++) {
/* This for loop will add 1 to $i at the end of each pass until $i
is greater than $numofpages (4.08). */
if ($i == $page) {
$pagination_links .= '<div class="page-link"><span>' . $i
. '</span></div> ';
} else {
$pagination_links .= '<div class="page-link"><a href="?page=' . $i
. '&' . $query_string . '">' . $i . '</a></div> ';
}
/* This if statement will not make the current page number available
in link form. It will, however, make all other pages available
in link form. */
} // This ends the for loop
if (($totalrows % $limit) != 0) {
/* The above statement is the key to knowing if there are remainders, and it's
all because of the %. In PHP, C++, and other languages, the % is known as a
Modulus. It returns the remainder after dividing two numbers. If there is no
remainder, it returns zero. In our example, it will return 0.8 */
if ($i == $page) {
$pagination_links .= '<div class="page-link"><span>' . $i
. '</span></div> ';
} else {
$pagination_links .= '<div class="page-link"><a href="?page=' . $i
. '&'.$query_string.'">'.$i.'</a></div> ';
}
/* This is the exact statement that turns pages into link
form that is used above */
} // Ends the if statement
return $pagination_links;
}
//added by drale.com - 1-19-2010
function showNext($totalrows,$page,$limit,$text="next »")
{
$next_link = null;
$numofpages = $totalrows / $limit;
if ($page < $numofpages) {
$page++;
$next_link = '<div class="page-link"><a href="?page=' . $page
. '&'.$query_string.'">' . $text . '</a></div>';
}
return $next_link;
}
function showPrev($totalrows,$page,$limit,$text="« prev")
{
$next_link = null;
$numofpages = $totalrows / $limit;
if ($page > 1) {
$page--;
$prev_link = '<div class="page-link"><a href="?page=' . $page
. '&' . $query_string . '">'.$text.'</a></div>';
}
return $prev_link;
}
function queryString()
{
//matches up to 10 digits in page number
$query_string = eregi_replace("page=[0-9]{0,10}&","",$_SERVER['QUERY_STRING']);
return $query_string;
}
}
?>
Untested, but this should always show pages 1 - 3 and the last 3 pages of the list. Otherwise, it will only ever show the previous 3 pages and the next three pages from the current one you're on. (whenever the amount of pages is greater than 10)
$alwaysShowPages = array(1, 2, 3);
// dynamically add last 3 pages
for ($i = 3; $i >= 0; $i--) {
$alwaysShowPages[] = $numofpages - $i;
}
for ($i = 1; $i <= $numofpages; $i++) {
$showPageLink = true;
if ($numofpages > 10 && !in_array($i, $alwaysShowPages)) {
if (($i < $page && ($page - $i) > 3)
|| ($i > $page && ($i - $page) > 3)
) {
$showPageLink = false;
}
}
if ($showPageLink) {
if ($i == $page) {
$pagination_links .= '<div class="page-link"><span>'.$i.'</span></div> ';
} else {
$pagination_links .= '<div class="page-link">'.$i.'</div> ';
}
}
}
I have a version that does this:
1 | 2 | 3 | 4 | 5 | 6 ... 554 | 555 | 556
1 | 2 | 3 | 4 | 5 | 6 ... 554 | 555 | 556
1 | 2 | 3 ... 278 | 279 | 280 ... 554 | 555 | 556
1 | 2 | 3 ... 415 | 416 | 417 ... 554 | 555 | 556
1 | 2 | 3 | 553 | 554 | 555 | 556
The ... are actually links that go halfway between current page and 1st of the next (or last) group of links.
I made it so the 1st 6 pages always appear if current page is less than 5.
But I made all parameters dynamic, so you can change variables like:
$end_links = 3; // set number of links at each end to always show
$center_links; // number of links including current page to show 'floating' in center
It took me hours to do it, which is pretty sad. Oh well.
Just use arrays a lot, and figure out how to add the right values to it. It's simple math and logic, really.
I have the following method that creates and returns markup for my pagination links in PHP.
public function getPaginationLinks($options) {
if($options['total_pages'] > 1) {
$markup = '<div class="pagination">';
if($options['page'] > 1) {
$markup .= '< prev';
}
for($i = 1; $i <= $options['total_pages']; $i++) {
if($options['page'] != $i) {
$markup .= '' . $i . '';
}
else {
$markup .= '<span class="current">' . $i . '</span>';
}
}
if($options['page'] < $options['total_pages']) {
$markup .= 'next >';
}
$markup .= '</div>';
return $markup;
}
else {
return false;
}
}
I just recently discovered (to my surprise) that i had reached 70+ pages which means that there are now 70+ links showing up at the bottom..
I'm wondering if someone can help me break this up.. I'm not sure how most pagination works as far as showing the numbers if im on say.. page 30, ideas?
You just display the current page plus the previous and the following x (say 4) pages.
If you're on Page 1:
1 2 3 4 5
Page 35:
31 32 33 34 35 36 37 38 39
Page 70:
66 67 68 69 70
You could also add a quick link to the first and last page using « and » for instance.
Example:
$x = 4;
for ($i = $currentPage - $x; $i < $currentPage; $i++)
{
if ($i >= 1) { /* show link */}
else { /* show ellipsis and fix counter */ $i = 1; }
}
/* show current page number without link */
for ($i = $currentPage + 1; $i < $currentPage + $x; $i++)
{
if ($i <= $totalPages) { /* show link */}
else { /* show ellipsis and break */ break; }
}
You can also implement Infinite History / Pagination, which is uber cool. =)
UPDATE: A more elegant version of this # Codepad.
You could do (on page 15)
[View Previous] 12 13 14 [15] 15 17 18 [View More]
Where the [View More] link fetches the rest (or just a few more) page links. This keeps things uncluttered while allowing the user to navigate all the pages.
Example (after clicking View Previous)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 [15] 15 17 18 [View More]
or (just show a few more)
[View More] 7 8 9 10 11 12 13 14 [15] 15 17 18 [View More]
When I say "fetch" I mean use javascript to create links to the other pages w/o reloading the page
Consider "logarithmic pagination", as described here (PHP code included):
How to do page navigation for many, many pages? Logarithmic page navigation
You may also look at Zend_Paginator, which handles lots of these types of things for you.