(最初这是作为方法提示发布的,我的答案包含在问题中。我现在将我的答案分成下面的“答案”部分)。
更具体一点:
假设您正在向用户显示一组记录,并将其分解为固定大小的页面(例如,Google搜索的结果)。如果只有几页,您可以在结果的末尾显示一个页面导航区域,如下所示:
[<< [<] 1 2 3 4 5 6 7 8 9 10 11 12 13 [> ] [>> ]
但如果结果超过20或30页,这很快就变得不合时宜了。
有时你会看到这样的事情:
[<< ] [<] ... 665 666 667 668 669 670 671 672 673 ... [> ] [>> ]
或者这个:
[<< ] [<] 1 2 3 ... 667 668 669 670 671 ... 845 846 847 [> ] [>> ]
但是在这两种情况下,导航到“......”部分中间的任何位置都会花费很多很多的mousclicks。有时会提供用于直接输入页码的输入框;否则(假设我们在这里谈论一个网页),精明的用户可能会查看URL,看看他们是否可以直接编辑它。
最好的方法是让分页显示让用户只需几次鼠标点击就可以访问任何页面,而不会有太多可笑的链接。
如何才能实现这一目标?
答案 0 :(得分:25)
这可以通过根据与端点或当前页面的距离以对数方式分布页码来实现。这是我的意思的一个例子:
1 2 3 4 5 6。 10。 20。 30。 40。 50 .. 100 .. 200。 210。 220。 230。 240。 250。 252 253 254 255 256 257 258 259 260 261 262。 270。 280。 290。 300。 310 .. 400 .. 500 .. 600 .. 700 .. 800 .. 900 .. 950。 960 970 980 990 995 996 997 998 999 1000
请注意,在间隙中,编号从1秒到10秒到100秒(等等)。 (我使用的是10的幂,但原则上你可以使用不同的方案 - 比如2的幂)。
我在2004年写了一些代码来做这件事,我想我会在这里分享一下。有PHP和ASP版本,但逻辑应该很容易翻译成任何语言。请注意,底部的位(在两种情况下)只显示一些示例。显然格式化需要自定义以匹配您的网页(或应用程序),所以这里非常基础。更改LINKS_PER_STEP
中的paginationHTML
以确定在步长增加之前显示的数量,当您离开端点或当前页面时。
对于更紧凑的输出,您还可以考虑更改代码,以使编号在端点周围不“密集”(即仅在当前页面周围密集)。
以下是代码:
<?
// Used by paginationHTML below...
function paginationLink($p, $page, $URL)
{
if ($p==$page) return '<b style="color:#C0C0C0">' . $p . '</b>';
return '<a href="' . $URL . $p . '">' . $p . '</a>';
}
// Used by paginationHTML below...
function paginationGap($p1, $p2)
{
$x = $p2-$p1;
if ($x==0) return '';
if ($x==1) return ' ';
if ($x<=10) return ' . ';
if ($x<=100) return ' .. ';
return ' ... ';
}
// URL requires the $page number be appended to it.
// e.g. it should end in '&page=' or something similar.
function paginationHTML($page, $lastPage, $URL)
{
$LINKS_PER_STEP = 5;
// Nav buttons
if ($page>1)
$result = '<form action="' . $URL . '1" method="POST" style="display:inline"><input type="submit" value=" |< "></form> ' .
'<form action="' . $URL . ($page-1) . '" method="POST" style="display:inline"><input type="submit" value=" < "></form>';
else $result = '<input type="button" value=" |< " disabled> <input type="button" value=" < " disabled>';
$result .= ' ' . $page . ' ';
if ($page<$lastPage)
$result .= '<form action="' . $URL . ($page+1) . '" method="POST" style="display:inline"><input type="submit" value=" > "></form> ' .
'<form action="' . $URL . $lastPage . '" method="POST" style="display:inline"><input type="submit" value=" >| "></form>';
else $result .= '<input type="button" value=" > " disabled> <input type="button" value=" >| " disabled>';
$result .= "<br>";
// Now calculate page links...
$lastp1 = 1;
$lastp2 = $page;
$p1 = 1;
$p2 = $page;
$c1 = $LINKS_PER_STEP+1;
$c2 = $LINKS_PER_STEP+1;
$s1 = '';
$s2 = '';
$step = 1;
while (true)
{
if ($c1>=$c2)
{
$s1 .= paginationGap($lastp1,$p1) . paginationLink($p1,$page,$URL);
$lastp1 = $p1;
$p1 += $step;
$c1--;
}
else
{
$s2 = paginationLink($p2,$page,$URL) . paginationGap($p2,$lastp2) . $s2;
$lastp2 = $p2;
$p2 -= $step;
$c2--;
}
if ($c2==0)
{
$step *= 10;
$p1 += $step-1; // Round UP to nearest multiple of $step
$p1 -= ($p1 % $step);
$p2 -= ($p2 % $step); // Round DOWN to nearest multiple of $step
$c1 = $LINKS_PER_STEP;
$c2 = $LINKS_PER_STEP;
}
if ($p1>$p2)
{
$result .= $s1 . paginationGap($lastp1,$lastp2) . $s2;
if (($lastp2>$page)||($page>=$lastPage)) return $result;
$lastp1 = $page;
$lastp2 = $lastPage;
$p1 = $page+1;
$p2 = $lastPage;
$c1 = $LINKS_PER_STEP;
$c2 = $LINKS_PER_STEP+1;
$s1 = '';
$s2 = '';
$step = 1;
}
}
}
?>
<br><br><br>
<?=paginationHTML(1,1,'?page=')?>
<br><br><br>
<?=paginationHTML(2,3,'?page=')?>
<br><br><br>
<?=paginationHTML(3,3,'?page=')?>
<br><br><br>
<?=paginationHTML(73,100,'?page=')?>
<br><br><br>
<?=paginationHTML(4,100,'?page=')?>
<br><br><br>
<?=paginationHTML(257,1000,'?page=')?>
<br><br><br>
<?=paginationHTML(7062,10555,'?page=')?>
<br><br><br>
<?=paginationHTML(22080,503456,'?page=')?>
<%
' Used by paginationHTML below...
Function paginationLink(p, page, URL)
if p=page then
paginationLink = "<b style=""color:#C0C0C0"">" & p & "</b>"
else
paginationLink = "<a href=""" & URL & p & """>" & p & "</a>"
end if
End Function
' Used by paginationHTML below...
Function paginationGap(p1, p2)
Dim x
x = p2-p1
if x=0 then
paginationGap = ""
elseif x=1 then
paginationGap = " "
elseif x<=10 then
paginationGap = " . "
elseif x<=100 then
paginationGap = " .. "
else
paginationGap = " ... "
end if
End Function
' URL requires the page number be appended to it.
' e.g. it should end in "&page=" or something similar.
Function paginationHTML(page, lastPage, URL)
const LINKS_PER_STEP = 5
Dim p1, p2, c1, c2, s1, s2, lastp1, lastp2, step
' Nav buttons
if page>1 then
paginationHTML = "<form action=""" & URL & "1"" method=""POST"" style=""display:inline""><input type=""submit"" value="" |< ""></form> " & _
"<form action=""" & URL & (page-1) & """ method=""POST"" style=""display:inline""><input type=""submit"" value="" < ""></form>"
else
paginationHTML = "<input type=""button"" value="" |< "" disabled> <input type=""button"" value="" < "" disabled>"
end if
paginationHTML = paginationHTML & " " & page & " "
if page<lastPage then
paginationHTML = paginationHTML & "<form action=""" & URL & (page+1) & """ method=""POST"" style=""display:inline""><input type=""submit"" value="" > ""></form> " & _
"<form action=""" & URL & lastPage & """ method=""POST"" style=""display:inline""><input type=""submit"" value="" >| ""></form>"
else
paginationHTML = paginationHTML & "<input type=""button"" value="" > "" disabled> <input type=""button"" value="" >| "" disabled>"
end if
paginationHTML = paginationHTML & "<br>"
' Now calculate page links...
lastp1 = 1
lastp2 = page
p1 = 1
p2 = page
c1 = LINKS_PER_STEP+1
c2 = LINKS_PER_STEP+1
s1 = ""
s2 = ""
step = 1
do
if c1>=c2 then
s1 = s1 & paginationGap(lastp1, p1) & paginationLink(p1, page, URL)
lastp1 = p1
p1 = p1+step
c1 = c1-1
else
s2 = paginationLink(p2, page, URL) & paginationGap(p2, lastp2) & s2
lastp2 = p2
p2 = p2-step
c2 = c2-1
end if
if c2=0 then
step = step*10
p1 = p1+step-1 ' Round UP to nearest multiple of step
p1 = p1-(p1 mod step)
p2 = p2-(p2 mod step) ' Round DOWN to nearest multiple of step
c1 = LINKS_PER_STEP
c2 = LINKS_PER_STEP
end if
if p1>p2 then
paginationHTML = paginationHTML & s1 & paginationGap(lastp1, lastp2) & s2
if (lastp2>page) or (page>=lastPage) then exit do
lastp1 = page
lastp2 = lastPage
p1 = page+1
p2 = lastPage
c1 = LINKS_PER_STEP
c2 = LINKS_PER_STEP+1
s1 = ""
s2 = ""
step = 1
end if
loop
End Function
%>
<br><br><br>
<%=paginationHTML(1,1,"?page=")%>
<br><br><br>
<%=paginationHTML(2,3,"?page=")%>
<br><br><br>
<%=paginationHTML(3,3,"?page=")%>
<br><br><br>
<%=paginationHTML(73,100,"?page=")%>
<br><br><br>
<%=paginationHTML(4,100,"?page=")%>
<br><br><br>
<%=paginationHTML(257,1000,"?page=")%>
<br><br><br>
<%=paginationHTML(7062,10555,"?page=")%>
<br><br><br>
<%=paginationHTML(22080,503456,"?page=")%>
<!doctype html>
<html>
<head>
<title>Logarithmic Pagination Demo</title>
<style>
body {background:#C0C0C0;font-family:Arial,Helvetica,sans-serif;font-size:16px;text-align:left}
div {margin:0;padding:0}
div#setupDiv {margin:40px;text-align:center}
table#datarows {border-collapse:collapse;margin:40px auto}
table#datarows th {padding:5px 10px;background:#80B0FF;color:#FFFFFF;border:2px solid #80B0FF;width:1000px;text-align:center}
table#datarows td {padding:2px 10px;background:#FFFFFF;color:#D0D0D0;border:2px solid #80B0FF;width:1000px;text-align:left;font-style:italic}
input.err {border:2px solid #FF0000;background-color:#FFF0F0}
form.pager {display:table;margin:0 auto;padding:20px;border:2px solid #E0E0E0;border-radius:10px;background-color:#D0D0D0;text-align:left;white-space:nowrap}
form#pager1 {margin-top:40px}
form#pager2 {margin-bottom:60px}
form.pager div {display:table-cell;vertical-align:middle;padding:0 20px;white-space:nowrap}
form.pager div + div {border-left:2px solid #E0E0E0}
form.pager div.plinks {padding:0;border:0 none;font-size:14px;line-height:24px;max-width:800px;white-space:normal}
form.pager div.plinks b {display:inline-block;vertical-align:bottom;font-size:24px;line-height:21px;height:24px;overflow:hidden;color:#808080}
form.pager div.plinks a {text-decoration:none;color:black}
form.pager div.plinks a:hover {color:#0000FF;font-weight:bold}
form.pager div.plinks + div {border:0 none}
</style>
<script>
var NumPages, RecsPerPage, els1, els2, plinks1, plinks2;
function setupClick()
{
var el, n, r;
el = document.getElementById("NumPages");
el.className = ((n = (el.value >>> 0)) ? "" : "err");
el = document.getElementById("RecsPerPage");
el.className = ((r = (el.value >>> 0)) ? "" : "err");
if (n&&r) { NumPages = n; RecsPerPage = r; setupServerPage(); }
}
// This function sets up what would normally be part of the server's HTML output.
function setupServerPage()
{
var totRecs = NumPages * RecsPerPage, tbdy = document.getElementById("datarows").tBodies[0], l = tbdy.rows.length;
document.getElementById("plength1").innerHTML = document.getElementById("plength2").innerHTML = totRecs + " record" + ((totRecs===1)?"":"s") + "<br>" + NumPages + " page" + ((NumPages===1)?"":"s");
els1["pcount"].value = els2["pcount"].value = NumPages;
while (l>RecsPerPage) tbdy.deleteRow(--l);
while (l<RecsPerPage) tbdy.insertRow(l++).insertCell(0).innerHTML = "Some data...";
pageNavigate(1);
}
// This would be handled by a return trip to the server, if not using AJAX.
function pageClick(e)
{
e = e||window.event;
var s = e.target||e.srcElement, n, p, el;
if (s.tagName==="A") { n = (p = s.href).lastIndexOf("=")+1; pageNavigate(p.substring(n) >>> 0); return false; }
else if ((s.tagName!=="INPUT")||(s.type!=="submit")) return;
if (!(n = s.name)) { p = ((el = this.elements["p"]).value >>> 0); if ((p<=0)||(p>NumPages)) { el.className = "err"; return false; }}
else if (n==="p1") p = 1;
else if (n==="pprev") p = (this.elements["pcurr"].value >>> 0)-1;
else if (n==="pnext") p = (this.elements["pcurr"].value >>> 0)+1;
else if (n==="plast") p = (this.elements["pcount"].value >>> 0);
pageNavigate(p);
return false;
}
// This would also be handled by a return trip to the server, or else data records could be retrieved via AJAX.
function pageNavigate(p)
{
els1["p"].className = els2["p"].className = els1["p"].value = els2["p"].value = "";
if (p<1) p = 1; else if (p>NumPages) p = NumPages;
els1["p1"].disabled = els2["p1"].disabled = els1["pprev"].disabled = els2["pprev"].disabled = (p===1);
els1["pnext"].disabled = els2["pnext"].disabled = els1["plast"].disabled = els2["plast"].disabled = (p===NumPages);
els1["pcurr"].value = els2["pcurr"].value = p;
// if the server is handling this, insert NON-logarithmic page links here (can be just first, current, and last page).
plinks1.innerHTML = plinks2.innerHTML = logarithmicPaginationLinks(NumPages,p,"?p=");
}
// This function produces the logarithmic pagination links.
function logarithmicPaginationLinks(lastPage,matchPage,linkURL)
{
function pageLink(p, page) { return ((p===page) ? "<b>"+p+"</b>" : '<a href="'+linkURL+p+'">'+p+"</a>"); }
function pageGap(x) { if (x===0) return ""; if (x===1) return " "; if (x<=10) return " . "; if (x<=100) return " .. "; return " ... "; }
var page = (matchPage ? matchPage : 1), LINKS_PER_STEP = 5, lastp1 = 1, lastp2 = page, p1 = 1, p2 = page, c1 = LINKS_PER_STEP+1, c2 = LINKS_PER_STEP+1, s1 = "", s2 = "", step = 1, linkHTML = "";
while (true)
{
if (c1>=c2)
{
s1 += pageGap(p1-lastp1) + pageLink(p1,matchPage);
lastp1 = p1;
p1 += step;
c1--;
}
else
{
s2 = pageLink(p2,matchPage) + pageGap(lastp2-p2) + s2;
lastp2 = p2;
p2 -= step;
c2--;
}
if (c2===0)
{
step *= 10;
p1 += step-1; // Round UP to nearest multiple of step
p1 -= (p1 % step);
p2 -= (p2 % step); // Round DOWN to nearest multiple of step
c1 = LINKS_PER_STEP;
c2 = LINKS_PER_STEP;
}
if (p1>p2)
{
linkHTML += s1 + pageGap(lastp2-lastp1) + s2;
if ((lastp2>page)||(page>=lastPage)) break;
lastp1 = page;
lastp2 = lastPage;
p1 = page+1;
p2 = lastPage;
c1 = LINKS_PER_STEP;
c2 = LINKS_PER_STEP+1;
s1 = '';
s2 = '';
step = 1;
}
}
return linkHTML;
}
window.onload = function()
{
els1 = document.getElementById("pager1").elements;
els2 = document.getElementById("pager2").elements;
plinks1 = document.getElementById("plinks1");
plinks2 = document.getElementById("plinks2")
document.getElementById("pager1").onclick = document.getElementById("pager2").onclick = pageClick;
(document.getElementById("setupDiv").lastChild.onclick = setupClick)();
}
</script>
</head>
<body>
<div id="setupDiv">Select number of pages: <input type="text" id="NumPages" value="100" size="7"> and records per page: <input type="text" id="RecsPerPage" value="20" size="7"> <input type="button" value=" Go "></div>
<hr>
<form id="pager1" class="pager" method="GET"><input type="hidden" name="pcount" value=""><input type="hidden" name="pcurr" value="1">
<div>Go to page: <input type="text" name="p" size="7"> <input type="submit" value=" Go "></div>
<div><input type="submit" name="p1" value=" |< " disabled> <input type="submit" name="pprev" value=" < " disabled></div>
<div id="plinks1" class="plinks"></div>
<div><input type="submit" name="pnext" value=" > "> <input type="submit" name="plast" value=" >| "></div>
<div id="plength1"></div>
</form>
<table id="datarows"><thead><tr><th>Column Heading...</th></tr></thead><tbody></tbody></table>
<form id="pager2" class="pager" method="GET"><input type="hidden" name="pcount" value=""><input type="hidden" name="pcurr" value="1">
<div>Go to page: <input type="text" name="p" size="7"> <input type="submit" value=" Go "></div>
<div><input type="submit" name="p1" value=" |< " disabled> <input type="submit" name="pprev" value=" < " disabled></div>
<div id="plinks2" class="plinks"></div>
<div><input type="submit" name="pnext" value=" > "> <input type="submit" name="plast" value=" >| "></div>
<div id="plength2"></div>
</form>
</body>
</html>
答案 1 :(得分:3)
生成下拉菜单。这个示例只是document.write它,但您可以根据需要进一步开发它(添加onChange等)。 Javascript转换归功于http://www.basereality.com/PHPToJavascript。
<script>
function paginationLink(p, page)
{
if (p == page)
return '<option selected value="' + p + '">' + p + '</option>';
return '<option value="' + p + '">' + p+ '</option>';
}
function paginationHTML(page, lastPage)
{
var LINKS_PER_STEP = 5;
// Now calculate page links...
var lastp1 = 1;
var lastp2 = page;
var p1 = 1;
var p2 = page;
var c1 = LINKS_PER_STEP + 1;
var c2 = LINKS_PER_STEP + 1;
var s1 = '';
var s2 = '';
var step = 1;
var result = 0;
while (true)
{
if (c1 >= c2)
{
s1 += paginationLink(p1, page);
lastp1 = p1;
p1 += step;
c1--;
}
else
{
s2 = paginationLink(p2, page) + s2;
lastp2 = p2;
p2 -= step;
c2--;
}
if (c2 == 0)
{
step *= 10;
p1 += step - 1; // Round UP to nearest multiple of $step
p1 -= (p1 % step);
p2 -= (p2 % step); // Round DOWN to nearest multiple of $step
c1 = LINKS_PER_STEP;
c2 = LINKS_PER_STEP;
}
if (p1 > p2)
{
result += s1 + s2;
if ((lastp2 > page) || (page >= lastPage))
return result;
lastp1 = page;
lastp2 = lastPage;
p1 = page + 1;
p2 = lastPage;
c1 = LINKS_PER_STEP;
c2 = LINKS_PER_STEP + 1;
s1 = '';
s2 = '';
step = 1;
}
}
}
document.write('Menu generated with JavaScript <select>' + paginationHTML(765, 5055))+'</select>';
</script>
答案 2 :(得分:1)
怎么样:
a)添加&lt; -100&lt; -10 [pagination] + 10&gt; + 100〕而不是炸毁分页本身
b)提供直接页面输入[#..] [view],根据有效页面范围过滤输入
c)需要一些正确的编码,但是:将内部浮动范围扩展为+/- 10,+ / - 25,+ / - 100页面而不是炸毁整个分页范围
答案 3 :(得分:0)
我想到了对数分页的两种选择:
如果相关,您可以在章节,章节和书籍中拆分数据。这是旧方式,当纸张为王时,图书馆成为互联网的工作。一些PDF文档仍然有这个。
如果有人想要跳转到提及supercalifragilisticexpialidocious
的大数据部分,您可以提供一个搜索框,即维基百科。