Создание постраничной навигации: два варианта
При создании сайтов крайне часто появляется необходимость создания меню постраничной навигации. Иначе говоря - списка страниц (точнее, номеров страниц), который используется для перехода между ними. Ниже приводится два варианта создания такого меню.
Вариант номер один: многоточия
Достаточно широко распространенный вариант постраничной навигации, в котором пользователь видит текущую страницу, ссылки на соседние страницы и многоточия, означающие, что все показать просто негде. Собственно, этот вариант очень хорош в случае, когда места для меню не очень много и размер его должен быть предсказуем.
Итак, для начала создаем функцию, которая нам сделает набор данных, необходимый для вывода.
Параметры:
- $baseurl - базовый адрес страницы, к которому будет добавляться параметр с номером страницы
- $currpage - номер текущей страницы
- $pcnt - общее количество страниц
- $param - параметр для адресной строки, который будет содержать номер страницы (необязательный параметр)
- $delta - сколько соседних страниц надо показывать (необязательный параметр)
-
function show_pagination($baseurl, $currpage, $pcnt, $param='p', $delta=3) {
-
if ($pcnt == 0) {
-
$pcnt = 1;
-
}
-
$pages['prev'] = ($currpage > 1) ? ($baseurl.'&'.$param.'=1') : '#';
-
$pages['next'] = ($currpage < $pcnt) ? ($baseurl.'&'.$param.'='.$pcnt) : '#';
-
$from = $currpage - $delta;
-
$pages['need_p_dots'] = ($from > 0);
-
if ($from < 1) {
-
$from = 1;
-
}
-
$to = $currpage + $delta;
-
$pages['need_t_dots'] = ($to < $pcnt);
-
if ($to > $pcnt) {
-
$to = $pcnt;
-
}
-
for ($i = $from; $i <= $to; $i++) {
-
$pages['pages'],
-
'num' => $i,
-
'url' => $baseurl.'&'.$param.'='.$i,
-
'class' => (($i == $currpage) ? 'current' : 'normal')
-
)
-
);
-
} // for - generate pages
-
-
return $pages;
-
} // show_pagination
Теперь вызываем функцию:
-
$pagination = show_pagination('index.php?op=forum&sub=view&fid=5', $current_page, $pages_count);
И выводим данные:
-
$output = '
-
<table cellpadding="2" cellspacing="0">
-
<tr>
-
<td>
-
<a href="'.$pagination['prev'].'">в начало</a>
-
</td>
-
'.($pagination['need_p_dots'] ? '<td>...</td>' : '');
-
$output .= '
-
<td class="'.$pagination['pages'][$i]['class'].'">
-
<a href="'.$pagination['pages'][$i]['url'].'">'.$pagination['pages'][$i]['num'].'</a>
-
</td>';
-
} // for all pages
-
$output .= ($pagination['need_t_dots'] ? '<td>...</td>' : '').'
-
<td>
-
<a href="'.$pagination['next'].'">в конец</a>
-
</td>
-
</tr>
-
</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 - сколько соседних страниц надо показывать (необязательный параметр)
-
function show_pages_single($from, $to, $page, $page_count, $baseurl, $param) {
-
$output = '';
-
if ($from < $page_count) {
-
if ($to > $page_count) {
-
$to = $page_count;
-
}
-
for($i = $from; $i <= $to; $i++) {
-
$output .= ' <a href="'.(($i == $page) ? '' : ($baseurl.'&'.$param.'='.$i)).'">'.$i.'</a> ';
-
} // for
-
} // if ($from < $page_count)
-
return $output;
-
} // show_pages_single
-
-
function show_pages_ranges($from, $to, $page, $page_count, $baseurl, $param, $delta) {
-
$output = '';
-
if ($from < $page_count) {
-
if ($to > $page_count - 1) {
-
$to = $page_count - 1;
-
}
-
for($i = $from; $i <= $to; $i += $delta) {
-
if ($i > $page_count - 1) {
-
$i = $page_count - 1;
-
}
-
$curr_to = ((($i + $delta - 1) > ($page_count - 1)) ? ($page_count - 1) : ($i + $delta - 1));
-
$output .= ' <a href="'.$baseurl.'&'.$param.'='.$i.'">'.$i.'-'.$curr_to.'</a> ';
-
} // for
-
} // if ($from < $page_count)
-
return $output;
-
} // show_pages_ranges
-
-
function show_pages($baseurl, $page, $page_count, $param='p', $delta=10) {
-
$output = '';
-
if ($page_count > 1) {
-
if ($page > 1) {
-
$output .= '<a href="'.($baseurl.'&'.$param.'='.($page - 1)).'">←</a> ';
-
}
-
if ($page < $delta) {
-
$output .= show_pages_single(1, $delta - 1, $page, $page_count, $baseurl, $param);
-
$output .= show_pages_ranges($delta, $page_count, $page, $page_count, $baseurl, $param, $delta);
-
} // $page < $delta
-
else {
-
$output .= show_pages_ranges(1, floor($page / $delta) * $delta, $page, $page_count, $baseurl, $param, $delta);
-
$output .= show_pages_ranges(floor($page / $delta) * $delta + $delta, $page_count, $page, $page_count, $baseurl, $param, $delta);
-
} // $page >= $delta
-
if ($page != $page_count) {
-
$output .= ' <a href="'.($baseurl.'&'.$param.'='.($page + 1)).'">→</a>';
-
}
-
} // if ($page_count > 1)
-
return $output;
-
} // show_pages
Теперь вызываем сделанное:
В результате такого вызова получим:
← 1 2 3 4 5 6 7 8 9 10-19 →
Заключение
Мы рассмотрели два варианта создания постраничной навигации. В будущем мы, возможно, еще вернемся к этой теме. Но, в принципе, опубликованного материала достаточно для того, чтобы жизнь стала проще :).


