Logik hinter der Paginierung wie bei Google

Lesezeit: 10 Minuten

Benutzer-Avatar
ThomasK

Was ist die Logik hinter dem Paginierungsverhalten von Google?

Mein Paginator geht ungefähr so:

[1]  2   3  ...  184   >
 <   1  [2]  3   4  ...  184   >
 <   1   2  [3]  4   5  ...  184   >
 <   1   2   3  [4]  5   6   ...  184   >
 <   1  ...  3   4  [5]  6    7   ...  184   >
 <   1  ...  4   5  [6]  7    8   ...  184   >
 <   1  ...  5   6  [7]  8    9   ...  184   >
 <   1  ...  6   7  [8]  9    10  ...  184   >

Hier ist eine Live-Version des obigen Beispiels: http://www.dev.thomaskile.me/?page=test-zone&module=Paginator.
Ich weiß, warum das passiert; Ich habe die Anzahl der Seitenzahlen, die auf jeder Seite der aktuellen Seite angezeigt werden sollen, auf zwei (2) gesetzt.

Ich hätte lieber, dass der Zahlenbereich so gleich ist:

[1]  2   3   4   5   6   7   8   ...   184   >
 <   1  [2]  3   4   5   6   7   ...   184   >
 <   1   2  [3]  4   5   6   7   ...   184   >
 <   1   2   3  [4]  5   6   7   ...   184   >
 <   1  ...  3   4  [5]  6   7   ...   184   >
 <   1  ...  4   5  [6]  7   8   ...   184   >
 <   1  ...  5   6  [7]  8   9   ...   184   >    
 <   1  ...  6   7  [8]  9   10  ...   184   >

Es ist am Anfang und am Ende, dass ich einige Änderungen vornehmen muss, aber ich kann nicht herausfinden, wie ich es zu einer einfachen Operation machen kann …
Ich möchte es auch flexibel machen. Das heißt, ich möchte die Anzahl der gewünschten Seiten auf jeder Seite ändern und das Skript erweitern und alles berechnen lassen …

Hier mein bisheriger Code:

/**
 *  page controller buttons 
 *  @param str $this->querySting      href="https://stackoverflow.com/questions/11272108/URL string"
 *  @param str $this->pageIdentifier  $_GET['this-name']
 *  @param int $this->numPages        Total amount of pages
 *  @param int $this->midRange        Number of pages to show on each side of current page
 */

public function prevPage() 
{
    if ($this->currentPage > 1){ 
        $prevPage = ($this->currentPage - 1); 
        return '<a href="'.$this->queryString.'&'.$this->pageIdentifier.'='.$prevPage.'" class="prev">prev</a>'; 
    }
}
public function nextPage() 
{
    if ($this->currentPage < $this->numPages) { 
        $nextPage = $this->currentPage + 1;
        return '<a href="'.$this->queryString.'&'.$this->pageIdentifier.'='.$nextPage.'" class="next">next</a>';  
    }  
}
public function firstPage() 
{
    if ($this->currentPage > ($this->midRange + 1)) {  //  if number of pages between "currentPage" and "firstPage" exceeds $midRange with 1...
        $firstPage .= '<a href="'.$this->queryString.'&'.$this->pageIdentifier.'=1" class="first">1</a>';  //  ...show "first page"-link
        if ($this->currentPage > ($this->midRange + 2)) {   //  if number of pages between $currentPage and "first page" exceeds $midRange with more than 1
            $firstPage .= '&hellip;';  //  add "..." between "1st page"-link and first page in $range
        }
    }
    return $firstPage;
}
public function lastPage() 
{
    if ($this->currentPage < ($this->numPages - $this->midRange)) {  //  if number of pages between "currentPage" and "last page" is equal to $midRange
        if (($this->currentPage < ($this->numPages - $this->midRange) - 1)) {  //  if number of pages between $currentPage and "last page" exceeds $range with more than two
            $lastPage .= '&hellip;';  //  add "..." between "last page"-link and last page in $range
        } 
        $lastPage .= '<a href="'.$this->queryString.'&'.$this->pageIdentifier.'='.$this->numPages.'" class="last">'.$this->numPages.'</a>';   //  show "last page"-link
    }
    return $lastPage;
}

