This Might Be Useful

Создание постраничной навигации: два варианта

При создании сайтов крайне часто появляется необходимость создания меню постраничной навигации. Иначе говоря - списка страниц (точнее, номеров страниц), который используется для перехода между ними. Ниже приводится два варианта создания такого меню.

Вариант номер один: многоточия

Достаточно широко распространенный вариант постраничной навигации, в котором пользователь видит текущую страницу, ссылки на соседние страницы и многоточия, означающие, что все показать просто негде. Собственно, этот вариант очень хорош в случае, когда места для меню не очень много и размер его должен быть предсказуем.

Итак, для начала создаем функцию, которая нам сделает набор данных, необходимый для вывода.

Параметры:

  • $baseurl - базовый адрес страницы, к которому будет добавляться параметр с номером страницы
  • $currpage - номер текущей страницы
  • $pcnt - общее количество страниц
  • $param - параметр для адресной строки, который будет содержать номер страницы (необязательный параметр)
  • $delta - сколько соседних страниц надо показывать (необязательный параметр)
PHP:
  1. function show_pagination($baseurl, $currpage, $pcnt, $param='p', $delta=3) {
  2.   if ($pcnt == 0) {
  3.     $pcnt = 1;
  4.   }
  5.   $pages = array();
  6.   $pages['prev'] = ($currpage > 1) ? ($baseurl.'&'.$param.'=1') : '#';
  7.   $pages['next'] = ($currpage < $pcnt) ? ($baseurl.'&amp;'.$param.'='.$pcnt) : '#';
  8.   $from = $currpage - $delta;
  9.   $pages['need_p_dots'] = ($from > 0);
  10.   if ($from < 1) {
  11.     $from = 1;
  12.   }
  13.   $to = $currpage + $delta;
  14.   $pages['need_t_dots'] = ($to < $pcnt);
  15.   if ($to > $pcnt) {
  16.     $to = $pcnt;
  17.   }
  18.   $pages['pages'] = array();
  19.   for ($i = $from; $i <= $to; $i++) {
  20.     array_push(
  21.       $pages['pages'],
  22.       array(
  23.         'num' => $i,
  24.         'url' => $baseurl.'&amp;'.$param.'='.$i,
  25.         'class' => (($i == $currpage) ? 'current' : 'normal')
  26.       )
  27.     );
  28.   } // for - generate pages
  29.  
  30.   return $pages;
  31. } // show_pagination

Теперь вызываем функцию:

PHP:
  1. $pagination = show_pagination('index.php?op=forum&sub=view&fid=5', $current_page, $pages_count);

И выводим данные:

PHP:
  1. $output = '
  2.     <table cellpadding="2" cellspacing="0">
  3.       <tr>
  4.         <td>
  5.           <a href="'.$pagination['prev'].'">в начало</a>
  6.         </td>
  7.         '.($pagination['need_p_dots'] ? '<td>...</td>' : '');
  8. for ($i = 0; $i < count($pagination['pages']); $i++) {
  9.     $output .= '
  10.         <td class="'.$pagination['pages'][$i]['class'].'">
  11.           <a href="'.$pagination['pages'][$i]['url'].'">'.$pagination['pages'][$i]['num'].'</a>
  12.         </td>';
  13. } // for all pages
  14. $output .= ($pagination['need_t_dots'] ? '<td>...</td>' : '').'
  15.         <td>
  16.           <a href="'.$pagination['next'].'">в конец</a>
  17.         </td>
  18.       </tr>
  19. </table>';

В результате получим следующее ($delta равно 3):

  • Первая страница:
    в начало 1 2 3 4 ... в конец
  • Пятая страница:
    в начало ... 2 3 4 5 6 7 8 ... в конец

Остается только сделать кусочек CSS, в котором будут описаны классы для страниц - td.current для текущей и td.normal для остальных.

Вариант номер два: диапазоны

На мой взгляд, этот вариант выглядит лучше предыдущего и использовать его удобнее. Отличается он тем, что вместо многоточий выводятся диапазоны страниц с определенным шагом. Таким образом пользователь сразу видит, сколько всего страниц, и может перейти к нужной странице намного быстрее (просто кликнув на диапазон).

Итак, для реализации этого нам понадобится три функции. Использовать мы будем только show_pages(), остальные две - служебные.