March 23rd, 2007 at 00:56 Quote
Скриптик очень хороший, удобный, а главное, полезный ;) Так держать и продолжать в том же духе... Как грицо: "more drama plx" ^_^
May 24th, 2007 at 12:59 Quote
Весь скрипт целиком мне немного сложновато понять, но
"1-10 10 11 12 13 14 ..." такой момент казался очень не привлекательным, поэтому 25ую строчку заменил на вот это: http://pastebin.parentnode.org/14502
May 24th, 2007 at 13:04 Quote
why not... просто второй вариант делался для клиента, который захотел чтобы было именно так :)
May 24th, 2007 at 15:12 Quote
чОрт, ашибко, чутог.
if ($page>=$curr_to), а не if ($page==$curr_to) :) вот.
Дим, какие-то слиишком требовательные клиенты :)
По-моему, так просто симпотичнее. :)
May 24th, 2007 at 23:09 Quote
Намучавшимь с аяксом, переделал эту функцию под джаваскрипт. Ничего сложного, но если кому-нибудь нужно будет: http://pastebin.parentnode.org/14584
Этот вариант чисто для моего случая; я там убрал аттрибут param так как использую mod_rewrite, если очень захотеть можно его добавить, глянув где он в оригинале. :-)
May 25th, 2007 at 06:47 Quote
Corsair @ 24.05.2007, 23:09 #
Возник вопрос. Может мне сделать у нас на TMBU место для закидывания кода и добавления своих заметок?
May 25th, 2007 at 09:24 Quote
Filosoff @ 25.05.2007, 06:47 #
Пейсбин типо? Было бы удобно, да. :-) Еще если бы пользователи могли комментарии добавлять, типо обсуждение кода и все такое, было бы очень удобно. :-)
May 25th, 2007 at 09:26 Quote
Блин, только что в голову вбилась мысль: Сделать бы еще возможность редактирование кода автором :-)
May 25th, 2007 at 14:20 Quote
Corsair @ 25.05.2007, 09:24 #
готово.
закинул туда твой код для теста: http://tmbu.info/code/1
May 25th, 2007 at 17:25 Quote
Filosoff @ 25.05.2007, 14:20 #
Супер. Теперь можно пожелания? :))
Как-нибудь сделать отображаемый код шире... оверфлоуом, что ли... Чтобы не "ломать" сайт. :)
И побольше textarea, и прописать этому всему добру субдомейн типо http://pastebin.tmbu.info/1 :-)
May 25th, 2007 at 22:05 Quote
Corsair @ 25.05.2007, 17:25 #
так вроде и сейчас не ломается. просто строки переносятся. вроде как удобнее читать.
Corsair @ 25.05.2007, 17:25 #
textarea нужен только для удобного copy-paste, так что я его только незначительно увеличил.
субдомен можно, но только для редиректа. по некоторым соображениям хочу именно каталог. так устроит?
May 25th, 2007 at 22:10 Quote
Filosoff @ 25.05.2007, 22:05 #
Ну если будет выдаваться ссылка на субдомейн, то можно :-)
Кстати еще бы возможность комментить и редактировать код автором, было бы вообще супер :-))
May 25th, 2007 at 22:19 Quote
Corsair @ 25.05.2007, 22:10 #
комменты можно сделать. а редактирование... тогда ведь регистрацию надо. тяжеловесно будет.
May 26th, 2007 at 00:05 Quote
Filosoff @ 25.05.2007, 22:19 #
Зачем регистрацию? :) Можно, например, при добавлении кода предложить ввести пароль для редактирования. Ну мысль ты понял, я уверен. :-)
May 26th, 2007 at 08:58 Quote
Corsair @ 26.05.2007, 00:05 #
ok. сделаю потом :)