#  Range of pages between (prev first ...) and (... last next)
public function listPages() 
{
    for ($i = ($this->currentPage - $this->midRange); $i < (($this->currentPage + $this->midRange) + 1); $i++){
       if (($i > 0) && ($i <= $this->numPages))  //  if page number are within page range
       {
          if ($i == $this->currentPage) { $listPages .= '<a class="current">'.$i.'</a>'; }  //  if we're on current page
          else { $listPages .= '<a href="'.$this->queryString.'&'.$this->pageIdentifier.'='.$i.'">'.$i.'</a>'; }  //  if not current page
        }
    }
    return $listPages; 
}

  • Es kommt selten vor, dass Benutzer mit geringen Wiederholungszahlen Fragen mit einer so hohen Qualität stellen wie Ihre. Prost!

    – Madaras Geist

    30. Juni 2012 um 9:04 Uhr

  • Tolle Fragenbeschreibung. 1+

    – Arash Milani

    30. Juni 2012 um 18:16 Uhr

  • Es tut mir leid, Jungs, aber ich weiß wirklich nicht einmal, worum es bei all diesen Preisen geht … Ich sollte mir wahrscheinlich die Zeit nehmen und herausfinden, wie diese Seite funktioniert, anstatt nur Fragen zu stellen … Ich werde nachsehen es

    – ThomasK

    2. Juli 2012 um 14:12 Uhr

  • Gute Frage, aber warum gehen Sie nicht zu Ihrer alten Frage und wählen eine Antwort aus?

    – dynamisch

    2. Juli 2012 um 16:09 Uhr

Benutzer-Avatar
invisal

Dies ist, was ich für meine Paginierung mache.

$startPage = $currentPage - 4;
$endPage = $currentPage + 4;

if ($startPage <= 0) {
    $endPage -= ($startPage - 1);
    $startPage = 1;
}

if ($endPage > $totalPage)
    $endPage = $totalPage;

if ($startPage > 1) echo " First ... ";
for($i=$startPage; $i<=$endPage; $i++) echo " {$i} ";
if ($endPage < $totalPage) echo " ... Last ";

Ich glaube, mein Code ist selbsterklärend, aber ich werde versuchen, ihn in einfachem Englisch zu erklären. Zunächst müssen Sie zwei Dinge wissen, bevor Sie eine Paginierung erstellen können: $totalPage und $aktuelleSeite.

Schritt 1: Angenommen, die aktuelle Seite liegt im mittleren Bereich. $startPage und $endPage speichern den Seitenbereich, den die Paginierung zu generieren versucht.

Schritt 2: Wenn $startPage negativ ist, dann müssen Sie nachholen $endPage.

Schritt 3: Wenn $endPage Überschuss $totalPagedann $endPage ist die letzte Seite.

Schritt 4: Paginierung in HTML generieren. (Es liegt an Ihnen, wie Ihre Paginierung aussehen soll. Ich werde einfach einfachen Text verwenden, um meine Paginierung darzustellen.)

if ($startPage > 1) echo " First ... ";
for($i=$startPage; $i<=$endPage; $i++) echo " {$i} ";
if ($endPage < $totalPage) echo " ... Last ";

Fehler in meiner vorherigen Logik behoben

$startPage = ($curPage < 5)? 1 : $curPage - 4;
$endPage = 8 + $startPage;
$endPage = ($totalPage < $endPage) ? $totalPage : $endPage;
$diff = $startPage - $endPage + 8;
$startPage -= ($startPage - $diff > 0) ? $diff : 0;