Параметры show_pages() такие же, как и в варианте номер один:

  • $baseurl - базовый адрес страницы, к которому будет добавляться параметр с номером страницы
  • $currpage - номер текущей страницы
  • $pcnt - общее количество страниц
  • $param - параметр для адресной строки, который будет содержать номер страницы (необязательный параметр)
  • $delta - сколько соседних страниц надо показывать (необязательный параметр)
PHP:
  1. function show_pages_single($from, $to, $page, $page_count, $baseurl, $param) {
  2.   $output = '';
  3.   if ($from < $page_count) {
  4.     if ($to > $page_count) {
  5.       $to = $page_count;
  6.     }
  7.     for($i = $from; $i <= $to; $i++) {
  8.       $output .= ' <a href="'.(($i == $page) ? '' : ($baseurl.'&amp;'.$param.'='.$i)).'">'.$i.'</a> ';
  9.     } // for
  10.   } // if ($from < $page_count)
  11.   return $output;
  12. } // show_pages_single
  13.  
  14. function show_pages_ranges($from, $to, $page, $page_count, $baseurl, $param, $delta) {
  15.   $output = '';
  16.   if ($from < $page_count) {
  17.     if ($to > $page_count - 1) {
  18.       $to = $page_count - 1;
  19.     }
  20.     for($i = $from; $i <= $to; $i += $delta) {
  21.       if ($i > $page_count - 1) {
  22.         $i = $page_count - 1;
  23.       }
  24.       $curr_to = ((($i + $delta - 1) > ($page_count - 1)) ? ($page_count - 1) : ($i + $delta - 1));
  25.       $output .= ' <a href="'.$baseurl.'&amp;'.$param.'='.$i.'">'.$i.'-'.$curr_to.'</a> ';
  26.     } // for
  27.   } // if ($from < $page_count)
  28.   return $output;
  29. } // show_pages_ranges
  30.  
  31. function show_pages($baseurl, $page, $page_count, $param='p', $delta=10) {
  32.   $output = '';
  33.   if ($page_count > 1) {
  34.     if ($page > 1) {
  35.       $output .= '<a href="'.($baseurl.'&amp;'.$param.'='.($page - 1)).'">&larr;</a> ';
  36.     }
  37.     if ($page < $delta) {
  38.       $output .= show_pages_single(1, $delta - 1, $page, $page_count, $baseurl, $param);
  39.       $output .= show_pages_ranges($delta, $page_count, $page, $page_count, $baseurl, $param, $delta);
  40.     } // $page < $delta
  41.     else {
  42.       $output .= show_pages_ranges(1, floor($page / $delta) * $delta, $page, $page_count, $baseurl, $param, $delta);
  43.       $output .= show_pages_single(floor($page / $delta) * $delta, floor($page / $delta) * $delta + $delta - 1, $page, $page_count, $baseurl, $param);
  44.       $output .= show_pages_ranges(floor($page / $delta) * $delta + $delta, $page_count, $page, $page_count, $baseurl, $param, $delta);
  45.     } // $page >= $delta
  46.     if ($page != $page_count) {
  47.       $output .= ' <a href="'.($baseurl.'&amp;'.$param.'='.($page + 1)).'">&rarr;</a>';
  48.     }
  49.   } // if ($page_count > 1)
  50.   return $output;
  51. } // show_pages

Теперь вызываем сделанное:

PHP:
  1. echo show_pages('index.php', 7, 20);

В результате такого вызова получим:
← 1 2 3 4 5 6 7 8 9 10-19 →

Заключение

Мы рассмотрели два варианта создания постраничной навигации. В будущем мы, возможно, еще вернемся к этой теме. Но, в принципе, опубликованного материала достаточно для того, чтобы жизнь стала проще :).

· Включение показа menu bar
· Изменение значения кнопки power в Start Menu со Sleep на Shut Down
· Tweaks for Firefox 3’s “AwesomeBar” location bar
· Добавление папок в контекстное меню Send To
· Оптимизация Windows XP

- Коментировать
- Trackback

