Codeigniter pagination libraries - codeigniter

I'm looking for codeigniter pagination library, where my pages would be displayed like this:
1 2 3 4 5 ... 11 12 13 14 ... 27 28 29
I mean with adjacent. Where can I find it? My php knowledge is not so good to rewrite pagination library

use codeigniter user guide Pagination

try this code. You can change the logic according to your needs:-
let totalcount = Math.ceil(JSON.parse(this.response).total / limit), HTML = "", j = 1;
(page > 3) ? HTML += "<button>...</button>" : null;
(page === 1) ? page = page + 1 : (page === totalcount) ? page = (totalcount - 1) : page;
for (let i = Math.max(2, page - j); i <= Math.min(totalcount - 1, page + j); i++) {
HTML += "<button onclick=loadDoc(" + i + ")>" + (i) + "</button>"
}
(page < 10) ? HTML += "<button>...</button>" : null;
HTML += "<button onclick=loadDoc(" + totalcount + ")>" + (totalcount) + "</button>";
document.getElementById("pager").innerHTML = HTML;

Related

Get attribute or elements from page by script in nightwatch

I need a check that class elements was ui-state-active.
class="ui-state-default ui-state-active" href="#">15</a>
I am trying to using all methods and don't undestand how to write a code:
.perform(function () {
var arrAttr = [];
var arrCssProp = [];
var arrValue= [];
for (i = 1; i < 8; i++) {
for (j = 1; j < 7; j++) {
browser.useXpath();
browser.getCssProperty('//*[#id="ui-datepicker-div"]/table/tbody/tr[' + i + ']/td[' + j + ']', '.ui-state-default', function (result) {
arrCssProp[j, i] = result.value;
});
browser.getAttribute('//*[#id="ui-datepicker-div"]/table/tbody/tr[' + i + ']/td[' + j + ']', '.ui-state-default', function (result) {
arrAttr[j, i] = result.value;
});
browser.getValue('//*[#id="ui-datepicker-div"]/table/tbody/tr[' + i + ']/td[' + j + ']', '.ui-state-default', function (result) {
arrValue[j, i] = result.value;
});
browser.useCss();
writeLogLine('arrAttr:' + i + "|" + j + ' :' + arrAttr);
console.log('arrAttr:' + i + "|" + j + ' :' + arrAttr);
writeLogLine('arrCssProp:' + i + "|" + j + ' :' + arrCssProp);
console.log('arrCssProp:' + i + "|" + j + ' :' + arrCssProp);
writeLogLine('arrValue:' + i + "|" + j + ' :' + arrValue);
console.log('arrValue:' + i + "|" + j + ' :' + arrValue);
}
}
})
To get the attribute of class, you can write similar code
browser.getAttribute(pageObject.getElement('#ui'), "class", function (result) {
if (result.value.indexOf("ui-state-active")!=-1) {
console.log('class name:' + result.value);
}
else { console.log('class name:' + result.value); }});
You can use any locator strategy. To use CSS strategy based on class name, use .ui-state-default along with tagname.
Hope this helps.
Like in Rohit's example, if you want to use an attribute value, all the commands that rely on it need to be inside the callback. Doing arrCssProp[j, i] = result.value; won't work, since that value will disappear as soon as you exit the callback.
For more info, check out https://github.com/nightwatchjs/nightwatch/wiki/Understanding-the-Command-Queue

Algorithm for a Program which can convert Roman to Decimal

I need some help regarding algorithm, I have attached a problem in it which says that i have to develop an algorithm for a program which can convert Roman to Decimal.
I don't know how to do it, would prefer a complete algorithm but any help is appreciated.
It is an algorithm not a program!
The idea is to traverse the roman numeral string from end to start. For each character, add the corresponding number to the result. For some special
cases, such as ‘I’, ‘X’, ‘C’, check if the result is greater than the corresponding number. If yes, we need to subtract the number
from the result. If no, we need to add the number to the result.
res = 0
for each character c backwards:
if c =='I'
res += res + (res >= 5 ? -1 : 1)
else if c=='V'
res += res + 5
else if c=='X'
res += 10 * (res >= 50 ? -1 : 1)
else if c=='L'
res += 50;
else if c == 'C'
res += 100 * (res >= 500 ? -1 : 1)
else if c== 'D'
res += 500
else if c=='M'
res += 1000
return res
For example: MMDCCCXCIX
= 0 + MMDCCCXCIX
= 10 + MMDCCCXCI
= 9 + MMDCCCXC (as 10 > 5)
= 109 + MMDCCCX
= 99 + MMDCCC (as 109 > 50)
= 199 + MMDCC
= 299 + MMDC
= 399 + MMD
= 899 + MM
= 1899 + M
= 2899

