如何对很多很多页面进行页面导航?对数页面导航

发布于 2024-12-11 00:51:52 字数 773 浏览 0 评论 0原文

显示许多页面的页面导航的最佳方式是什么?

(最初这是作为操作提示发布的,我的答案包含在问题中。我现​​在将我的答案分成下面的“答案”部分)。


更具体地说:

假设您要向用户显示一组记录,这些记录分为固定大小的页面(例如 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 [ > ] [>> ]

但在这两种情况下,导航到“...”部分中间的任何位置都需要多次单击鼠标。有时会提供直接输入页码的输入框;否则(假设我们在这里讨论的是网页)精明的用户可能会查看 URL 以查看是否可以直接编辑它。

如果有一个分页显示,让用户只需点击几下鼠标就可以到达任何页面,而不需要有太多的链接,那就太好了。

如何最好地实现这一目标?

What's the best way of displaying page navigation for many, many pages?

(Initially this was posted as a how-to tip with my answer included in the question. I've now split my answer off into the "answers" section below).


To be more specific:

Suppose you're displaying a set of records to the user, broken up into fixed-size pages (like the results of a Google search, for example). If there are only a few pages, you can display a page navigation area at the end of the results that might look like this:

[ << ] [<] 1 2 3 4 5 6 7 8 9 10 11 12 13 [ > ] [ >> ]

But this quickly becomes unweildy if there are much more than 20 or 30 pages of results.

Sometimes you'll see things like this:

[ << ] [<] ... 665 666 667 668 669 670 671 672 673 ... [ > ] [ >> ]

or this:

[ << ] [<] 1 2 3 ... 667 668 669 670 671 ... 845 846 847 [ > ] [ >> ]

but in both cases, navigating to anywhere in the middle of the "..." sections would take many, many mousclicks. Sometimes an input box for entering the page number directly is provided; otherwise (assuming we're talking about a webpage here) the savvy user is likely to look at the URL to see if they can edit it directly.

What would be nice would be to have a pagination display that lets the user reach any page in only a few mouseclicks, without having ridiculously many links.

How would that best be achieved?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

只怪假的太真实 2024-12-18 00:51:52

这是我的解决方案 - 使用“对数页面导航”:

这可以通过根据距端点或当前页面的距离以对数方式分布页码来实现。这是我的意思的一个例子:

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 版本,但逻辑应该很简单,可以翻译成任何语言。请注意,底部的位(在两种情况下)仅显示一些示例。显然,格式需要自定义才能匹配您的网页(或应用程序),因此这里的格式非常基本。更改 paginationHTML 中的 LINKS_PER_STEP 以确定当您离开端点或当前页面时步长增加之前显示的数字数量。

为了获得更紧凑的输出,您还可以考虑更改代码,以使端点周围的编号不会“密集”(即仅在当前页面周围密集)。

代码如下:

PHP 版本:

<?

// 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=')?>

ASP 版本:

<%

' 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=")%>

Javascript 版本(在完整的测试页内):

<!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>

Here's my solution - use "Logarithmic Page Navigation":

This can be achieved by having page numbers distributed logarithmically, according to distance from either the endpoints or the current page. Here's an example of what I mean:

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

Notice how in the gaps, numbering goes from 1s, to 10s, to 100s (etc.). (I use powers of 10, but in principle you could use a different scheme - powers of 2, say).

I wrote some code that does this back in 2004, and thought I'd share it here. There are PHP and ASP versions, but the logic ought to be simple to translate into any language. Note that the bit at the bottom (in both cases) just displays some examples. Obviously the formatting will need customization to match your webpage (or application), so it's pretty basic here. Alter LINKS_PER_STEP in paginationHTML to determine how many numbers get displayed before the step size increases, as you move away from the endpoints or current page.

For a more compact output you could also consider altering the code so that the numbering is not "dense" around the endpoints (i.e. dense only around the current page).

Here's the code:

PHP version:

<?

// 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=')?>

ASP version:

<%

' 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=")%>

Javascript version (within complete test 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>
泡沫很甜 2024-12-18 00:51:52

JavaScript 中“对数页面导航”的简化版本:

生成下拉菜单。这个示例只是 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>

Simplified version of "Logarithmic Page Navigation" in JavaScript:

Generates dropdown menu. This sample just document.write's it but you can develop it further according to your need (add onChange, etc). Javascript conversion thanks to 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>
梦初启 2024-12-18 00:51:52

怎么样:

a) 添加 <-100 <-10 [分页] +10> +100>不要破坏分页本身

b) 提供直接页面输入 [# .. ] [ view ] ,根据有效页面范围过滤输入

c) 需要一些适当的编码,但是:通过说 +/ 扩展内部浮动范围-10、+/-25、+/-100 页,而不是放大整个分页范围

How about:

a) add <-100 <-10 [pagination] +10> +100> instead of blow up the pagination itself

b) offer a direct page input [# .. ] [ view ] , filter the input against the valid page range

c) needs some proper coding, but: expand the inner, floating range by say +/-10, +/-25, +/-100 page instead of blowing up the complete paging range

寄居者 2024-12-18 00:51:52

我想到了对数分页的两种替代方案:

  1. 如果相关,您可以将数据拆分为部分、章节和书籍。这是古老的方式,当时纸张为王,图书馆取代了互联网的工作。一些 PDF 文档仍然有这样的内容。

  2. 如果有人想跳转到提到 supercalifragilisticexpialidocious 的大数据部分,您可以提供一个搜索框,如维基百科。

I think of two alternatives of logarithmic pagination:

  1. If relevant, you could split your data in sections, chapters and books. This is the old way, when paper was king, and libraries made the job of internet. Some PDF documents still have that.

  2. You can offer a search box, ala Wikipedia, if someone wants to jump to the part of big-data where supercalifragilisticexpialidocious is mentioned.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文