if ($startPage > 1) echo " First ... ";
for($i=$startPage; $i<=$endPage; $i++) echo " {$i} ";
if ($endPage < $totalPage) echo " ... Last ";

  • Beantwortet dies die Frage?

    – 472084

    1. Juli 2012 um 19:13 Uhr

  • Nun, ich glaube, meine Logik ist einfach und beantworte die Frage.

    – invisal

    2. Juli 2012 um 8:30 Uhr

  • Ich habe deinen Vorschlag direkt unter meinem hier eingefügt: dev.thomaskile.me/?page=test-zone&module=Paginator (fast nur kopiert/eingefügt), und am Anfang sind Sie fast genau richtig. Aber am Ende sieht man deutlich den Unterschied…

    – ThomasK

    2. Juli 2012 um 14:57 Uhr


  • Am Ende ist es nicht möglich, die startPage einfach auf -4 zu setzen. Wir müssen es auf eine bestimmte Seitenzahl setzen, um es zu sperren, damit die Anzahl der sichtbaren Seiten wie am Anfang funktioniert …

    – ThomasK

    2. Juli 2012 um 15:14 Uhr


  • Ich sah den Fehler meiner Logik am Ende. Ich werde versuchen, es zu beheben, ohne zu viel if-else-elseif zu verwenden. Ich glaube, es kann mit etwas Mathematik gelöst werden.

    – invisal

    2. Juli 2012 um 15:28 Uhr

Benutzer-Avatar
Herbst Leonard

Dieses Gespräch war ein toller Start für mich! Aber ich wollte einen Paginator, der den Absichten der ursprünglichen Frage näher kommt:
1) Könnte in einer Funktion mit Variablen enthalten sein, um die Gesamtzahl der Seiten, die aktuelle Seite und die Anzahl der Seiten auf jeder Seite der aktuellen Seite zu ändern, die angezeigt werden sollen.
2) Behält eine konstante Breite bei, ähnlich wie beim ursprünglichen Beitrag:

 <  [1]   2    3    4    5    6   7    ...   99   >
 <   1   [2]   3    4    5    6   7    ...   99   >
 <   1    2   [3]   4    5    6   7    ...   99   >
 <   1    2    3   [4]   5    6   7    ...   99   >
 <   1    2    3    4   [5]   6   7    ...   99   >
 <   1   ...   4    5   [6]   7   8    ...   99   >
 <   1   ...   5    6   [7]   8   9    ...   99   >
 <   1   ...   92   93  [94]  95  96   ...   99   >
 <   1   ...   93   94  [95]  96  97   98    99   >
 <   1   ...   93   94   95  [96] 97   98    99   >
 <   1   ...   93   94   95   96 [97]  98    99   >
 <   1   ...   93   94   95   96  97  [98]   99   >
 <   1   ...   93   94   95   96  97   98   [99]  >

3) Zeigt weiterhin die Zahl “2” anstelle von “…” an, wenn Sie 1 … 3 hätten
4) Dasselbe für das Ende.

Also hier ist, was ich getan habe. Ich codiere in einer anderen Sprache (Coffeescript), aber es sollte trotzdem als guter Sudo-Code funktionieren:

get_pages_array = (total_page, each_side, curr_page) ->
    if total_page <= (2*each_side)+5
        # in this case, too few pages, so display them all
        start_page = 1
        end_page = total_page
    else if curr_page<=each_side+3
        # in this case, curr_page is too close to the beginning
        start_page = 1
        end_page = (2*each_side)+3
    else if curr_page >= total_page - (each_side+2)
        # in this case, curr_page is too close to the end
        start_page = total_page - (2*each_side) - 2
        end_page = total_page
    else
        # regular case
        start_page = curr_page - each_side
        end_page = curr_page + each_side
    return_me = []
    if start_page> 1
        return_me.push "1"
    if start_page>2
        return_me.push "..."
    for x in [start_page..end_page]
        return_me.push x
    if end_page<total_page-1
        return_me.push "..."
    if end_page<total_page
        return_me.push total_page
    return return_me

Ich verwende diesen Code für each_side = 2, also bin ich mir sicher, dass es dort funktioniert.

BEARBEITEN: Feste Logik gemäß @Vextil

  • Ich verwende derzeit Ihre Lösung, aber sie funktioniert nicht richtig, wenn each_side <> 2. Das Reparieren ist einfach, Sie müssen nur ersetzen end_page = each_side+5 Mit: end_page = (each_side * 2) + 3 Und das: start_page = total_page - (each_side+4) Mit: start_page = total_page - (each_side * 2) - 2

    – Vextil

    16. September 2016 um 14:41 Uhr