15 Responses to “Создание постраничной навигации: два варианта”


  1. NeX1k Says:

    Скриптик очень хороший, удобный, а главное, полезный ;) Так держать и продолжать в том же духе... Как грицо: "more drama plx" ^_^

  2. NeX1k Says:

    Весь скрипт целиком мне немного сложновато понять, но
    "1-10 10 11 12 13 14 ..." такой момент казался очень не привлекательным, поэтому 25ую строчку заменил на вот это: http://pastebin.parentnode.org/14502

  3. Filosoff Says:

    why not... просто второй вариант делался для клиента, который захотел чтобы было именно так :)

  4. NeX1k Says:

    чОрт, ашибко, чутог.
    if ($page>=$curr_to), а не if ($page==$curr_to) :) вот.
    Дим, какие-то слиишком требовательные клиенты :)
    По-моему, так просто симпотичнее. :)

  5. Corsair Says:

    Намучавшимь с аяксом, переделал эту функцию под джаваскрипт. Ничего сложного, но если кому-нибудь нужно будет: http://pastebin.parentnode.org/14584
    Этот вариант чисто для моего случая; я там убрал аттрибут param так как использую mod_rewrite, если очень захотеть можно его добавить, глянув где он в оригинале. :-)

  6. Filosoff Says:

    Corsair @ 24.05.2007, 23:09 #

    Намучавшимь с аяксом, переделал эту функцию под джаваскрипт.

    Возник вопрос. Может мне сделать у нас на TMBU место для закидывания кода и добавления своих заметок?

  7. Corsair Says:

    Filosoff @ 25.05.2007, 06:47 #

    Возник вопрос. Может мне сделать у нас на TMBU место для закидывания кода и добавления своих заметок?

    Пейсбин типо? Было бы удобно, да. :-) Еще если бы пользователи могли комментарии добавлять, типо обсуждение кода и все такое, было бы очень удобно. :-)

  8. Corsair Says:

    Блин, только что в голову вбилась мысль: Сделать бы еще возможность редактирование кода автором :-)

  9. Filosoff Says:

    Corsair @ 25.05.2007, 09:24 #

    Пейсбин типо? Было бы удобно, да. :-) Еще если бы пользователи могли комментарии добавлять, типо обсуждение кода и все такое, было бы очень удобно. :-)

    готово.
    закинул туда твой код для теста: http://tmbu.info/code/1

  10. Corsair Says:

    Filosoff @ 25.05.2007, 14:20 #

    готово.
    закинул туда твой код для теста: http://tmbu.info/code/1

    Супер. Теперь можно пожелания? :))
    Как-нибудь сделать отображаемый код шире... оверфлоуом, что ли... Чтобы не "ломать" сайт. :)
    И побольше textarea, и прописать этому всему добру субдомейн типо http://pastebin.tmbu.info/1 :-)

  11. Filosoff Says:

    Corsair @ 25.05.2007, 17:25 #

    Как-нибудь сделать отображаемый код шире... оверфлоуом, что ли... Чтобы не "ломать" сайт. :)

    так вроде и сейчас не ломается. просто строки переносятся. вроде как удобнее читать.

    Corsair @ 25.05.2007, 17:25 #

    И побольше textarea, и прописать этому всему добру субдомейн типо http://pastebin.tmbu.info/1 :-)

    textarea нужен только для удобного copy-paste, так что я его только незначительно увеличил.
    субдомен можно, но только для редиректа. по некоторым соображениям хочу именно каталог. так устроит?

  12. Corsair Says:

    Filosoff @ 25.05.2007, 22:05 #

    textarea нужен только для удобного copy-paste, так что я его только незначительно увеличил.
    субдомен можно, но только для редиректа. по некоторым соображениям хочу именно каталог. так устроит?

    Ну если будет выдаваться ссылка на субдомейн, то можно :-)
    Кстати еще бы возможность комментить и редактировать код автором, было бы вообще супер :-))

  13. Filosoff Says:

    Corsair @ 25.05.2007, 22:10 #

    Кстати еще бы возможность комментить и редактировать код автором, было бы вообще супер :-))

    комменты можно сделать. а редактирование... тогда ведь регистрацию надо. тяжеловесно будет.

  14. Corsair Says:

    Filosoff @ 25.05.2007, 22:19 #

    комменты можно сделать. а редактирование... тогда ведь регистрацию надо. тяжеловесно будет.

    Зачем регистрацию? :) Можно, например, при добавлении кода предложить ввести пароль для редактирования. Ну мысль ты понял, я уверен. :-)

  15. Filosoff Says:

    Corsair @ 26.05.2007, 00:05 #

    Зачем регистрацию? :) Можно, например, при добавлении кода предложить ввести пароль для редактирования. Ну мысль ты понял, я уверен. :-)

    ok. сделаю потом :)

Leave a Reply

code