Конвертация и ввод макетов страниц
Итак, макет создан. Следующий шаг - конвертация его в формат NetCat.
Первый этап - копирование всех необходимых файлов (картинок, flash-роликов, внешних подключаемых файлов и пр.) на сервер. Обычно их копируют при помощи FTP-клиента в каталог images. В исходном файле в процессе конвертации следует заменить адреса картинок на новые. Рекомендуется использовать относительные ссылки - </images/logo.gif> вместо <http://www.example.ru/images/logo.gif> и <images/logo.gif> - особенно если сайт разрабатывается по временному адресу. Следующий шаг - разбиение макета на две части - хедер и футер. В примере, приведенном в предыдущем пункте, <разрыв> должен находиться после заголовка страницы:
<h1>Рога прямые</h1>
<p>
Следующий шаг - непосредственно конвертация макета. В обеих частях макета необходимо заменить динамические элементы специальными выражениями.
Разберем подробно каждый пункт. Прежде всего, следует учитывать, что для системы NetCat содержимое хедера и футера является обычным строковым выражением, которое нужно отобразить, выполнив прежде функцию PHP eval(). Т.е. хедер следует воспринимать в контексте следующего оператора: eval("echo \"$header\";"). Это значит, что для хедера (и футера) действуют все правила представления переменных, а именно:
- при вызове функций необходимо закрывать кавычку, сцеплять строку с функцией при помощи точки, сцеплять функцию со следующей строкой, открывать кавычку, например: <:text before".func($parameters)."text after:>;
- символы обратного слеша <\>, кавычки <">, знак доллара <$> нужно маскировать при помощи обратного слеша, т.е. для отображения символа <\> нужно писать <\\>, а для отображения кавычки - <\"> (для автоматической маскировки специальных символов вы можете воспользоваться соответствующим функционалом системы);
- переменные сцеплять со строкой необязательно: <:some text $f_some_var some another text> или <text ${f_some_var} some text>;
- можно использовать все специальные символы - <\n> (перенос строки), <\t> (табуляция) и пр.; также доступны функции PHP и специальные функции NetCat (полный перечень см. в Приложении 2).
Итак, заменяем динамические элементы необходимыми переменными и функциями. Более детальное описание указанных ниже функций и переменных Вы можете найти в Приложении 2 этого Руководства.
- Содержимое тега <title>
В нашем примере в заголовке окна браузера выводится путь до текущей страницы. Полный путь (с тегами) выводится при помощи функции s_browse_path($array), где $array - массив, содержащий шаблон вывода пути до текущей страницы); для вывода его без тегов следует вызвать функции очищения текста от тегов:
<title>".strip_tags(s_browse_path($browse_top))."</title>
Для форматирования вывода элемента навигации в данном случае использован массив $browse_top, который определяется в настройках макета:
$browse_top[active_link] = "%NAME";
$browse_top[unactive] = "%NAME";
$browse_top[active] = "%NAME";
$browse_top[divider] = " / ";
- Содержимое таблицы CSS
Для того чтобы таблица CSS была единой для всех макетов, были произведены следующие действия:
- В системную таблицу <Макеты дизайна> (меню <Инструменты - Системные таблицы>) было добавлено текстовое поле <Таблица стилей> (английское название поля - <CSS>);
- В корневом (стандартном) макете это поле было заполнено;
- В хедере между тегами <style type=text/css> и </style> была добавлена макропеременная %CSS.
- Вспомогательное меню <Поиск>, <Карта сайта>, <English version>
Теоретически данный блок можно прописать в макете <жестко>, т.е. HTML-текстом. Но вполне возможно, что через некоторое время нужно будет убрать или добавить какой-либо пункт, изменить название. Чтобы для внесения этих изменений не нужно было менять код всех макетов, где присутствует блок вспомогательной навигации, было сделано следующее:
- В структуру сайта был добавлен выключенный раздел <Вспомогательное меню> (его номер, например, 113);
- Все три пункта вспомогательного меню были добавлены в этот раздел в качестве подразделов;
- В настройки макета добавлен массив $browse_sub_help, который описывает формат вывода данного элемента навигации. Разберем его подробно:
$browse_sub_help[prefix] = "";
$browse_sub_help[suffix] = "";
// Префикс и суффикс отсутствуют
$browse_sub_help[unactive] = "<a href=%URL class=menu>%NAME</a>";
$browse_sub_help[active] = "<a href=%URL class=menu>%NAME</a>";
$browse_sub_help[active_link] = "<a href=%URL class=menu>%NAME</a>";
// Формат вывода самый простой
$browse_sub_help[divider] = " | ";
// В качестве разделителя между элементами меню используется прямая черта, окруженная пробелами.
- В макет вставлена функция отображения списка подразделов 113-го раздела:
".s_browse_sub(113,$browse_sub_help)."
- Коллаж для текущего раздела
Согласно дизайнерскому решению, на каждой странице сайта отображается коллаж. Причем, нужно понимать, что, если по какой-то причине для некоего раздела коллаж не был создан, это не должно привести к <битым> картинкам. Для реализации этого решения приведем желательную последовательность действий:
- В системную таблицу <Разделы> добавляем поле <Collage> (Коллаж) типа <Файл>. В свойствах поля указываем, что оно наследуемое (т.е. для всех подразделов внутри <Каталога товаров> это поле будет наследоваться из раздела <Каталога товаров>, если на каком-нибудь уровне оно не будет переопределено);
- Для каждого раздела первого уровня создаем коллаж;
- В форме редактирования настроек всех разделов закачиваем нужный коллаж;
- В нужном месте макета дизайна указываем его следующим образом: <img src='".$current_sub[Collage]."'>
- Меню первого уровня
В нашем примере формат меню первого уровня практически идентичен формату вспомогательного меню. В тексте макета вместо списка ссылок на разделы надо вызвать функцию: ".s_browse_level(0, $browse_sub[0])."
А в настройках макета определить формат отображения пунктов этого меню:
$browse_sub[0] = "";
$browse_sub[0] = "";
// Префикс и суффикс отсутствуют
$browse_sub[0] = "<a href=%URL class=menu>%NAME</a>";
$browse_sub[0] = "<b><a href=%URL class=menu>%NAME</a></b>";
// Активный раздел выделим жирным
$browse_sub[0] = "<b>%NAME</b>";
// Если посетитель находится на странице, куда ведет ссылка из меню, то сама эта ссылка, очевидно, не нужна
$browse_sub[0] = " ";
- Меню второго уровня
Меню первого уровня функицонально сложнее первого уровня. В данном случае необходимо вывести активный пункт меню <раскрытым>, т.е. под активным пунктом меню выводится список всех его подменю (меню третьего уровня). Для реализации этой задачи использовался стандартный механизм настроек элемента навигации:
- В настройки макета добавляем массив $browse_sub[1]:
$browse_sub[1][prefix] = "\"; global \$browse_sub; \$result.=\"<table width=100% cellpadding=2>";
// Настройки раздела обрабатываются функцией eval() языка PHP. При выполнении этой функции в данном случае массив $browse_sub не будет <виден> внутри цикла, а этот массив нам понадобится для вывода меню второго уровня. Поэтому в префиксе текст <прерывается> при помощи такого выражения:
<"\";...\$result.=\">, а вместо троеточия вставляется объявление глобальной переменной - массива $browse_sub.
Такая конструкция нужна только для данного примера - если бы был использован стандартный принцип вывода навигации (когда на любой внутренней странице видно только меню первого уровня и меню второго уровня, относящееся к этому разделу), <разрывать> текст не было бы необходимости. После разрыва идет начало таблицы, в которой будет выведено меню.
$browse_sub[1][suffix] = "</table>";
// Суффикс меню второго уровня - таблица закрывается.
$browse_sub[1][active] = "<tr><td ><b><a href=%URL>%NAME</a></b></td></tr>".s_browse_level(2,$browse_sub[2]);
// Формат вывода активного элемента меню первого уровня.
После названия со ссылкой выводится меню третьего уровня - функция s_browse_level(2,$browse_sub[2]), последний параметр которой нужно будет описать - он отвечает за форматирование вывода меню третьего уровня (см. ниже).
$browse_sub[1][active_link] = "<tr><td><b>%NAME</b></td></
tr>".s_browse_level(2,$browse_sub[2]);
// После активного элемента меню необходимо вывести все
его подразделы в том шаблоне, который был объявлен
глобальным в prefix.
$browse_sub[1][unactive] = "<tr><td ><a href=%URL>
%NAME</a></td></tr>";;
$browse_sub[1][divider] = "";
// Разделитель не используется.
2. В настройках раздела определяем внешний вид меню второго уровня:
$browse_sub[2][prefix] = "";
$browse_sub[2][suffix] = "";
$browse_sub[2][active] = "<tr><td><font size=-1> <a
href=%URL>%NAME</a></font></td></tr>";
$browse_sub[2][active_link] = "<tr><td><font
size=-1> %NAME</font></td></tr>";
$browse_sub[2][unactive] = $browse_sub[2][active];
$browse_sub[2][divider] = "";
3. В нужное место в макете вставляем вызов функции, отвечающей за
вывод меню второго уровня:
".s_browse_level(1,$browse_sub[1])."
7. Заголовок страницы
Стандартный способ вывести заголовок страницы (название текущего
раздела) - написать переменную $f_title. Но данный случай, в силу своей
специфики, не подходит под стандартный способ, потому что, как видно
из меню третьего уровня, раздел называется <Прямые>, а необходимо
выдать полное название раздела. Для этого нам неоходимо:
1. Создать в системной таблице <Разделы> поле <Полное
название> (название по-английски, например, FullName)
2. Заполнить его в нужных разделах
3. В макете вывести его значение:
".$current_sub[FullName]."
Однако, если это поле в каком-то разделе заполнено не будет, заголовок
не выведется. Поэтому целесообразно проверять его наличие и в случае
его отсутствия выводить стандартное название раздела:
".opt_case($current_sub[FullName], $current_sub[FullName],
$f_title)."
Система управления сайтами NetCat 3.0. Руководство разработчика 45
8. Выборка двух последних новостей
Это, пожалуй, одна из самых простых операций. Например, номера
раздела <Новости> - 12, а номер компонента раздела - 30. Тогда вывести
последние два объекта новостей можно будет вызовом функции:
".s_list_class(12,30,"recNum=2")."
Забегая немного вперед, стоит указать, что формат вывода новостей во
вставке оформления страницы может отличаться от списка новостей в
соответствующем разделе. В этом случае альтернативный формат
должен быть описан в шаблоне вывода компонента <Новости>. Поэтому
следует подать дополнительный параметр на функцию s_list_class(),
который будет обработан в тексте шаблона компонента:
".s_list_class(12,30,"recNum=2&tmpl=short")."
9. Количество новинок в каталоге
Среди стандартных функций NetCat нет функции, которая бы выводила
количество товаров в каком-либо разделе с какими-либо условиями
выборки, поэтому данную выборку придется формировать прямым
запросом к базе. Предположим, под новыми товарами мы подразумеваем
товары, добавленные сегодня. Компонент <Товары> имеет номер 57, т.е.
его экземпляры хранятся в таблице Message57. SQL-запрос к базе в этом
случае будет выглядеть так:
SELECT a.Subdivision_Name AS name, b.Sub_Class_ID AS id,
count(c.Message_ID) AS cnt FROM Subdivision AS a, Sub_Class
AS b, Message57 AS c where a.Subdivision_ID=b.Subdivision_ID
AND b.Sub_Class_ID=c.Sub_Class_ID AND
DATE(c.Created)=CURDATE() GROUP BY name ORDER BY name
Отформатируем результаты запроса при помощи соответствующей
функции NetCat:
".listQuery("select a.Subdivision_Name as name,
b.Sub_Class_ID as id, count(c.Message_ID) as cnt from
Subdivision as a, Sub_Class as b, Message57 as c where
a.Subdivision_ID=b.Subdivision_ID and
b.Sub_Class_ID=c.Sub_Class_ID and DATE(c.Created)=CURDATE()
group by name order by name", "<li>\$data[name]: <b>\
$data[cnt]</b>")."
10.Содержательная часть страницы
Для определения места вывода содержательной части страницы не
используются никакие вставки. Это место в макете является разрывом
между хедером и футером. Т.е. текст до этого места записывается в
хедер, а после - в футер.
11.Текущий год
Система управления сайтами NetCat 3.0. Руководство разработчика 46
Текущий год вставляется простейшей функцией PHP:
© 2000-".date('Y')."
Таким образом, мы получили следующие значения полей для макета.
Шаблоны вывода навигации (настройки макета):
$browse_top[active_link] = "%NAME";
$browse_top[unactive] = "%NAME";
$browse_top[active] = "%NAME";
$browse_top[divider] = " / ";
$browse_sub_help[prefix] = "";
$browse_sub_help[suffix] = "";
$browse_sub_help[unactive] = "<a href=%URL class=menu>%NAME</
a>";
$browse_sub_help[active] = "<a href=%URL class=menu>
%NAME</a>";
$browse_sub_help[active_link] = "<a href=%URL class=menu>
%NAME</a>";
$browse_sub_help[divider] = " | ";
$browse_sub_help[0] = "";
$browse_sub_help[0] = "";
$browse_sub_help[0] = "<a href=%URL class=menu>%NAME</a>";
$browse_sub_help[0] = "<b><a href=%URL class=menu>%NAME</a></
b>";
$browse_sub_help[0] = "<b>%NAME</b>";
$browse_sub_help[0] = " ";
$browse_sub[2][prefix] = "";
$browse_sub[2][suffix] = "";
$browse_sub[2][active] = "<tr><td><font size=-1> <a
href=%URL>%NAME</a></font></td></tr>";
$browse_sub[2][active_link] = "<tr><td><font size=-1>
%NAME</font></td></tr>";
$browse_sub[2][unactive] = $browse_sub[2][active];
$browse_sub[2][divider] = "";
$browse_sub[1][prefix] = "\";global \$browse_sub;\
$result.=\"<table width=100% cellpadding=2>";
$browse_sub[1][suffix] = "</table>";
$browse_sub[1][active] = "<tr><td ><b><a href=%URL>
%NAME</a></b></td></tr>".s_browse_level(2,$browse_sub[2]);
$browse_sub[1][active_link] = "<tr><td><b>
%NAME</b></td></tr>".s_browse_level(2,$browse_sub[2]);
$browse_sub[1][unactive] = "<tr><td ><a href=%URL>%NAME</a></
td></tr>";
$browse_sub[1][divider] = "";
Хедер:
Система управления сайтами NetCat 3.0. Руководство разработчика 47
<html>
<head>
<title>".strip_tags(s_browse_path($browse_top))."</title>
<style type=text/css>
%CSS
</style>
</head>
<body>
<table width='100%' cellpadding='3'>
<tr>
<td><img src='/images/logo.gif'></td>
<td align='right' valign='bottom'><img src='".
$current_sub[Collage]."'></td>
</tr>
<tr>
<td colspan='2' bgcolor='#EEEEEE'>".s_browse_level(0,
$browse_sub[0])."</td>
</table>
<table width='100%'>
<tr>
<td valign='top' width='200' bgcolor='#EEEEEE'>
<p>
".s_browse_level(1, $browse_sub[1])."
<p>
<font size=-2>
<b>Последние новости</b>
<p>
".s_list_class(12,30,"recNum=2&tmpl=short")."
<b>Новинки в каталоге</b>
".listQuery("select a.Subdivision_Name as name,
b.Sub_Class_ID as id, count(c.Message_ID) as cnt from
Subdivision as a, Sub_Class as b, Message57 as c where
a.Subdivision_ID=b.Subdivision_ID and
b.Sub_Class_ID=c.Sub_Class_ID and DATE(c.Created)=CURDATE()
group by name order by name", "<li>\$data[name]: <b>\
$data[cnt]</b>")."
<p>
</font>
</td>
<td valign='top'>
<div align=right>".s_browse_sub(113,$browse_sub_help)."</div>
".opt_case($current_sub[FullName], $current_sub[FullName],
$f_title)."<p>
Футер:
</td>
</tr>
</table>
<p align='center'>© 2000-".date('Y')." \"Рога и копыта\". Все права защищены.
</body>
</html>
Таблица стилей:
body {background-color:white; margin:0; font-family:verdana;}
Обратите внимание, что:
- В настройках макета массив $browse_sub[2] определен выше, чем $s_browse_sub[1]. Это необходимо, чтобы $browse_sub[2] был <виден> в $browse_sub[1].
- Атрибуты HTML-тегов сознательно указаны то в одинарных кавычках, то вообще без кавычек - двойные кавычки не использованы. Это связано с тем, что двойная кавычка является признаком конца/начала строки в языке PHP. Все двойные кавычки необходимо маскировать обратным слэшем, как это сделано в футере: \"Рога и копыта\"
Другие функции и переменные, доступные для использования в макетах, см. в Приложении 2.
После добавления макета выберите его в настройках сайта (или нужных разделов). Номер макета также можно напрямую подавать на страницу как параметр. Это целесообразно, когда макет нужно тестировать на рабочем сайте. Например, если есть задача протестировать внешний вид страницы <www.example.ru/about/> с новым макетом (например, номер 3), сделав процесс тестирования незаметным для посетителей сайта, нужно вызывать страницу таким образом: <www.example.ru/about/?template=3>.
Аналогично решается задача создания версии для печати:
- Создается (и тестируется) новый облегченный макет, предназначенный для распечатки;
- В тексте макета (если ссылка <версия для печати> нужна на всех страницах, использующих макет) или компонента (если ссылка нужна только на страницах некоторых компонентов) ввести примерно следующий текст:
<a href='?template=3'>версия для печати</a>
Рейтинг: 0
Для оценки необходимо авторизоваться.
Комментарии: 0
Для добавления комментария необходимо авторизоваться.
| |