Hier ist ein Python-Programm, das zeigt, wie man das richtig macht:

def main():
    num_pages = 13
    page = 12

    window = 5
    start = page - window
    end = page + window - 1
    if start <= 0:
        end = end - start + 1
        start = 1
    if end > num_pages:
        end = num_pages
        start = max(end - (window * 2) + 1, 1)

    for no in range(start, end + 1):
        print "{}*".format(no) if page == no else no

if __name__ == '__main__':
    main()

  • Schöne Lösung, aber warum end = page + window - 1 Anstatt von end = page + window ?

    – David Kerr

    14. August 2019 um 20:50 Uhr


Benutzer-Avatar
ThomasK

Das ist einfach genial! Ich glaube, ich habe diesen Paginator dazu gebracht, so zu arbeiten, wie ich es beschrieben habe.
Schauen Sie doch mal rein und probieren Sie es hier aus http://dev.thomaskile.me/?page=test-zone&module=Paginator und lass mich wissen…

Nach viel logischem Mathestudium bin ich schließlich zu folgendem Schluss gekommen:
Damit dies auf verschiedenen Ebenen so unterschiedlich wirkt, müssen einige da sein if, elsef-s, um die Logik auf jeder Ebene separat zu behandeln. Ich werde versuchen, es zu erklären, aber es fällt mir schwer, es auf eine gute Art und Weise zu tun …

Diese Ebenen meine ich:

  • Wenn aktuelleSeite == ersteSeite :
    Berechnen Sie, wie viele Seiten nach der aktuellen Seite angezeigt werden sollen, beginnend mit der 2. Seite.
    Diese Berechnung musste basierend auf der Anzahl der Seitenrahmen durchgeführt werden, die höchstens vorhanden sein würden. (MidRange-Wert ist hier ein Schlüsselfaktor)

    [1] 2   3    4    5    6    7    8   ...   184   >
    
  • elseif aktuelleSeite ist zwischen firstPage- und midRange-Wert ausgeschöpft.
    Reduzieren Sie Seiten im Bereich um eins, um zu verhindern, dass der gesamte Paginator nach rechts verschoben wird, sobald prevPage hinzugefügt wurde. Berechnen Sie die Seiten, die vor und nach der aktuellen Seite angezeigt werden sollen, um die Anzahl der Seiten durch das Ganze gleich zu halten.

    <   1  [2]   3    4    5    6    7   ...   184   >
    <   1   2   [3]   4    5    6    7   ...   184   >
    <   1   2    3   [4]   5    6    7   ...   184   >
    
  • elseif midRange Wert ist auf jeder Seite maximal. Das heißt, wir sind irgendwo in der Mitte.
    MidRange-Seiten + die aktuelle Seite + MidRange-Seiten. Ziemlich direkt, denke ich …

    <   1  ...   3    4   [5]   6    7   ...   184   >
                          ...
                          ...
                          ...
    <   1  ...  178  179 [180] 181  182  ...   184   >
    
  • elseif aktuelleSeite ist zwischen midRange-Wert und lastPage
    Fast genauso wie am Anfang. Der Unterschied bestand darin, eine statische Seitenzahl zu berechnen, von der aus Seiten gestartet werden sollen, und dann die Seiten zu berechnen, die vor / nach der aktuellen Seite angezeigt werden sollen …
    (das war übrigens mein Kopfschmerz an diesem Wochenende)

    <   1  ...  178  179  180 [181] 182  183   184   >
    <   1  ...  178  179  180  181 [182] 183   184   >
    <   1  ...  178  179  180  181  182 [183]  184   >
    
  • elseif currentPage == numPages (Anzahl tatsächlicher Seiten). Ziemlich dasselbe wie die firstPage-Operation … berechnen, wie viele Seiten benötigt werden, um das Ganze zu füllen, und berechnen, wo man anfangen soll …

