На двух предыдущих уроках мы
Урок 3. Первый шаг - раздел новостей |
Создать календарь средствами одного HTML - задача достаточно нетривиальная, к тому же код получится очень громоздким. Сейчас Вы увидите, как легко это сделать на Parser. Приступаем.
Все файлы, относящиеся к разделу новостей, будем размещать в разделе /news/, что было указано нами в файле sections.cfg. Для начала создадим там (!) файл auto.p. Удивлены? Да, файлы auto.p можно создавать в любом каталоге сайта. Однако при этом надо иметь в виду, что функции, описанные в auto.p разделов, будут явно доступны только внутри этих разделов. Согласитесь, ни к чему загромождать корневой auto.p функциями, которые нужны для одного раздела. Логичнее вынести их в отдельный файл, относящийся именно к этому разделу.
Еще одно замечание: если в auto.p раздела переопределить функцию, ранее описанную в корневом auto.p, то будет исполняться именно эта, переопределенная функция. Сработает механизм виртуальных функций, описанный в предыдущем уроке.
Итак, в auto.p раздела news пишем такой код:
@calendar[]
$calendar_locale[
$.month_names[
$.1[Январь]
$.2[Февраль]
$.3[Март]
$.4[Апрель]
$.5[Май]
$.6[Июнь]
$.7[Июль]
$.8[Август]
$.9[Сентябрь]
$.10[Октябрь]
$.11[Ноябрь]
$.12[Декабрь]
]
$.day_names[
$.0[пн]
$.1[вт]
$.2[ср]
$.3[чт]
$.4[пт]
$.5[сб]
$.6[вс]
]
$.day_colors[
$.0[#000000]
$.1[#000000]
$.2[#000000]
$.3[#000000]
$.4[#000000]
$.5[#800000]
$.6[#800000]
]
]
$now[^date::now[]]
$days[^date:calendar[rus]($now.year;$now.month)]
<center>
<table bgcolor="#000000" cellspacing="1">
<tr>
<td bgcolor="#FFFFFF" colspan="7" align="middle">
<b>$calendar_locale.month_names.[$now.month]</b>
</td>
</tr>
<tr>
^for[week_day](0;6){
<td width="14%" align="middle" bgcolor="#A2D0F2">
<font color="$calendar_locale.day_colors.$week_day">
$calendar_locale.day_names.$week_day
</font>
</td>
}
</tr>
^days.menu{
<tr>
^for[week_day](0;6){
^if($days.$week_day){
^if($days.$week_day==$now.day){
<td align="middle" bgcolor="#FFFF00">
<font color="$calendar_locale.day_colors.$week_day">
<b>$days.$week_day</b>
</font>
</td>
}{
<td align="middle" bgcolor="#FFFFFF">
<font color="$calendar_locale.day_colors.$week_day">
$days.$week_day
</font>
</td>
}
}{
<td bgcolor="#DFDFDF"> </td>
}
}
</tr>
}
</table>
</center>
Мы определили функцию calendar, которая создает HTML- код календаря. Получился довольно громоздкий код, но ведь и задачи, которые мы ставим перед собой, тоже усложнились. Не волнуйтесь, сейчас во всем разберемся.
Самая объемная часть кода, начинающаяся с определения $calendar_locale, оказалась незнакомой. Посмотрите на эту структуру. Похоже, в ней мы определяем какие-то данные для календаря, напоминающие таблицу. То, что определено как $calendar_locale, в терминологии Parser называется «хеш», или ассоциативный массив. Зачем он нужен можно сказать, просто бегло просмотрев код примера: здесь мы сопоставляем русское написание месяца его номеру в году (3 - март), название дня недели его номеру, а также связываем шестнадцатиричное значение цвета с некоторым числом. Теперь идея хешей должна проясниться: они нужны для сопоставления (ассоциативной связи) имени с объектом. В нашем случае мы ассоциируем порядковые номера месяцев и дней с их названиями (строками). Parser использует объектную модель, поэтому строка тоже является объектом. Нам несложно получить порядковый номер текущего месяца, но намного нагляднее будет вывести в календаре «Ноябрь» вместо «11» или «пн» вместо «1». Для этого мы и создаем ассоциативный массив.
В общем виде порядок объявления переменных-хешей такой:
$имя[
$.ключ[значение]
]
Эта конструкция позволяет обратиться к переменной по имени с ключом $имя.ключ и получить сопоставленное значение. Обратите внимание, что в нашем случае мы имеем хеш, полями которого являются три других хеша.
После определения хеша мы видим уже знакомую переменную now (текущая дата), а вот дальше идет незнакомая конструкция:
$days[^date:calendar[rus]($date.year;$date.month)]
По логике работы она напоминает конструктор, поскольку в переменную days помещается таблица с календарем на текущий месяц текущего года. Тем не менее, привычного :: здесь не наблюдается. Это один из статических методов класса date. Статические методы наряду с уже знакомыми конструкторами могут возвращать объекты, поэтому в данном случае необходимо присвоить созданный объект переменной. Про статические переменные и методы уже было немного сказано в конце предыдущего урока. Своим появлением они обязаны тому факту, что некоторые объекты или их свойства (поля) существуют в единственном экземпляре, как, например, календарь на заданный месяц или URI страницы. Поэтому подобные объекты и поля выделены в отдельную группу, и к ним можно обращаться напрямую, без использования конструкторов. В случае если мы обращаемся к статическому полю, мы получаем значение поля самого класса. В качестве примера можно привести класс math, предназначенный для работы с математическими функциями. Поскольку существует только одно число p, то для того, чтобы получить его значение, используется статическое поле $math:PI - это значение поля самого класса math.
В результате исполнения этого кода в переменной days будет содержаться такая таблица:
Таб.1 (для ноября 2001 года)
0 | 1 | 2 | 3 | 4 | 5 | 6 |
01 | 02 | 03 | 04 | |||
05 | 06 | 07 | 08 | 09 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 |
С ней мы и будем дальше работать.
Нельзя сразу же выводить содержимое переменной $days, просто обратившись к ней по имени. Если мы обратимся к таблице просто как к переменной, будет непонятно, что мы хотим получить - строку, всю таблицу целиком или значение только из одного столбца. Также явно требуется доработка содержимого полученной таблицы. Но ведь не зря же мы создавали наш хеш с названиями дней недели и месяцев. Поэтому далее по коду средствами HTML создается таблица, в первой строке которой мы выводим название текущего месяца, пользуясь данными из хеша, связанными с номером месяца в году:
$calendar_locale.month_names.[$now.month]
Что здесь что? Мы выводим значение поля month_names хеша calendar_locale с порядковым номером текущего месяца, полученным как $now.month. Результатом выполнения этой конструкции будет название месяца на русском (или любом другом) языке, которое было определено в хеше.
В следующей строке календаря выведем названия дней недели, пользуясь данными хеша. Давайте чуть подробнее определимся с задачей. Нам надо последовательно перебрать номера дней недели (от 0 до 6) и поставить в соответствие номеру дня его название из поля day_names хеша calendar_locale. Для этой цели удобнее всего воспользоваться циклом: последовательностью действий, выполняющейся заданное количество раз. В данном случае мы используем цикл for. Его синтаксис такой:
^for[счетчик](диапазон значений, например 0;6){последовательность действий}
Одно из достоинств циклов - возможность использования значения счетчика внутри цикла, обращаясь к нему как к переменной. Этим мы и воспользуемся:
^for[week_day](0;6){
<td width="14%" align="middle" bgcolor="#A2D0F2">
<font color="$calendar_locale.day_colors.$week_day">
$calendar_locale.day_names.$week_day
</font>
</td>
}
Все просто и понятно, если знать, что такое цикл: последовательно меняя значение week_day от 0 до 6 (здесь week_day является счетчиком цикла), мы получаем семь значений:
$calendar_locale.day_colors.$week_day - для цвета шрифта
$calendar_locale.day_names.$week_day - для названия дня недели.
Идея получения данных та же, что и для получения названия месяца, только используются другие ключи хеша.
Возможно, возник вопрос: зачем в хеше ключ day_colors? Ответ прост - все должно быть красиво! Если есть возможность максимально приблизить наш календарь к реальному, то так и сделаем - перекрасим выходные дни в красный цвет.
Далее по тексту следует большой красивый блок. Чтобы в нем разобраться, определимся с задачами. Итак, нам нужно:
1. Последовательно перебрать строки таблицы days (Таб.1).
2. В каждой строке таблицы days последовательно перебрать и вывести значения столбцов (числа месяца).
3. Корректно вывести пустые столбцы (то есть проверить первую и последнюю недели месяца на полноту).
4. Как-то выделить текущее число, например другим цветом и жирным шрифтом.
Приступаем. Первый пункт решается с помощью знакомого метода menu класса table:
^days.menu{…}
Перебор столбцов логичнее всего сделать циклом for, с которым мы только что познакомились:
^for[week_day](0;6){…}
Для проверки столбцов на пустоту для вывода столбцов без чисел используем оператор if. Вообще, любые проверки условий всегда можно реализовать с помощью if:
^if($days.$week_day){
…
}{
<td bgcolor="#DFDFDF"> </td>
}
Обратите внимание, что в условии if мы ни с чем не сравниваем $days.$week_day. Так осуществляется проверка на неравенство нулю.
Parser это условие понимает так:
«Если существует $days.$week_day, то {…}, если нет, то вывести пустую ячейку таблицы серого цвета»
Основная часть работы выполнена. Осталось только выделить текущее число.
Решается это использованием еще одного if, где условием задается сравнение текущего значения таблицы days с текущим числом ($days.$week_day==$now.day):
^if($days.$week_day==$now.day){
<td align="middle" bgcolor="#FFFF00">
<font color="$calendar_locale.day_colors.$week_day">
<b>$days.$week_day</b>
</font>
</td>
}{
<td align="middle" bgcolor="#FFFFFF">
<font color="$calendar_locale.day_colors.$week_day">
$days.$week_day
</font>
</td>
}
Обратите внимание на то, что здесь мы проверяем на равенство два числа, поэтому используем оператор == вместо eq, используемый для проверки равенства строк.
Еще раз посмотрим на общую структуру формирования календаря:
#перебираем строки таблицы с календарем
^days.menu{
#перебираем столбцы таблицы с календарем
^for[week_day](0;6){
^if($days.week_day){
^if($month.$week_day==$date.day){
число на другом фоне жирным шрифтом
}{
число
}
}{
пустой серый столбец
}
}
}
Эту конструкцию простой не назовешь. Здесь используются вложенные друг в друга конструкции. Однако она позволяет понять возможность комбинирования различных средств Parser для решения конкретной задачи. Есть более элегантное решение - вынести проверку текущей даты и ее раскрашивание нужным цветом в отдельную функцию, которую и вызывать внутри цикла. Похожее решение мы использовали во втором уроке. Это позволит разгрузить блок и сделать его более читабельным. Но поскольку в данном примере мы хотели показать вам возможность комбинирования нескольких логических структур, то оставляем эту возможность вам в качестве задания.
Если хотите убедиться в работоспособности этого модуля, создайте в разделе /news/ файл test.html и в нем наберите одну единственную строчку ^calendar[]. Теперь откройте этот файл из браузера и полюбуйтесь результатом своих трудов.
Подведем итоги третьего урока.
Что мы сделали: описали функцию, формирующую календарь на текущий месяц.
Что узнали:
· | файл auto.p может содержаться не только в корневом каталоге сайта, но и в любом другом, при этом функции, в нем определенные, явно доступны только внутри этого каталога |
· | переменная-хеш - это массив, нужный для построения ассоциативной связи одних объектов с другими. В нашем случае объектами выступали строки |
· | статический метод calendar создает таблицу с календарем на текущий месяц |
· | цикл for позволяет последовательно выполнить определенные действия заданное количество раз |
· | наряду с методами объектов, создаваемых с помощью конструкторов класса, существуют статические методы. Вы можете непосредственно обращаться к этим методам без предварительного использования конструктора для создания объекта |
· | в циклах for можно обращаться к счетчику как к переменной по имени и получать его текущее значение |
В Parser комментариями считается любая строка, начинающаяся со знака #. До сих пор мы не пользовались этим, но в дальнейшем нам пригодится комментирование кода. Следующая строка - пример комментария:
# весь этот текст Parser проигнорирует - это комментарий !!!!
Обязательно комментируйте свой код! В идеале он должен быть самодокументирующимся, а человек, читающий его, должен сразу же понимать о чем идет речь, что из чего следует и т.д. Если этого не сделать, то спустя какое-то время вспомнить что делает та или иная функция станет очень сложно даже вам самим, не говоря уже про остальных. Помните об этом!
Что будем делать дальше: на следующем уроке мы научим созданный нами календарь ставить ссылки на числа месяца. А самое главное, мы перейдем к работе с формами и базами данных для создания полноценного новостного раздела.
Copyright © 1997?2004 Art. Lebedev Studio | http://www.artlebedev.ru | Дата обновления: 13.01.2004 |