Frage

Kann jemand Code oder Pseudocode dafür bereitstellen, wie die Paging-Links auf StackOverflow generiert werden?

Ich zerbreche mir ständig den Kopf, kann mir aber keine vernünftige Möglichkeit vorstellen, die dynamischen Links zu erstellen, die immer die beiden Seiten rund um die aktuelle sowie die erste und die letzte anzeigen.

Beispiel: 1 ... 5 6 7 ... 593

War es hilfreich?

Lösung

Es gibt bereits mehrere andere Antworten, aber ich möchte Ihnen den Ansatz zeigen, den ich zur Lösung des Problems gewählt habe:Schauen wir uns zunächst an, wie Stack Overflow mit Normalfällen und Randfällen umgeht.Auf jeder meiner Seiten werden 10 Ergebnisse angezeigt. Um also herauszufinden, was sie für eine Seite bewirkt, suchen Sie nach einem Tag mit weniger als 11 Einträgen: Benutzerfreundlichkeit funktioniert heute.Wir können sehen, dass nichts angezeigt wird, was Sinn macht.

Wie wäre es mit 2 Seiten?Suchen Sie ein Tag mit zwischen 11 und 20 Einträgen (Emacs funktioniert heute).Wir sehen:"1 2 Weiter“ oder „Zurück 1“. 2", je nachdem, auf welcher Seite wir uns befinden.

3 Seiten?"1 2 3 ...3 Weiter“, „Vorherige 1 2 3 Weiter“ und „Vorherige 1 ...“2 3".Interessanterweise können wir sehen, dass Stack Overflow selbst diesen Randfall nicht sehr gut bewältigt:es sollte „anzeigen“1 2 ...3 Weiter"

4 Seiten?"1 2 3 ...4 Weiter“, „Vorherige 1 2 3 ...4 Weiter“, „Vorherige 1 ...2 3 4 Weiter“ und „Vorherige 1 ...“3 4"

Schauen wir uns zum Schluss den allgemeinen Fall an, N Seiten:"1 2 3 ...N Nächster“, „Vorheriger 1 2 3 ...N Weiter“, „Vorherige 1 ...“2 3 4 ...N Weiter“, „Vorherige 1 ...“3 4 5 ...„N Weiter“ usw.

Lassen Sie uns basierend auf dem, was wir gesehen haben, verallgemeinern:Der Algorithmus scheint diese gemeinsamen Merkmale zu haben:

  • Wenn wir uns nicht auf der ersten Seite befinden, zeigen Sie den Link zur vorherigen Seite an
  • Zeigen Sie immer die erste Seitenzahl an
  • Zeigt immer die aktuelle Seitenzahl an
  • Zeigen Sie immer die Seite vor dieser Seite und die Seite nach dieser Seite an.
  • Zeigt immer die letzte Seitenzahl an
  • Wenn wir uns nicht auf der letzten Seite befinden, zeigen Sie den Link „Weiter“ an

Lassen Sie uns den Randfall einer einzelnen Seite ignorieren und einen guten ersten Versuch mit dem Algorithmus unternehmen:(Wie bereits erwähnt, wäre der Code zum tatsächlichen Ausdrucken der Links komplizierter.Stellen Sie sich jede Stelle vor, an der wir eine Seitennummer (Vorherige oder Nächste) platzieren, als einen Funktionsaufruf, der die richtige URL zurückgibt.)

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

Diese Funktion funktioniert einwandfrei, berücksichtigt jedoch nicht, ob wir uns in der Nähe der ersten oder letzten Seite befinden.Wenn wir uns die obigen Beispiele ansehen, möchten wir nur die ... anzeigen.wenn die aktuelle Seite zwei oder mehr entfernt ist.

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

Wie Sie sehen, gibt es hier einige Duplikate.Wir können das zur besseren Lesbarkeit bereinigen:

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

Es bleiben nur noch zwei Probleme.Erstens drucken wir eine Seite nicht korrekt aus und zweitens drucken wir „1“ zweimal aus, wenn wir uns auf der ersten oder letzten Seite befinden.Lassen Sie uns beides auf einmal bereinigen:

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

Eigentlich habe ich gelogen:Wir haben noch ein Problem.Wenn Sie mindestens 4 Seiten haben und sich auf der ersten oder letzten Seite befinden, erhalten Sie eine zusätzliche Seite in Ihrer Anzeige.Anstatt "1 2 ...10 Als nächstes erhalten Sie1 2 3 ...10 Weiter".Um genau zu ermitteln, was bei Stack Overflow vor sich geht, müssen Sie die folgende Situation prüfen:

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

Ich hoffe das hilft!

Andere Tipps

Die Steuerelemente zeigen im Allgemeinen Steuerelemente für:P1, Pn, Pc (aktuelle Seite), Pc+1, Pc-1.Dies ändert sich nur an beiden Enden des Paging-Bereichs {Pc < P3 oder Pc > (Pn-3)}

  • Der erste Schritt besteht natürlich darin, die Anzahl der Seiten zu ermitteln:

numPages = ceiling(totalRecords / numPerPage)

  • Wenn Sie 4 oder weniger haben, brechen Sie an dieser Stelle ab, da nach den oben genannten Regeln das Paging immer festgelegt ist (P1, P2, Pn-1, Pn), wobei man tatsächlich Pc sein wird

  • Ansonsten haben Sie drei „Zustände“

A.(Pc < P3) – also P1, P2, P3, Pn, Next anzeigen. Wenn Pc >1, wird vor P1 ein „Prev“-Link angezeigt.

B.(Pc > Pn - 2), also zeige Prev, P1, Pn - 2, Pn -1, Pn, zeige einen Next-Link, wenn Pc < Pn

C.Show Prev, P1, Pc -1, Pc, Pc +1, Pn, Next

Kinderleicht im Pseudocode.Die Schleifen können bei der Implementierung etwas unangenehm werden, da Sie einige Iterationen durchführen müssen, um die Links zu generieren.

Bearbeiten:Natürlich sind Prev und Next identisch mit Pc +/- 1

Nun, wenn Sie die aktuelle Seite kennen, ist es ziemlich trivial, einfach die Zahl um 1 zu subtrahieren und um 1 zu addieren, diese Zahlen dann mit den Grenzen zu vergleichen und immer die erste und letzte Seite anzuzeigen, auch wenn sie nicht in der richtigen Reihenfolge sind , füge die Ellipsen hinzu.

Oder möchten Sie die Gesamtzahl der Seiten ermitteln und die aktuelle Seitenzahl ermitteln ...?

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 wird als Math.Ceiling(totalRecords/RecordsPerPage) berechnet.

Hmmm.In dem Fall, dass CurrentPage 3 ist, zeigt es immer noch [1] ... [2] [3] [4] ... [xxx] Ich denke, die Ellipsen sind in diesem Fall überflüssig.Aber so funktioniert es.

Bearbeiten:Die Vorschau formatiert den Codeblock korrekt. Warum wird er verstümmelt?Klar, es ist nur Pseudocode ...aber dennoch....

Dies ist mein Ansatz, um einen Paging-Link zu erstellen.Die folgende Java-Code ist nur ein 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);
        }
    }

}

Hier ist mein Algorithmus, der wirklich gut funktioniert:

    // 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 können Sie einen Pager wie diesen erstellen:

    if prevPage
    [1] [prevPage] 
    endif

    [startPage] ... [endPage] 

    if nextPage
    [nextPage] [lastPage] 
    endif

oder passen Sie alles an, was Ihnen gefällt.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top