Was ich jetzt tun muss, ist, den Code selbst besser zu machen …

    <   1  ...  178  179  180  181  182  183  [184]  >

Das “Problem” in meinem Fall war, dass der gesamte Paginator alles basierend auf dem MidRange-Wert berechnen sollte und sonst nichts. Damit ich diesen Paginator in einem meiner zukünftigen Projekte ausführen kann, muss ich nur Folgendes tun:

    $paginator = new paginator((int));  //  e.g. number of total results from a db request

In den meisten Fällen muss ich möglicherweise eine persönliche Abfragezeichenfolge hinzufügen, um sicherzustellen, dass dies der Fall ist a href funktioniert:

    $paginator->set_queryString('my querystring');

Und das ist so ziemlich alles. Ich habe ein paar optionale Funktionen wie folgt eingerichtet:

    $paginator->set_resultsPerPage((int));
    $paginator->set_midRange((int));
    $paginator->set_pageIdentifier('querystring-pageNumber-identifier-name-for-get');  //  whatever I needed

Schließlich zeige ich den Paginator-Seitencontroller wie folgt an:

    $paginator->pageController('full');  //  full, med, min for different styles.

Wenn keiner davon gut genug ist, könnte ich jeden Button einfach so aufrufen:

    $paginator->prevPage();
    $paginator->firstPage();
    $paginator->listPages();
    $paginator->lastPage();
    $paginator->nextPage();
    $paginator->pageJumper();
    $paginator->perPageSelector();

Ich nehme an, Ihre Paginierung hat diese Struktur:

number_of_active_page + separate(…) + page(184) + next_page(>)

Sie können number_of_active_page auf 8 setzen (einschließlich prev_page(<) + pages ( ... and page number )

[1]  2   3   4   5   6   7   8         ...     184       >
[number_of_active_page(set to 8)] + separate + page + next_page  
 <   1  ...  3   4  [5]  6   7         ...     184       >

Benutzer-Avatar
Hritwij Shrivastava

import math
size = 3
len = 13

for page in range(1,10):
    if(( size*(page-1) ) >len):
        startPoint =  (size*(page-1)) - (size*(page- math.ceil(len/size)))
    else:
        startPoint =  ( size*(page-1) )

    if((startPoint +size)>len):
        endPoint = len
    else:
        endPoint = (startPoint +size -1)

    print("Page = "+str(page))
    print("start = " +str(startPoint))
    print("end = " +str(endPoint))
    print()

Benutzer-Avatar
Mandeloli

Hear ist ein einfaches Beispiel für die Paginierungsanzeige:

$paginationDisplay = ""; // Initialize the pagination output variable
// This code runs only if the last page variable is not equal to 1, 
// if it is only 1 page we require no paginated links to display
if ($lastPage != "1"){
  // This shows the user what page they are on, and the total number of pages
  $paginationDisplay .= 'Page <strong>' . $pn . 
            '</strong> of ' . $lastPage. 'last';
  // If we are not on page 1 we can place the Back button
  if ($pn != 1) {
     $previous = $pn - 1;
     $paginationDisplay .=  '&nbsp;  <a href="' . 
            $_SERVER['PHP_SELF'] . '?pn=' . $previous . '"> Back</a> ';
    } 
    // Lay in the clickable numbers display here between the Back and Next links
    $paginationDisplay .= '<span>' . $centerPages . '</span>';
    // If we are not on the very last page we can place the Next button
    if ($pn != $lastPage) {
        $nextPage = $pn + 1;
        $paginationDisplay .=  '&nbsp;  <a href="' . 
            $_SERVER['PHP_SELF'] . '?pn=' . $nextPage . '"> Next</a> ';
    } 
}

  • Willkommen bei S.O. Sie können 4 Leerzeichen verwenden, um einen Codeblock zu erstellen, und 2 Leerzeichen, um eine Zeile aus Codeblöcken herauszubrechen. Mehr über den Hilfelink im Antworteditor.

    – Ricardo Souza

    1. Juli 2012 um 19:07 Uhr

1245710cookie-checkLogik hinter der Paginierung wie bei Google

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy