web-dev-qa-db-fra.com

Logique derrière la pagination comme Google

Quelle est la logique du comportement de la pagination de Google?

Mon paginateur va quelque chose comme ça:

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

Voici une version en direct de l'exemple ci-dessus: http://www.dev.thomaskile.me/?page=Test-zone&module=paginator .
[.____] Je sais pourquoi cela se passe; J'ai défini la quantité de numéros de page à afficher de chaque côté de la page actuelle à deux (2).

Je préférerais avoir la gamme de chiffres pour être égaux comme ceci:

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

C'est au début et la fin dont j'ai besoin de faire des changements, mais je ne peux pas comprendre comment en faire une opération facile ...
[.____] J'aimerais aussi faire flexible. Ce qui signifie que je voudrais pouvoir modifier le nombre de pages recherchées de chaque côté et que le script se développera et le calculer tout ...

Voici mon code jusqu'à présent:

/**
 *  page controller buttons 
 *  @param str $this->querySting      href="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; 
}
33
ThomasK

C'est ce que je fais pour ma pagination.

$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 ";

Je crois que mon code est expliqué auto-expliqué, mais je vais essayer de l'expliquer en anglais clair. Tout d'abord, vous devez connaître deux choses avant que vous puissiez générer une pagination: $ totalpage et $-courant.

Étape 1: En supposant que la page en cours soit à mi-parcours. $ startpage et $ EndPage Store Gamme de page que la pagination tente de générer.

étape 2: Si -$ startpage est négatif, alors vous devez faire maquillage pour $ endpage.

Étape: Si $ endpage excès $ totalpage, puis $ endpage est la dernière page.

étape 4: générer une pagination dans HTML. (C'est à vous de choisir votre pagination. Je vais simplement utiliser un texte brut pour représenter ma pagination)

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

défaut fixe à ma logique précédente

$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 ";
40
invisal

Cette conversation a été un bon départ pour moi! Mais je voulais plus près d'un paginateur des intentions de la question initiale, que:
[.____] 1) pourrait être contenu dans une fonction avec des variables pour modifier les pages totales, la page en cours et le nombre de pages de chaque côté du courant à afficher.
2) maintient une largeur constante, semblable à celle d'origine:

 <  [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) Continue à afficher le numéro "2" plutôt que "..." dans les cas où vous auriez 1 ... 3
4) Même chose pour la fin.

Alors voici ce que j'ai fait. Je codiste dans une langue différente (Coffeescript), mais cela devrait fonctionner comme bon sudo-code:

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

J'utilise ce code pour chaque_side = 2, c'est là que je suis sûr qu'il fonctionne.

Modifier: Logique fixe selon @vextil

5
Autumn Leonard

Voici un Python programme qui montre comment procéder correctement:

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()
1
John Wheeler