Domanda

Qualcuno può fornire codice o pseudocodice per come vengono generati i collegamenti di paging su StackOverflow?

Continuo a tormentarmi ma non riesco a pensare a un modo decente per costruire i collegamenti dinamici che mostrino sempre le 2 pagine attorno a quella corrente, più la prima e l'ultima.

Esempio: 1 ... 5 6 7 ... 593

È stato utile?

Soluzione

Ci sono già molte altre risposte, ma vorrei mostrarti l'approccio che ho adottato per risolverlo:Per prima cosa, vediamo come Stack Overflow gestisce i casi normali e i casi limite.Ognuna delle mie pagine visualizza 10 risultati, quindi per scoprire cosa fa per 1 pagina, trova un tag che abbia meno di 11 voci: usabilità funziona oggi.Possiamo vedere che non viene visualizzato nulla, il che ha senso.

Che ne dici di 2 pagine?Trova un tag che contenga da 11 a 20 voci (emacs funziona oggi).Vediamo:"1 2 Successivo" o "Prec. 1 2", a seconda della pagina in cui ci troviamo.

3 pagine?"1 2 3...3 Successivo", "Prec. 1 2 3 Successivo" e "Prec. 1...2 3".È interessante notare che possiamo vedere che Stack Overflow stesso non gestisce molto bene questo caso limite:dovrebbe essere visualizzato "1 2...3 Avanti"

4 pagine?"1 2 3...4 Successivo", "Prec. 1 2 3...4 Successivo", "Prec. 1...2 3 4 Successivo" e "Prec. 1...3 4"

Infine diamo un'occhiata al caso generale, N pagine:"1 2 3...N Avanti", "Prec. 1 2 3...N Avanti", "Prec. 1...2 3 4...N Avanti", "Prec. 1...3 4 5...N Avanti", ecc.

Generalizziamo in base a quanto visto:L’algoritmo sembra avere questi tratti in comune:

  • Se non siamo nella prima pagina, visualizza il collegamento a Prec
  • Visualizza sempre il numero della prima pagina
  • Visualizza sempre il numero di pagina corrente
  • Visualizza sempre la pagina prima di questa pagina e la pagina dopo questa pagina.
  • Visualizza sempre l'ultimo numero di pagina
  • Se non siamo nell'ultima pagina, visualizza il collegamento a Successivo

Ignoriamo il caso limite di una singola pagina e facciamo un buon primo tentativo con l'algoritmo:(Come è stato accennato, il codice per stampare effettivamente i collegamenti sarebbe più complicato.Immagina in ogni posto in cui inseriamo un numero di pagina, Prev o Next come una chiamata di funzione che restituirà l'URL corretto.)

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

Questa funzione funziona bene, ma non tiene conto se siamo vicini alla prima o all'ultima pagina.Guardando gli esempi sopra, vogliamo solo visualizzare il...se la pagina corrente è a due o più di distanza.

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

Come puoi vedere, qui abbiamo qualche duplicazione.Possiamo andare avanti e ripulirlo per la leggibilità:

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

Rimangono solo due problemi.Innanzitutto, non stampiamo correttamente una pagina e, in secondo luogo, stamperemo "1" due volte se siamo sulla prima o sull'ultima pagina.Puliamoli entrambi in una volta sola:

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

In realtà ho mentito:Abbiamo un problema rimanente.Quando hai almeno 4 pagine e sei sulla prima o sull'ultima pagina, ottieni una pagina in più sul tuo display.Invece di "1 2...10 Successivamente" ottieni "1 2 3...10 Avanti".Per abbinare esattamente ciò che sta succedendo su Stack Overflow, dovrai verificare questa situazione:

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

Spero che aiuti!

Altri suggerimenti

I controlli generalmente mostrano i controlli per:P1, Pn, Pc (pagina corrente), Pc+1, Pc-1.L'unica volta che questo cambia è alle estremità dell'intervallo di paginazione {Pc < P3 o Pc > (Pn-3)}

  • Il primo passo è ovviamente calcolare il numero di pagine:

numPages = ceiling(totalRecords / numPerPage)

  • Se ne hai 4 o meno, a questo punto abbandona, perché, secondo le regole di cui sopra, la paginazione sarà sempre fissa (P1, P2, Pn-1, Pn), dove in realtà uno sarà Pc

  • altrimenti hai tre "stati"

UN.(Pc < P3) - quindi mostra P1, P2, P3, Pn, Next Se Pc >1, mostra un collegamento 'prev' prima di P1.

B.(Pc > Pn - 2), quindi mostra Prev, P1, Pn - 2, Pn -1, Pn, mostra un collegamento Next se Pc < Pn

C.Mostra Prec, P1, Pc -1, Pc, Pc +1, Pn, Successivo

Facile come una torta in pseudo codice.I loop possono diventare un po' fastidiosi una volta implementati poiché è necessario eseguire alcune iterazioni per generare i collegamenti.

Modificare:Ovviamente Prev e Next sono identici a Pc +/- 1

Bene, se conosci la pagina corrente, è piuttosto banale sottrarre semplicemente il numero per 1 e aggiungerlo per 1, quindi controlla quei numeri rispetto ai limiti e visualizza sempre la prima e l'ultima pagina, quindi se non sono in sequenza , aggiungi i puntini di sospensione.

Oppure stai chiedendo come ottenere il numero totale di pagine e determinare il numero di pagina corrente...?

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 viene calcolato come Math.Ceiling(totalRecords/RecordsPerPage).

hmmm.In realtà, nel caso in cui CurrentPage sia 3, mostra ancora [1] ... [2] [3] [4] ... [xxx] Penso che le ellissi siano superflue in quel caso.Ma è così che funziona.

Modificare:l'anteprima formatta correttamente il blocco di codice, perché viene danneggiato?certo, è solo pseudocodice....ma comunque....

Questo è il mio approccio per creare un collegamento di paging.Il seguente codice Java è solo uno 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);
        }
    }

}

Ecco il mio algoritmo che funziona davvero bene:

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

Quindi puoi fare un cercapersone come questo:

    if prevPage
    [1] [prevPage] 
    endif

    [startPage] ... [endPage] 

    if nextPage
    [nextPage] [lastPage] 
    endif

o personalizza quello che preferisci.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top