Создание навигационного индекса

Задача
Список элементов на веб-странице очень длинный. Вы хотите упростить передвижение по такой странице.

Решение
Создайте навигационный индекс со ссылками на различные разделы списка.

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

В этом разделе приведено два примера, иллюстрирующих эти приемы. Оба они используют таблицу kjv. Примеры реализуют два вида отображения для стихов Книги Есфирь (The Book of Esther), хранящихся в таблице kjv:

• Одностраничный вывод, представляющий все стихи всех глав Книги Есфирь.


Список разбит на 10 разделов (по одному на главу) и содержит навигационный индекс, ссылки которого указывают на начало каждого раздела.

• Многостраничный вывод, содержащий страницу для стихов каждой из глав Книги Есфирь, а также главную страницу, которая предлагает пользователю выбрать нужную главу. Каждая из страниц выводит список глав в виде гиперссылок на страницы, отображающие стихи соответствующей главы. Благодаря таким ссылкам можно легко переходить с одной страницы на другую.

Создание одностраничного навигационного индекса
Рассмотрим пример, выводящий все стихи Книги Есфирь на одной странице, при этом стихи разбиты на разделы по главам. Для того чтобы вывести страницу так, чтобы каждый раздел содержал маркер навигации, поместите анкер (a name) перед началом стихов каждой новой главы:

(a name="1")Chapter 1(/a)
... список стихов главы 1...(a name="2")Chapter 2(/a)
... список стихов главы 2...
(a name="3")Chapter 3(/a)
... список стихов главы 3...
...

Будет сгенерирован список, включающий набор маркеров с названиями 1, 2, 3 и т. д. Для создания навигационного индекса сформируйте набор гиперссылок, каждая из которых указывает на один из маркеров name:

(a href="#1)Chapter 1(/a)
(a href="#2)Chapter 2(/a)
(a href="#3)Chapter 3(/a)
...

Символ # в каждом атрибуте href означает, что ссылка указывает на элемент той же страницы.


Например, href="#3" указывает на анкер с атрибутом name=" 3".

Реализовать такой навигационный индекс можно двумя способами:

• Извлечь записи (records) стихов в память и определить по ним, какие элементы должны присутствовать в навигационном индексе. Затем вывести и индекс, и список стихов.

• Заранее определить все необходимые анкеры и построить индекс. Список номеров глав можно получить так:

SELECT DISTINCT cnum FROM kjv WHERE bname = 'Esther' ORDER BY cnum;

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

Рассмотрим сценарий esther1.pl, реализующий первый подход к решению задачи. Это переделанный пример из раздела о вложенных списках:

#! /usr/bin/perl -w
# esther1.pl – выводит Книгу Есфирь на одной странице с навигационным индексом
use strict;
use lib qw(/usr/local/apache/lib/perl);
use CGI qw(:standard escape escapeHTML);
use Cookbook;
my $title = "The Book of Esther";
my $page = header ()
. start_html (-title => $title, -bgcolor => "white")
.


h3 ($title);
my $dbh = Cookbook::connect ();
# Извлекаем стихи из Книги Есфирь и сопоставляем каждому из них
# список стихов главы, в которую он входит.my $sth = $dbh->prepare (
"SELECT cnum, vnum, vtext FROM kjv
WHERE bname = 'Esther'
ORDER BY cnum, vnum");
$sth->execute ();
my %verses = ();
while (my ($cnum, $vnum, $vtext) = $sth->fetchrow_array ())
{
# инициализируем списком стихов главы пустой массив, если это ее первый стих,
# затем добавляем в массив номер и текст стиха.
$verses{$cnum} = [] unless exists ($verses{$cnum});
push (@{$verses{$cnum}}, p (escapeHTML ("$vnum. $vtext")));
}
# Определяем номера всех глав и используем их для построения навигационного
# индекса. Это будут ссылки в виде (a href="#num)Chapter num(/a), где num –
# это номер главы, а'#' означает ссылку внутри одной страницы.
# Ни URL-, ни HTML-кодирование не применяется (отображаемый текст в этом
# не нуждается). Проверьте, что номера глав упорядочиваются в числовом порядке
# (используйте { a <=> b }). Разделяем ссылки неразрывными пробелами.
my $nav_index;
foreach my $cnum (sort { $a <=> $b } keys (%verses))
{
$nav_index .= " " if $nav_index;
$nav_index .= a ({-href => "#$cnum"}, "Chapter $cnum");
}
# Теперь выводим список стихов каждой главы.


Перед каждым разделом вводится
# заголовок с номером главы и элементом навигационного индекса.
foreach my $cnum (sort { $a <=> $b } keys (%verses))
{
# добавляем анкер (a name) для этого раздела
$page .= p (a ({-name => $cnum}, font ({-size => "+2"}, "Chapter $cnum"))
. br ()
. $nav_index);
$page .= join ("", @{$verses{$cnum}}); # добавить список стихов главы
}
$dbh->disconnect ();
$page .= end_html ();
print $page;
exit (0);

Создание многостраничного навигационного индекса
Теперь рассмотрим сценарий на Perl esther2.pl, который может генерировать любую из нескольких страниц, отображающих стихи Книги Есфирь из таблицы kjv. Первая страница отображает список глав книги, а также инструкции по выбору главы. Каждая глава списка – это гиперссылка, которая по-вторно вызывает сценарий для вывода списка стихов соответствующей главы. Так как сценарий отвечает за формирование нескольких страниц, он должен уметь определять, какую из страниц выводить при каждом запуске.

Для этого сценарий исследует параметр chapter собственного URL, указывающий номер главы для вывода.


Если параметр chapter отсутствует или его значение не целое, то сценарий выводит первую страницу.

URL первой страницы будет таким:
http://apache.snake.net/cgi-bin/esther2.pl
Ссылки на страницы отдельных глав выглядят так (cnum – это номер главы):
http://apache.snake.net/cgi-bin/esther2.pl?chapter=cnum
Сценарий esther2.pl использует функцию CGI.pm param() для получения зна-
чения параметра chapter:
my $cnum = param ("chapter");
if (!defined ($cnum) || $cnum !~ /^\d+$/)
{
# Номер главы отсутствует или неправильный
}
else
{
# Номер главы указан правильно
}

Если параметр chapter отсутствует в URL, то $cnum будет содержать undef. В противном случае $cnum устанавливается в значение параметра, после того как проверено, что оно целочисленное (это делается для выявления случаев ввода некорректных значений с целью остановки работы сценария).

Вот полный текст сценария esther2.pl:

#! /usr/bin/perl -w
# esther2.pl – выводит Книгу Есфирь на нескольких страницах,
# по одной на главу, с навигационным индексом
use strict;
use lib qw(/usr/local/apache/lib/perl);
use CGI qw(:standard escape escapeHTML);
use Cookbook;
my $title = "The Book of Esther";
my $page = header () . start_html (-title => $title, -bgcolor => "white");
my ($left_panel, $right_panel);
my $dbh = Cookbook::connect ();
my $cnum = param ("chapter");
if (!defined ($cnum) || $cnum !~ /^\d+$/)
{
# Отсутствующая или неправильно сформированная страница; вывести
# главную страницу, левая панель которой содержит список всех глав# в виде гиперссылок, а правая - инструкции по выбору главы.
$left_panel = get_chapter_list ($dbh, 0);
$right_panel = p (strong ("The Book of Esther"))
. p ("Select a chapter from the list at left.");
}
else
{
# Указан номер главы; вывести в левой панели список глав, все главы,
# кроме текущей, представлены гиперссылками, а текущая выделена жирным шрифтом.
# Правая панель отображает список стихов текущей главы.
$left_panel = get_chapter_list ($dbh, $cnum);
$right_panel = p (strong ("The Book of Esther"))
. get_verses ($dbh, $cnum);
}
$dbh->disconnect ();
# Оформить страницу как однострочную таблицу из трех ячеек
# (средняя ячейка - разделитель)
$page .= table (Tr (
td ({-valign => "top", -width => "15%"}, $left_panel),
td ({-valign => "top", -width => "5%"}, " "),
td ({-valign => "top", -width => "75%"}, $right_panel)
));
$page .= end_html ();
print $page;
exit (0);
# ----------------------------------------------------------------------
# Создать навигационный индекс в виде списка ссылок на страницы каждой главы
# Книги Есфирь. Заголовки имеют форму "Chapter n"; номера глав встроены
# в ссылки в виде параметров chapter=num
# $dbh - это дескриптор базы данных, $cnum - номер главы, информация которой
# выводится в настоящий момент. Заголовок из списка глав, соответствующий
# этому номеру, выводится как статический текст, а все остальные -
# как гиперссылки на другие страницы глав. Введите 0, чтобы все записи
# стали гиперссылками (ни одна из глав не имеет номера 0).
# Кодирование не производится, так как номера глав - это числа,
# и кодирование не требуется.
sub get_chapter_list
{
my ($dbh, $cnum) = @_;
my $nav_index;
my $ref = $dbh->selectcol_arrayref (
"SELECT DISTINCT cnum FROM kjv
WHERE bname = 'Esther' ORDER BY cnum"
);foreach my $cur_cnum (@{$ref})
{
my $link = url () . "?chapter=$cur_cnum";
my $label = "Chapter $cur_cnum";
$nav_index .= br () if $nav_index; # разделить записи, используя

# использовать статический, выделенный жирным шрифтом текст
# для текущей главы, для остальных - гиперссылку
$nav_index .= ($cur_cnum == $cnum
? strong ($label)
: a ({-href => $link}, $label));
}
return ($nav_index);
}
# Получить список стихов указанной главы. Если отсутствует, то введен
# неправильный номер, но будем разумно обрабатывать такую ситуацию.
sub get_verses
{
my ($dbh, $cnum) = @_;
my $ref = $dbh->selectall_arrayref (
"SELECT vnum, vtext FROM kjv
WHERE bname = 'Esther' AND cnum = ?",
undef, $cnum);
my $verses = "";
foreach my $row_ref (@{$ref})
{
$verses .= p (escapeHTML ("$row_ref->[0]. $row_ref->[1]"));
}
return ($verses eq "" # нет стихов?
? p ("No verses in chapter $cnum were found.")
: p ("Chapter $cnum:") . $verses);
}

Оцените статью: (0 голосов)
0 5 0

Статьи из раздела MySQL на эту тему:
Извлечение изображений и других двоичных данных
Использование результатов запроса для загрузки файлов
Представление результатов запроса в виде абзацев
Представление результатов запроса в виде гиперссылок
Представление результатов запроса в виде списков