<p>Can someome provide code or pseudo-code for how the paging links on StackOverflow are generated?</p>

<p>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.</p>

<p>Example: <code>1 ... 5 6 7 ... 593</code></p>

[{'answer_id': 44560, 'author': 'Mike Stone', 'author_id': 122, 'author_profile': 'https://Stackoverflow.com/users/122', 'pm_score': 1, 'selected': False, 'text': "<p>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.</p>\n\n<p>Or are you asking about getting the total number of pages and determining the current page number...?</p>\n"}, {'answer_id': 44614, 'author': 'Ian', 'author_id': 4396, 'author_profile': 'https://Stackoverflow.com/users/4396', 'pm_score': 2, 'selected': False, 'text': '<p>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 &lt; P3 or Pc > (Pn-3)}</p>\n\n<ul>\n<li>The first step is to obviously work out the number of pages:</li>\n</ul>\n\n<p><code>numPages = ceiling(totalRecords / numPerPage)</code></p>\n\n<ul>\n<li><p>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</p></li>\n<li><p>else, you have three "states"</p></li>\n</ul>\n\n<p>a. (Pc &lt; P3) - so show P1, P2, P3, Pn, Next  If Pc >1, show a \'prev\' link before P1.</p>\n\n<p>b. (Pc > Pn - 2), so show Prev, P1, Pn - 2, Pn -1, Pn, show a Next link if Pc &lt; Pn</p>\n\n<p>c. Show Prev, P1, Pc -1, Pc, Pc +1, Pn, Next</p>\n\n<p>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.</p>\n\n<p><em>Edit:\nOf course Prev and Next are identical to Pc +/- 1</em></p>\n'}, {'answer_id': 44627, 'author': 'Jimmy', 'author_id': 4435, 'author_profile': 'https://Stackoverflow.com/users/4435', 'pm_score': 1, 'selected': False, 'text': "<pre><code>public void PageLinks(int currentPage, int lastPage) {\n    if (currentPage &gt; 2) \n        Add('[1]', '...');\n    for(int i=Math.Max(1, currentPage-1); i&lt; Math.Min(currentPage+1, lastPage); i++)\n        Add('[i]');\n    if (currentPage &lt; lastPage-1)\n        Add('...', '[lastpage]');\n}\n</code></pre>\n\n<p>lastPage is calculated as Math.Ceiling(totalRecords/RecordsPerPage). </p>\n\n<p>hmmm. actually, in the case that currentpage is 3, it still shows [1]...[2][3][4]...[xxx] \ni think the ellipses are superfluous in that case. But that's how it works.</p>\n\n<p>Edit: the preview formats the codeblock correctly, why does it get mangled? sure, its just pseudocode.... but still....</p>\n"}, {'answer_id': 44844, 'author': 'Bill', 'author_id': 102, 'author_profile': 'https://Stackoverflow.com/users/102', 'pm_score': 7, 'selected': True, 'text': '<p>There are several other answers already, but I\'d like to show you the approach I took to solve it:\nFirst, 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: <a href="https://stackoverflow.com/questions/tagged/usability">usability</a> works today.  We can see nothing is displayed, which makes sense.</p>\n\n<p>How about 2 pages?  Find a tag that has between 11 and 20 entries (<a href="https://stackoverflow.com/questions/tagged/emacs">emacs</a> works today).  We see: "<strong>1</strong> 2 Next" or "Prev 1 <strong>2</strong>", depending on which page we\'re on.</p>\n\n<p>3 pages? "<strong>1</strong> 2 3 ... 3 Next", "Prev 1 <strong>2</strong> 3 Next", and "Prev 1 ... 2 <strong>3</strong>".  Interestingly, we can see that Stack Overflow itself doesn\'t handle this edge case very well: it should display "<strong>1</strong> 2 ... 3 Next"</p>\n\n<p>4 pages? "<strong>1</strong> 2 3 ... 4 Next", "Prev 1 <strong>2</strong> 3 ... 4 Next", "Prev 1 ... 2 <strong>3</strong> 4 Next" and "Prev 1 ... 3 <strong>4</strong>"</p>\n\n<p>Finally let\'s look at the general case, N pages:  "<strong>1</strong> 2 3 ... N Next", "Prev 1 <strong>2</strong> 3 ... N Next", "Prev 1 ... 2 <strong>3</strong> 4 ... N Next", "Prev 1 ... 3 <strong>4</strong> 5 ... N Next", etc.</p>\n\n<p>Let\'s generalize based on what we\'ve seen:\n  The algorithm seems to have these traits in common:</p>\n\n<ul>\n<li>If we\'re not on the first page, display link to Prev</li>\n<li>Always display the first page number</li>\n<li>Always display the current page number</li>\n<li>Always display the page before this page, and the page after this page.</li>\n<li>Always display the last page number</li>\n<li>If we\'re not on the last page, display link to Next</li>\n</ul>\n\n<p>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.)</p>\n\n<pre><code>function printPageLinksFirstTry(num totalPages, num currentPage)\n  if ( currentPage &gt; 1 )\n    print "Prev"\n  print "1"\n  print "..."\n  print currentPage - 1\n  print currentPage\n  print currentPage + 1\n  print "..."\n  print totalPages\n  if ( currentPage &lt; totalPages )\n    print "Next"\nendFunction\n</code></pre>\n\n<p>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.</p>\n\n<pre><code>function printPageLinksHandleCloseToEnds(num totalPages, num currentPage)\n  if ( currentPage &gt; 1 )\n    print "Prev"\n  print "1"\n  if ( currentPage &gt; 2 )\n    print "..."\n  if ( currentPage &gt; 2 )\n    print currentPage - 1\n  print currentPage\n  if ( currentPage &lt; totalPages - 1 )\n    print currentPage + 1\n  if ( currentPage &lt; totalPages - 1 )\n    print "..."\n  print totalPages\n  if ( currentPage &lt; totalPages )\n    print "Next"\nendFunction\n</code></pre>\n\n<p>As you can see, we have some duplication here.  We can go ahead and clean that up for readibility:</p>\n\n<pre><code>function printPageLinksCleanedUp(num totalPages, num currentPage)\n  if ( currentPage &gt; 1 )\n    print "Prev"\n  print "1"\n  if ( currentPage &gt; 2 )\n    print "..."\n    print currentPage - 1\n  print currentPage\n  if ( currentPage &lt; totalPages - 1 )\n    print currentPage + 1\n    print "..."\n  print totalPages\n  if ( currentPage &lt; totalPages )\n    print "Next"\nendFunction\n</code></pre>\n\n<p>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:</p>\n\n<pre><code>function printPageLinksFinal(num totalPages, num currentPage)\n  if ( totalPages == 1 )\n    return\n\n  if ( currentPage &gt; 1 )\n    print "Prev"\n\n  print "1"\n\n  if ( currentPage &gt; 2 )\n    print "..."\n    print currentPage - 1\n\n  if ( currentPage != 1 and currentPage != totalPages )\n    print currentPage\n\n  if ( currentPage &lt; totalPages - 1 )\n    print currentPage + 1\n    print "..."\n\n  print totalPages\n\n  if ( currentPage &lt; totalPages )\n    print "Next"\n\nendFunction\n</code></pre>\n\n<p>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 "<strong>1</strong> 2 ... 10 Next" you get "<strong>1</strong> 2 3 ... 10 Next".  To match what\'s going on at Stack Overflow exactly, you\'ll have to check for this situation:</p>\n\n<pre><code>function printPageLinksFinalReally(num totalPages, num currentPage)\n  if ( totalPages == 1 )\n    return\n\n  if ( currentPage &gt; 1 )\n    print "Prev"\n\n  print "1"\n\n  if ( currentPage &gt; 2 )\n    print "..."\n    if ( currentPage == totalPages and totalPages &gt; 3 )\n      print currentPage - 2\n    print currentPage - 1\n\n  if ( currentPage != 1 and currentPage != totalPages )\n    print currentPage\n\n  if ( currentPage &lt; totalPages - 1 )\n    print currentPage + 1\n    if ( currentPage == 1 and totalPages &gt; 3 )\n      print currentPage + 2\n    print "..."\n\n  print totalPages\n\n  if ( currentPage &lt; totalPages )\n    print "Next"\n\nendFunction\n</code></pre>\n\n<p>I hope this helps!</p>\n'}, {'answer_id': 2847286, 'author': 'Just a learner', 'author_id': 170931, 'author_profile': 'https://Stackoverflow.com/users/170931', 'pm_score': 0, 'selected': False, 'text': '<p>This is my approach to make a paging link. The following <strong><em>java code</em></strong> is just a pseudo.</p>\n\n<pre><code>package com.edde;\n\n/**\n * @author Yang Shuai\n */\npublic class Pager {\n\n    /**\n     * This is a method used to display the paging links(pagination or sometimes called pager).\n     * The totalPages are the total page you need to display. You can get this value using the\n     * formula:\n     * \n     *     total_pages = total_records / items_per_page\n     * \n     * This methods is just a pseudo-code.\n     * \n     * \n     * @param totalPages how many pages you need to display\n     * @param currentPage you are in which page now\n     */\n    public static void printPageLinks(int totalPages, int currentPage) {\n\n        // how many pages to display before and after the current page\n        int x = 2;\n\n        // if we just have one page, show nothing\n        if (totalPages == 1) {\n            return;\n        }\n\n        // if we are not at the first page, show the "Prev" button\n        if (currentPage &gt; 1) {\n            System.out.print("Prev");\n        }\n\n        // always display the first page\n        if (currentPage == 1) {\n            System.out.print("    [1]");\n        } else {\n            System.out.print("    1");\n        }\n\n        // besides the first and last page, how many pages do we need to display?\n        int how_many_times = 2 * x + 1;\n\n        // we use the left and right to restrict the range that we need to display\n        int left = Math.max(2, currentPage - 2 * x - 1);\n        int right = Math.min(totalPages - 1, currentPage + 2 * x + 1);\n\n        // the upper range restricted by left and right are more loosely than we need,\n        // so we further restrict this range we need to display\n        while (right - left &gt; 2 * x) {\n            if (currentPage - left &lt; right - currentPage) {\n                right--;\n                right = right &lt; currentPage ? currentPage : right;\n            } else {\n                left++;\n                left = left &gt; currentPage ? currentPage : left;\n            }\n        }\n\n        // do we need display the left "..."\n        if (left &gt;= 3) {\n            System.out.print("    ...");\n        }\n\n        // now display the middle pages, we display how_many_times pages from page left\n        for (int i = 1, out = left; i &lt;= how_many_times; i++, out++) {\n            // there are some pages we need not to display\n            if (out &gt; right) {\n                continue;\n            }\n\n            // display the actual page\n            if (out == currentPage) {\n                System.out.print("    [" + out + "]");\n            } else {\n                System.out.print("    " + out);\n            }\n        }\n\n        // do we need the right "..."\n        if (totalPages - right &gt;= 2) {\n            System.out.print("    ...");\n        }\n\n        // always display the last page\n        if (currentPage == totalPages) {\n            System.out.print("    [" + totalPages + "]");\n        } else {\n            System.out.print("    " + totalPages);\n        }\n\n        // if we are not at the last page, then display the "Next" button\n        if (currentPage &lt; totalPages) {\n            System.out.print("    Next");\n        }\n        System.out.println();\n    }\n\n    public static void main(String[] args) {\n        // printPageLinks(50, 3);\n        help(500);\n    }\n\n    public static void test(int n) {\n        for (int i = 1; i &lt;= n; i++) {\n            printPageLinks(n, i);\n        }\n        System.out.println("------------------------------");\n    }\n\n    public static void help(int n) {\n        for (int i = 1; i &lt;= n; i++) {\n            test(i);\n        }\n    }\n\n    public static void help(int from, int to) {\n        for (int i = from; i &lt;= to; i++) {\n            test(i);\n        }\n    }\n\n}\n</code></pre>\n'}, {'answer_id': 51988336, 'author': 'Tsvetan Filev', 'author_id': 475733, 'author_profile': 'https://Stackoverflow.com/users/475733', 'pm_score': 0, 'selected': False, 'text': '<p>Here is my algorithm. It works really nice:</p>\n\n<pre class="lang-js prettyprint-override"><code>// Input\ntotal_items   // Number of rows, records etc. from db, file or whatever\nper_page      // num items per page\npage          // current page\nvisible_pages // number of visible pages\n\n// Calculations\nlastPage = ceil(total_items / per_page);\nprevPage = page - 1 &lt; 1 ? 0 : page - 1;\nnextPage = page + 1 &gt; lastPage ? 0 : page + 1;\nhalfpages = ceil(visible_pages / 2);\nstartPage = page - halfpages &lt; 1 ? 1 : page - halfpages;\nendPage = startPage + visible_pages - 1;\nif(endPage &gt; lastPage) {\n    startPage -= endPage - lastPage;\n    startPage = startPage &lt; 1 ? 1 : startPage;\n    endPage = startPage + visible_pages &gt; lastPage ? lastPage : startPage + visible_pages - 1;\n}\n\n// Output\nlastPage    // Total number of pages\nprevPage    // Previous page number (if 0 there is no prev page)\nnextPage    // Next page number (if 0 there is no next page)\nstartPage   // First visible page\nendPage     // Last visible page\n</code></pre>\n\n<p>So you can do a pager like this:</p>\n\n<pre><code>if prevPage\n    [1] [prevPage] \nendif\n\n[startPage] ... [endPage] \n\nif nextPage\n    [nextPage] [lastPage] \nendif\n</code></pre>\n\n<p>or customize whatever you like.</p>\n'}]
['https://Stackoverflow.com/questions/44542', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/1097/']