How to append click event to handsontable row/column header?

I'm trying to implement some features like excel to click row/column header to select entire row/column, I think I should append a click event to all row/column header, so I tried add code below in core.js, but it was never been trigged:
this.click = function() {
alert("Clicked!");
};
So where should I begin with?
Thanks for any help.
Implemented by myself based on Handsontable 0.9.9:
From 5e2e8f51374741432d34624eb86edce6a802bf80 Mon Sep 17 00:00:00 2001
From: Xinfeng Li <xinfli#gmail.com>
Date: Wed, 17 Jul 2013 12:04:21 +0800
Subject: [PATCH 1/1] Implement select entire row/column when click on
row/column header.
---
src/3rdparty/walkontable/src/event.js | 5 ++++
src/3rdparty/walkontable/src/settings.js | 3 +-
src/pluginHooks.js | 3 ++
src/tableView.js | 50 ++++++++++++++++++++++++++++++++
4 files changed, 60 insertions(+), 1 deletion(-)
diff --git a/src/3rdparty/walkontable/src/event.js b/src/3rdparty/walkontable/src/event.js
index e150fef..a4cbb09 100644
--- a/src/3rdparty/walkontable/src/event.js
+++ b/src/3rdparty/walkontable/src/event.js
## -17,6 +17,11 ## function WalkontableEvent(instance) {
that.instance.getSetting('onCellMouseDown', event, cell.coords, cell.TD);
}
}
+ else if (cell.TD && cell.TD.nodeName === 'TH') {
+ if (that.instance.hasSetting('onHeaderMouseDown')) {
+ that.instance.getSetting('onHeaderMouseDown', event, cell.coords, cell.TD);
+ }
+ }
else if (that.wtDom.hasClass(event.target, 'corner')) {
that.instance.getSetting('onCellCornerMouseDown', event, event.target);
}
diff --git a/src/3rdparty/walkontable/src/settings.js b/src/3rdparty/walkontable/src/settings.js
index 35eb736..b16e4cf 100644
--- a/src/3rdparty/walkontable/src/settings.js
+++ b/src/3rdparty/walkontable/src/settings.js
## -41,8 +41,9 ## function WalkontableSettings(instance, settings) {
//callbacks
onCellMouseDown: null,
+ onHeaderMouseDown: null,
onCellMouseOver: null,
-// onCellMouseOut: null,
+ //onCellMouseOut: null,
onCellDblClick: null,
onCellCornerMouseDown: null,
onCellCornerDblClick: null,
diff --git a/src/pluginHooks.js b/src/pluginHooks.js
index afcc7e2..ececdd1 100644
--- a/src/pluginHooks.js
+++ b/src/pluginHooks.js
## -37,6 +37,9 ## Handsontable.PluginHookClass = (function () {
afterSelectionEndByProp : [],
afterCopyLimit : [],
+ // Customer plugin after row/column header clicked.
+ afterHeaderClick : [],
+
// Modifiers
modifyCol : []
}
diff --git a/src/tableView.js b/src/tableView.js
index 39512c0..ded6b74 100644
--- a/src/tableView.js
+++ b/src/tableView.js
## -242,6 +242,56 ## Handsontable.TableView = function (instance) {
that.settings.afterOnCellMouseDown.call(instance, event, coords, TD);
}
},
+ onHeaderMouseDown: function (event, coords, TD) {
+ var row = coords[0];
+ var col = coords[1];
+ var rangeRowStart, rangeColStart, rangeRowEnd, rangeColEnd;
+
+ //console.log("Clicked on header[row = " + row + ", col = " + col + "], TD.innerHTML.length: " + TD.innerHTML.length);
+ if ((row == 0) && (col == -1) && (TD.innerHTML.length == 0)) {
+ // Click on left upper corner
+ // Since the row and col is same when click on left upper corner and row heder of first row,
+ // The length of current TD.innerHTML must be checked.
+ rangeRowStart = 0;
+ rangeColStart = 0;
+ rangeRowEnd = instance.countRows() - 1;
+ rangeColEnd = instance.countCols() - 1;
+ }
+ else if (row == 0) {
+ if (col >= 0) {
+ // Click on column header
+ rangeRowStart = 0;
+ rangeColStart = col;
+ rangeRowEnd = instance.countRows() - 1;
+ rangeColEnd = col;
+ } else {
+ // Click on row header of first row
+ rangeRowStart = row;
+ rangeColStart = 0;
+ rangeRowEnd = row;
+ rangeColEnd = instance.countCols() - 1;
+ }
+ }
+ else if (col == -1) {
+ // Click on row header
+ rangeRowStart = row;
+ rangeColStart = 0;
+ rangeRowEnd = row;
+ rangeColEnd = instance.countCols() - 1;
+ }
+
+ if ((rangeRowStart != undefined) && (rangeColStart != undefined) && (rangeRowEnd != undefined) && (rangeColEnd != undefined)) {
+ //console.log("Select from [" + rangeRowStart + ", " + rangeColStart + "] to [" + rangeRowEnd + ", " + rangeColEnd + "]");
+ instance.selectCell(rangeRowStart, rangeColStart, rangeRowEnd, rangeColEnd);
+ }
+
+ if (!that.settings.fragmentSelection) {
+ event.preventDefault(); //disable text selection in Chrome
+ clearTextSelection();
+ }
+
+ instance.PluginHooks.run('afterHeaderClick', event, coords, TD);
+ },
/*onCellMouseOut: function (/*event, coords, TD* /) {
if (isMouseDown && that.settings.fragmentSelection === 'single') {
clearTextSelection(); //otherwise text selection blinks during multiple cells selection
--
1.8.1.msysgit.1

algorithm used to calculate 5 star ratings

I need to calculate 5-star ratings like the one on Amazon website. I have done enough search to find what is the best algorithm, but I am not able to get a proper answer. For example, if these are the ratings
5 star - 252
4 star - 124
3 star - 40
2 star - 29
1 star - 33
totally 478 reviews
Amazon has calculated this to be "4.1 out of 5 stars". Can anyone tell me how this figure is arrived at? I am not able to get this just by doing average.
That's a weighted average, where you weigh each rating with the number of votes it got:
(5*252 + 4*124 + 3*40 + 2*29 + 1*33) / (252+124+40+29+33) = 4.11 and change
If you are start calculation of overall rating from beginning then this formula will help you.
Formula
((Overall Rating * Total Rating) + new Rating) / (Total Rating + 1)
Example
suppose you have no ratings till now then formula is like,
overall rating is "0" till now.
total rating "0"
and given rating is "4"
((0*0)+4)/1 = 4
If overall rating is "4.11" Total rating is "478" And new rating
giving by one user is "2"
then formula is like
((4.11 * 478)+ 2)/479 // 479 is increment of new rating from 478
a better way to do this,
rating = (sum_of_rating * 5)/sum_of_max_rating_of_user_count
example:
total users rated: 6
sum_of_max_rating_of_user_count: 6 x 5 = 30
sum_of_rating: 25
rating = (25 * 5) / 30
Done!
Yes, you can average them out:
(5 * 252 + 4 * 124 + 3 * 40 + 2 * 29 + 1 * 33) / 478 = 4.11
Super helpful reply by Blindy, here's the PHP code that's based on it. Some may find useful. The results will be 4.11 as per OP's example:
$ratings = array(
5 => 252,
4 => 124,
3 => 40,
2 => 29,
1 => 33
);
function calcAverageRating($ratings) {
$totalWeight = 0;
$totalReviews = 0;
foreach ($ratings as $weight => $numberofReviews) {
$WeightMultipliedByNumber = $weight * $numberofReviews;
$totalWeight += $WeightMultipliedByNumber;
$totalReviews += $numberofReviews;
}
//divide the total weight by total number of reviews
$averageRating = $totalWeight / $totalReviews;
return $averageRating;
}
How to build the above $ratings array
Example pseudo code, but which should work that explains how to build the $ratings array when info is stored in DB assuming you have a table called "ratings" and a column called "rating". In this case it's 1 join, you would need to do 4 joins to get all ratings, but this should get you started:
SELECT count(c1.rating) as one_star, count(c2.rating) as two_star
FROM ratings c1
LEFT OUTER JOIN
ratings c2
ON
c1.id = c2.id
WHERE
c1.rating = 1
AND
c2.rating = 2
another approach suggested in comments
SELECT SUM(rating = 1) AS one_s ,SUM(rating = 2) AS two_s ,SUM(rating = 3) as three_s FROM reviews where product_id = 9
This rating system is based on a weighted average or weighted mean. That is, they used the weight in terms of stars to compute a decimal value which rounds to 4.1. For example:
Sum of (weight * number of reviews at that weight) / total number of reviews
(5*252 + 4*124 + 3*40 + 2*29 + 1*33) / 478 = 4.1
Weighted average, sum the number of stars times its weight, and then divide it through by the total number of reviews.
According to your question your solution will be like this.
Sum of (Rate*TotalRatingOfThatRate)/ TotalNumberOfReviews
((5*252)+(4*124)+(3*40)+(2*29)+(1*33)) / (252+124+40+29+33)
output will be 4.1
in Javascript
function calcAverageRating(ratings) {
let totalWeight = 0;
let totalReviews = 0;
ratings.forEach((rating) => {
const weightMultipliedByNumber = rating.weight * rating.count;
totalWeight += weightMultipliedByNumber;
totalReviews += rating.count;
});
const averageRating = totalWeight / totalReviews;
return averageRating.toFixed(2);
}
const ratings = [
{
weight: 5,
count: 252
},
{
weight: 4,
count: 124
},
{
weight: 3,
count: 40
},
{
weight: 2,
count: 29
},
{
weight: 1,
count: 33
}
];
console.log(calcAverageRating(ratings));
In addition, I am just trying to make practical and full code for all.
My Json Object Array
var yourRatingData =[{
review_id:1,
customer_id:5,
customer_name:"Faysal",
rating:5,
review_content:"I like this product it's cool and best in quality"
},
{
review_id:2,
customer_id:6,
customer_name:"Adams",
rating:4,
review_content:"It's quality product though price a bit high"
},
{
review_id:3,
customer_id:8,
customer_name:"Jane",
rating:3,
review_content:"I like but should improve quality"
},
{
review_id:4,
customer_id:9,
customer_name:"Julia",
rating:1,
review_content:"It's not good"
}];
Rating Calculation
let _5star = yourRatingData.filter(r=>r.rating==5).length;
let _4star = yourRatingData.filter(r=>r.rating==4).length;
let _3star = yourRatingData.filter(r=>r.rating==3).length;
let _2star = yourRatingData.filter(r=>r.rating==2).length;
let _1star = yourRatingData.filter(r=>r.rating==1).length;
//Sum of individual star.
let sumOfRating = parseInt( _5star + _4star + _3star + _2star + _1star );
//Total number of rating
let overallRating = parseInt( 5*_5star + 4*_4star + 3*_3star + 2*_2star +1*_1star );
//Average of all rating
let averageRating = parseFloat(overallRating/sumOfRating);
//Percentage of each star rating
let _5starPercentage = parseInt((_5star/totalRating)*100);
let _4starPercentage = parseInt((_4star/totalRating)*100);
let _3starPercentage = parseInt((_3star/totalRating)*100);
let _2starPercentage = parseInt((_2star/totalRating)*100);
let _1starPercentage = parseInt((_1star/totalRating)*100);
I think it's helpful.
This is an example method using flutter,
double starRating = 5.0;
getRating() {
// ! Check Already Accepted by others or Not -----------------------------------
//
int totalof5s = 0;
int totalof4s = 0;
int totalof3s = 0;
int totalof2s = 0;
int totalof1s = 0;
//
FirebaseFirestore.instance
.collection('usersRating')
.where("passengerUid", isEqualTo: "GNblJJJsjicaA2vkXJNJ6XCAiwa2")
.snapshots()
.forEach((querySnapshot) {
if (querySnapshot.size > 0) {
querySnapshot.docs.forEach((element) async {
if (element["rating"] == 5) {
totalof5s++;
} else if (element["rating"] == 4) {
totalof4s++;
} else if (element["rating"] == 3) {
totalof3s++;
} else if (element["rating"] == 2) {
totalof2s++;
} else if (element["rating"] == 1) {
totalof1s++;
}
//
if (this.mounted) {
setState(() {
starRating = (5 * totalof5s +
4 * totalof4s +
3 * totalof3s +
2 * totalof2s +
1 * totalof1s) /
(totalof5s + totalof4s + totalof3s + totalof2s + totalof1s);
});
}
});
} else {
// This is default one in any case these user doesn't have any rating document exists
if (this.mounted) {
setState(() {
starRating = 5.0;
});
}
}
});
}
(Total nunber of star / total number of persons who review * 5 ) * 5
= Answer
Fixed decimals in js to 1.
answer.toFixed(1);
Example the total reviews of 5 person is 20 star.
(20/5*5)*5 = 4.0
I used this way to calculate ratings and it is working perfectly
let one_star = 0;
let two_star = 0;
let three_star = 0;
let four_star = 0;
let five_star = 0;
Object.values(reviews).forEach(({ rating }) => {
switch (rating) {
case 1: one_star++; break;
case 2: two_star++; break;
case 3: three_star++; break;
case 4: four_star++; break;
case 5: five_star++; break;
}
});
let sum = one_star + two_star + three_star + four_star + five_star;
let average = ((5 * five_star) + (4 * four_star) + (3 * three_star) + (2 * two_star) + (1 * one_star)) / (sum);
console.log(average);

Algorithm / pseudo-code to create paging links?

Can someome provide code or pseudo-code for how the paging links on StackOverflow are generated?
I keep racking my brain but can't think of a decent way to build the dynamic links that always show the 2 pages around the current, plus the first and last.
Example: 1 ... 5 6 7 ... 593
There are several other answers already, but I'd like to show you the approach I took to solve it:
First, let's check out how Stack Overflow handles normal cases and edge cases. Each of my pages displays 10 results, so to find out what it does for 1 page, find a tag that has less than 11 entries: usability works today. We can see nothing is displayed, which makes sense.
How about 2 pages? Find a tag that has between 11 and 20 entries (emacs works today). We see: "1 2 Next" or "Prev 1 2", depending on which page we're on.
3 pages? "1 2 3 ... 3 Next", "Prev 1 2 3 Next", and "Prev 1 ... 2 3". Interestingly, we can see that Stack Overflow itself doesn't handle this edge case very well: it should display "1 2 ... 3 Next"
4 pages? "1 2 3 ... 4 Next", "Prev 1 2 3 ... 4 Next", "Prev 1 ... 2 3 4 Next" and "Prev 1 ... 3 4"
Finally let's look at the general case, N pages: "1 2 3 ... N Next", "Prev 1 2 3 ... N Next", "Prev 1 ... 2 3 4 ... N Next", "Prev 1 ... 3 4 5 ... N Next", etc.
Let's generalize based on what we've seen:
The algorithm seems to have these traits in common:
If we're not on the first page, display link to Prev
Always display the first page number
Always display the current page number
Always display the page before this page, and the page after this page.
Always display the last page number
If we're not on the last page, display link to Next
Let's ignore the edge case of a single page and make a good first attempt at the algorithm: (As has been mentioned, the code to actually print out the links would be more complicated. Imagine each place we place a page number, Prev or Next as a function call that will return the correct URL.)
function printPageLinksFirstTry(num totalPages, num currentPage)
if ( currentPage > 1 )
print "Prev"
print "1"
print "..."
print currentPage - 1
print currentPage
print currentPage + 1
print "..."
print totalPages
if ( currentPage < totalPages )
print "Next"
endFunction
This function works ok, but it doesn't take into account whether we're near the first or last page. Looking at the above examples, we only want to display the ... if the current page is two or more away.
function printPageLinksHandleCloseToEnds(num totalPages, num currentPage)
if ( currentPage > 1 )
print "Prev"
print "1"
if ( currentPage > 2 )
print "..."
if ( currentPage > 2 )
print currentPage - 1
print currentPage
if ( currentPage < totalPages - 1 )
print currentPage + 1
if ( currentPage < totalPages - 1 )
print "..."
print totalPages
if ( currentPage < totalPages )
print "Next"
endFunction
As you can see, we have some duplication here. We can go ahead and clean that up for readibility:
function printPageLinksCleanedUp(num totalPages, num currentPage)
if ( currentPage > 1 )
print "Prev"
print "1"
if ( currentPage > 2 )
print "..."
print currentPage - 1
print currentPage
if ( currentPage < totalPages - 1 )
print currentPage + 1
print "..."
print totalPages
if ( currentPage < totalPages )
print "Next"
endFunction
There are only two problems left. First, we don't print out correctly for one page, and secondly, we'll print out "1" twice if we're on the first or last page. Let's clean those both up in one go:
function printPageLinksFinal(num totalPages, num currentPage)
if ( totalPages == 1 )
return
if ( currentPage > 1 )
print "Prev"
print "1"
if ( currentPage > 2 )
print "..."
print currentPage - 1
if ( currentPage != 1 and currentPage != totalPages )
print currentPage
if ( currentPage < totalPages - 1 )
print currentPage + 1
print "..."
print totalPages
if ( currentPage < totalPages )
print "Next"
endFunction
Actually, I lied: We have one remaining issue. When you have at least 4 pages and are on the first or last page, you get an extra page in your display. Instead of "1 2 ... 10 Next" you get "1 2 3 ... 10 Next". To match what's going on at Stack Overflow exactly, you'll have to check for this situation:
function printPageLinksFinalReally(num totalPages, num currentPage)
if ( totalPages == 1 )
return
if ( currentPage > 1 )
print "Prev"
print "1"
if ( currentPage > 2 )
print "..."
if ( currentPage == totalPages and totalPages > 3 )
print currentPage - 2
print currentPage - 1
if ( currentPage != 1 and currentPage != totalPages )
print currentPage
if ( currentPage < totalPages - 1 )
print currentPage + 1
if ( currentPage == 1 and totalPages > 3 )
print currentPage + 2
print "..."
print totalPages
if ( currentPage < totalPages )
print "Next"
endFunction
I hope this helps!
The controls generally show controls for: P1, Pn, Pc (current page), Pc+1, Pc-1. The only time this changes is at either ends of the paging range {Pc < P3 or Pc > (Pn-3)}
The first step is to obviously work out the number of pages:
numPages = ceiling(totalRecords / numPerPage)
If you've got 4 or less, the drop out at this point, because, by the above rules, the paging is always going to be fixed (P1, P2, Pn-1, Pn), where one will acutally be Pc
else, you have three "states"
a. (Pc < P3) - so show P1, P2, P3, Pn, Next If Pc >1, show a 'prev' link before P1.
b. (Pc > Pn - 2), so show Prev, P1, Pn - 2, Pn -1, Pn, show a Next link if Pc < Pn
c. Show Prev, P1, Pc -1, Pc, Pc +1, Pn, Next
Easy as Pie in pseudo code. The loops can get a bit nasty when implemented as you've got to do some iterating in order to generate the links.
Edit:
Of course Prev and Next are identical to Pc +/- 1
Well, if you know the current page, it's pretty trivial to just subtract the number by 1, and add it by 1, then check those numbers against the bounds and display the first and last page always, then if they aren't in sequence, add the ellipses.
Or are you asking about getting the total number of pages and determining the current page number...?
public void PageLinks(int currentPage, int lastPage) {
if (currentPage > 2)
Add('[1]', '...');
for(int i=Math.Max(1, currentPage-1); i< Math.Min(currentPage+1, lastPage); i++)
Add('[i]');
if (currentPage < lastPage-1)
Add('...', '[lastpage]');
}
lastPage is calculated as Math.Ceiling(totalRecords/RecordsPerPage).
hmmm. actually, in the case that currentpage is 3, it still shows [1]...[2][3][4]...[xxx]
i think the ellipses are superfluous in that case. But that's how it works.
Edit: the preview formats the codeblock correctly, why does it get mangled? sure, its just pseudocode.... but still....
This is my approach to make a paging link. The following java code is just a pseudo.
package com.edde;
/**
* #author Yang Shuai
*/
public class Pager {
/**
* This is a method used to display the paging links(pagination or sometimes called pager).
* The totalPages are the total page you need to display. You can get this value using the
* formula:
*
* total_pages = total_records / items_per_page
*
* This methods is just a pseudo-code.
*
*
* #param totalPages how many pages you need to display
* #param currentPage you are in which page now
*/
public static void printPageLinks(int totalPages, int currentPage) {
// how many pages to display before and after the current page
int x = 2;
// if we just have one page, show nothing
if (totalPages == 1) {
return;
}
// if we are not at the first page, show the "Prev" button
if (currentPage > 1) {
System.out.print("Prev");
}
// always display the first page
if (currentPage == 1) {
System.out.print(" [1]");
} else {
System.out.print(" 1");
}
// besides the first and last page, how many pages do we need to display?
int how_many_times = 2 * x + 1;
// we use the left and right to restrict the range that we need to display
int left = Math.max(2, currentPage - 2 * x - 1);
int right = Math.min(totalPages - 1, currentPage + 2 * x + 1);
// the upper range restricted by left and right are more loosely than we need,
// so we further restrict this range we need to display
while (right - left > 2 * x) {
if (currentPage - left < right - currentPage) {
right--;
right = right < currentPage ? currentPage : right;
} else {
left++;
left = left > currentPage ? currentPage : left;
}
}
// do we need display the left "..."
if (left >= 3) {
System.out.print(" ...");
}
// now display the middle pages, we display how_many_times pages from page left
for (int i = 1, out = left; i <= how_many_times; i++, out++) {
// there are some pages we need not to display
if (out > right) {
continue;
}
// display the actual page
if (out == currentPage) {
System.out.print(" [" + out + "]");
} else {
System.out.print(" " + out);
}
}
// do we need the right "..."
if (totalPages - right >= 2) {
System.out.print(" ...");
}
// always display the last page
if (currentPage == totalPages) {
System.out.print(" [" + totalPages + "]");
} else {
System.out.print(" " + totalPages);
}
// if we are not at the last page, then display the "Next" button
if (currentPage < totalPages) {
System.out.print(" Next");
}
System.out.println();
}
public static void main(String[] args) {
// printPageLinks(50, 3);
help(500);
}
public static void test(int n) {
for (int i = 1; i <= n; i++) {
printPageLinks(n, i);
}
System.out.println("------------------------------");
}
public static void help(int n) {
for (int i = 1; i <= n; i++) {
test(i);
}
}
public static void help(int from, int to) {
for (int i = from; i <= to; i++) {
test(i);
}
}
}
Here is my algorithm. It works really nice:
// Input
total_items // Number of rows, records etc. from db, file or whatever
per_page // num items per page
page // current page
visible_pages // number of visible pages
// Calculations
lastPage = ceil(total_items / per_page);
prevPage = page - 1 < 1 ? 0 : page - 1;
nextPage = page + 1 > lastPage ? 0 : page + 1;
halfpages = ceil(visible_pages / 2);
startPage = page - halfpages < 1 ? 1 : page - halfpages;
endPage = startPage + visible_pages - 1;
if(endPage > lastPage) {
startPage -= endPage - lastPage;
startPage = startPage < 1 ? 1 : startPage;
endPage = startPage + visible_pages > lastPage ? lastPage : startPage + visible_pages - 1;
}
// Output
lastPage // Total number of pages
prevPage // Previous page number (if 0 there is no prev page)
nextPage // Next page number (if 0 there is no next page)
startPage // First visible page
endPage // Last visible page
So you can do a pager like this:
if prevPage
[1] [prevPage]
endif
[startPage] ... [endPage]
if nextPage
[nextPage] [lastPage]
endif
or customize whatever you like.

Resources