2012-06-30 3 views
24

Какова логика разбиения страницы на страницы google?логика для разбивки на страницы, например google

Мой Paginator идет что-то вроде этого:

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

Вот живой версии приведенного выше примера: http://www.dev.thomaskile.me/?page=test-zone&module=Paginator.
Я знаю, почему это происходит; Я установил количество pagenumbers для показа на каждой стороне текущей страницы до двух (2).

Я предпочел бы иметь диапазон чисел, равным примерно так:

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

Это в начале и в конце мне нужно внести изменения сома е, но не могу понять, как это сделать простое управление ...
Я хотел бы сделать его гибким. Значение Я хотел бы быть в состоянии изменить количество требуемых страниц на каждой стороне, и есть сценарий расширения и claculate все это ...

Вот мой код до сих пор:

/** 
* 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; 
} 
+8

Это редкий, чтобы увидеть низкие пользователи респ задавать вопросы с таким высоким качеством, как ваша , Ура! –

+0

Отличное описание вопроса. 1+ –

+0

Мне жаль парней, но на самом деле даже не знаю, что все эти ставки все о ... Я, вероятно, должен потратить время и узнать, как работает этот сайт, а не просто задавать вопросы ...Я посмотрю на него – ThomasK

ответ

32

Это то, что я делаю для моей 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 "; 

Я считаю, что мой код самостоятельно объяснить, но я попытаюсь объяснить на простом английском языке. Прежде всего, вам нужно знать две вещи, прежде чем вы сможете создать разбивку на страницы: $ totalPage и $ currentPage.

Шаг 1: Предполагая, что текущая страница находится в среднем диапазоне. $ startPage и $ endPage хранят диапазон страниц, которые разбивают на страницы, чтобы сгенерировать.

Шаг 2: Если $ StartPage отрицательна, то вам нужно макияж для $ endPage.

Шаг 3: Если $ endPage избыток $ totalPage, то $ endPage последняя страница.

Этап 4: Создание разбивки на страницы в HTML.(Это до вас, как вы хотите, чтобы ваша пагинацию смотреть. Я буду просто использовать простой текст, чтобы представить свою нумерацию страниц)

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

Fixed недостаток моей предыдущей логику

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

Отвечает ли это на вопрос? – 472084

+1

Ну, я считаю, что моя логика проста и отвечает на вопрос. – invisal

+0

Я поставил ваш sugestion прямо под моим здесь: http://dev.thomaskile.me/?page=test-zone&module=Paginator (почти просто скопированный/вставленный), и вначале ваше почти пятно. Но в конце вы ясно видите разницу ... – ThomasK

0

Я предполагаю, что ваша пагинация имеет такую ​​структуру:

number_of_active_page + отдельный (...) + страница (184) + next_page (>)

Вы можете установить number_of_active _page стал 8 (включая prev_page (<) + страницы (... и номер страницы)

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

Слушание представляет собой простой пример отображения разбиения на страницы:

$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> '; 
    } 
} 
+0

Добро пожаловать в SO. Вы можете использовать 4 сапа для создания блока кода и 2 пробела для разрыва строки из кодовых блоков. Подробнее о ссылке справки в редакторе ответов. – rcdmk

1

Это просто здорово! Я думаю, что у меня есть этот paginator, чтобы работать так, как я описал.
Пожалуйста, посмотрите и попробовать его здесь http://dev.thomaskile.me/?page=test-zone&module=Paginator и дайте мне знать ...

После большого логического математики, изучая я, наконец, пришел к такому выводу:
Для того, чтобы сделать этот акт так по-разному на разных уровней, должно быть около if, elsef -s для обработки логики на каждом уровне отдельно. Я попытаюсь объяснить, но трудно сделать в хорошем смысле ...

Это уровни о которых я говорю:

  • Если CurrentPage == Firstpage:
    Calculate сколько страниц нужно показывать после текущей страницы, начиная со второй страницы.
    Этот расчет необходимо сделать в зависимости от того, сколько блоков страниц будет в лучшем случае. (значение MIDRANGE является ключевым фактором здесь)

    [1] 2 3 4 5 6 7 8 ... 184 > 
    
  • ElseIf CurrentPage находится между Firstpage и значение MIDRANGE увеличившихся .
    Уменьшите количество страниц в диапазоне на единицу, чтобы предотвратить перемещение целого paginator вправо, как только будет добавлено значение prevPage. Вычислить страницы, которые будут отображаться до и после текущей страницы, чтобы количество страниц равнялось всем этим.

    < 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 максимизировано с каждой стороны. Это значит, что мы где-то посередине.
    midRange страницы + текущая страница + страницы среднего диапазона. Довольно прямо вперед, я думаю ...

    < 1 ... 3 4 [5] 6 7 ... 184 > 
             ... 
             ... 
             ... 
    < 1 ... 178 179 [180] 181 182 ... 184 > 
    
  • ElseIf CurrentPage находится между значением MIDRANGE и Lastpage
    Почти такой же, как и в начале . Разница в том, чтобы вычислить статический PageNumber, чтобы начать страницы с, а затем вычислить страницы, чтобы показать до/после текущей страницы ...
    (это, кстати, была моя головная боль в эти выходные)

    < 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 (количество татальных страниц). Практически так же, как и операция firstPage ... подсчитывает, сколько страниц нужно заполнить, и вычислить, с чего начать ...

Что мне нужно сделать сейчас, чтобы сделать сам код лучше ...

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

«Проблема» в моем случае было то, что весь Paginator должен рассчитать все на основе значения MIDRANGE и ничего больше. Для меня исполнить этот Paginator в любом из моего будущего проекта, все, что нужно сделать, это:

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

я мог бы в большинстве случаев необходимо добавить личные строки запроса, чтобы убедиться, что a href работает:

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

И это почти все. Я настроил пару дополнительных функций, как это:

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

Наконец я отобразить контроллер Paginator страницы, как это:

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

Если не из них достаточно хорошо, я мог бы просто позвонить каждый кнопка, как это:

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

Вы должны взглянуть на мою логику ниже. Я считаю, что он делает то, что вы хотите. – invisal

-1

Это логика пагинация у меня есть

$pLinks = 5; // Links per page 
$pMids = 3; 
$pTot = 10; // Total page 
$pSel = 1 // Selected page 

if (($pSel <= $pMids) || ($pTot <= $pLinks)) { 
    $sPage = 1;     
    $ePage = ($pTot <= $pLinks) ? $pTot : $pLinks; 
} else { 
    $etPage = $pSel + ($pMids - 1);    
    $ePage = ($etPage <= $pTot) ? $etPage : $pTot;    
    $sPage = $ePage - ($pLinks - 1);    
} 

if ($pSel > $sPage) { 
    $sL = '<a href="#" id="1">First</a>'; 
    $sN = '<a href="#" id="'.($pSel-1).'">&laquo;</a>'; 
} else { 
    $sL = 'First'; 
    $sN = '&laquo;'; 
} 

if ($pSel < $ePage) { 
    $eL = '<a href="#" id="'.$pTot.'">End</a>'; 
    $eN = '<a href="#" id="'.($pSel+1).'">&raquo;</a>'; 
} else { 
    $eL = 'End'; 
    $eN = '&raquo;'; 
} 

$pOptions = ''; 

$pOptions .= '<span class="iPage">'.$pSel.'/'.$pTot.'</span>'; 
$pOptions .= '<span class="renderFL">'.$sL.'</span>'; 
$pOptions .= '<span class="renderPN">'.$sN.'</span>'; 

for ($i = $sPage; $i <= $ePage; $i++) { 
    if($i != $pSel) { 
     $pOptions .= '<span><a href="#" id="'.$i.'">'.$i.'</a></span>'; 
    } else { 
     $pOptions .= '<span class="selected">'.$i.'</span>'; 
    } 
} 

$pOptions .= '<span class="renderPN">'.$eN.'</span>'; 
$pOptions .= '<span class="renderFL">'.$eL.'</span>'; 

Результат будет выглядеть следующим образом:

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

Этот разговор был отличный старт для меня! Но я хотел, чтобы paginator был ближе к намерениям исходного вопроса:
1) Может содержаться в функции с переменными, чтобы изменить общие страницы, текущую страницу и количество страниц с каждой стороны текущего показа.
2) поддерживает постоянную ширину, похожий на оригинальный пост:

< [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) продолжает выводить на экран число «2», а не «...» в тех случаях, когда вы бы 1 ... 3
4) То же самое для конца.

Итак, вот что я сделал. Я кодирование на другом языке (CoffeeScript), но он должен работать как хороший Судо-код в любом случае:

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 

Я использую этот код для each_side = 2, так что там я уверен, что это работает.

EDIT: фиксированная логика согласно @Vextil

+1

настоящее время я использую свое решение, но он не работает правильно, когда each_side <> 2. Крепление легко, нужно просто заменить 'end_page = each_side + 5' С: ' end_page = (each_side * 2) + 3' И это: 'start_page = total_page - (each_side + 4)' С: 'start_page = total_page - (each_side * 2) - 2' – Vextil

0

Вот программа Python, которая показывает, как сделать это правильно:

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() 
Смежные вопросы