Урок 2. Меню навигации и структура страниц

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

Открываем файл auto.p и меняем его содержимое на:

@navigation[]
$sections[^
table::load[/sections.cfg]]
<nav>
   ^sections.
menu{
      ^navigation_item[]
   }
[|]
<nav>

@navigation_item[]
^if($sections.
uri eq $request:uri){
   <b>$sections.name</b>
}{
   <a href="$sections.uri">$sections.name</a>
}


Что изменилось? На первый взгляд, не так уж и много, но функциональность нашего модуля существенно возросла. Мы описали еще один метод -
navigation_item, который вызывается из метода navigation. В нем появилась новая структура:

^if(условие){код, если условие «истина»}{код, если условие «ложь»}

Что она делает, понять несложно. В круглых скобках задается условие, и в зависимости от того, какое значение возвращает условие, «ложь» или «истина», можно получить разный результат. Также, если в условии записано выражение, значение которого равно нулю, то результат - «ложь», иначе - «истина». Мы используем оператор
if для того, чтобы в одном случае поставить ссылку на раздел, а другом - нет. Осталось только разобраться с условием. Будем проверять на равенство две текстовые строки, в одной из которых - значение URI-раздела из таблицы sections, в другой - текущий URI ($request:uri возвращает строку, содержащую URI текущей страницы). Тут возникает вопрос, какие же строки равны между собой. Несомненно, только те, которые полностью совпадают и по длине, и по символьному содержанию.

Для сравнения двух строк в Parser предусмотрены следующие операторы:

eq - строки равны (equal): parser eq parser
ne
 - строки не равны (not equal): parser ne parser3
lt
 - первая строка меньше второй (less than): parser lt parser3
gt - первая строка больше второй (greater than): parser3 gt parser 
le
 - первая строка меньше или равна второй (less or equal)
ge - первая строка больше или равна второй (greater or equal)

С условием разобрались: если
$sections.uri и $request:uri совпадают, ссылку не ставим, если нет - ставим.
Вот, собственно, и все, что касается меню. Теперь оно функционально и готово к использованию.

Наш первый кирпичик для будущего сайта готов. Теперь займемся структурой страниц. Разобьем их на следующие блоки:
header - верхняя часть страницы, navigation - наше меню, content - основной информационный блок и footer - нижняя часть страницы. Страницы многих сайтов имеют похожую структуру.

Footer будет для всех страниц одинаковым, header - для всех страниц одинаковым по стилю, но с разными текстовыми строками - заголовками страницы, а content будет разным у всех страниц и сохранит только общую структуру (вертикальный информационный блок).

Каждая из страниц будет иметь следующую структуру:

header

navigation

content

footer


Так же как и в случае с меню, опишем каждый из этих блоков методом (функцией) на Parser. Разберемся подробнее с каждым блоком.

С
footer все очень просто - в auto.p добавляем код:

@footer[]
<footer>
   $now[^
date::now[]]
   Powered by Parser3 1997-$now.year
</footer>

Никаких новых идей здесь нет, разве что мы впервые использовали класс
date с конструктором now для получения текущей даты, а затем из объекта класса date взяли поле year (год). Если это кажется непонятным, нужно вернуться к первому уроку, где рассказано о работе с объектами на примере класса table. Все идентично, только теперь мы имеем дело с объектом другого класса.

Немного сложнее с модулем
header. С одной стороны, нам нужно формировать уникальный заголовок-приветствие для каждой страницы. В то же время он будет одинаковым с точки зрения внешнего вида, различие только в тексте, который будет выводиться. Как же быть? Мы предлагаем сделать следующее: определить в нашем auto.p новую функцию header, внутри которой будет вызываться другая функция - greeting. А функция greeting, в свою очередь, будет определяться на самих страницах сайта и содержать только отличающиеся части заголовков страниц (в нашем случае - строку-приветствие).

Дополняем
auto.p следующим кодом:

@header[]
<title>Parser3^greeting[]</title>
<style>
   html {
      height: 100%;
   }
   body {
      display: flex;
      flex-direction: column;
      height: 100%;
      margin: 0;
   }
   nav, #content, footer {
      padding: 10px;
   }
   #content {
      flex: 1 100%;
   }
</style>

Теперь внимание, кульминация. Parser позволяет сделать очень интересный финт: определить один раз общую структуру страниц в файле
auto.p, создать каркас, а затем, используя функции, подобные greeting, в тексте самих страниц, получать разные по содержанию страницы с одинаковой структурой. Как это работает?

В самом начале файла
auto.p определим функцию @main[]. Функция с таким названием всегда исполняется первой. Включим в нее вызовы функций, формирующих части страниц.

В начале
auto.p пишем:

@main[]
<html>
   <head>
      ^header[]
   </head>
   <body>
   ^navigation[]
   <div id="content">
      ^content[]
   </div>      
   ^footer[]
   </body>
</html>

А для получения уникальных заголовков страниц в каждой из них определим функцию
greeting, которая вызывается из header.

Для главной страницы:

@greeting[]
Добро пожаловать!

Для гостевой книги:
@greeting[]
Оставьте свой след…

и т. д.

Теперь при загрузке, например, главной страницы произойдет следующее:
1)из файла auto.p автоматически начнет выполняться main;  
2)первой вызовется функция header, из которой вызовется функция greeting;  
3)поскольку функция greeting определена в коде самой страницы, будет выполнена именно она, вне зависимости от того, определяется она в auto.p или нет (происходит переопределение функции);  
4)затем будут выполнены функции navigation, content и footer из main.  

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

Определение функции
content, так же как и в случае с greeting, вставим в страницы:

@content[]
Главная страница сайта

Этот текст приводится как образец для 
index.html. Отлично! Структура окончательно сформирована. Мы описали все необходимые модули в файле auto.p, сформировали общую структуру и теперь можем запросто генерировать страницы. Больше не нужно многократно писать одни и те же фрагменты HTML-кода. Привычные HTML-страницы трансформируются приблизительно в следующее (примерное содержание index.html файла для главной страницы):

@greeting[]
Добро пожаловать!

@content[]
Главная страница сайта

Просто и понятно, содержание разложено по методам и легкодоступно для изменения. После обработки подобного кода Parser создаст HTML-код страницы, у которой будет уникальный заголовок, меню, основной информационный блок заданной структуры и 
footer, одинаковый для каждой страницы. Фактически мы уже создали готовый сайт, который осталось только наполнить информацией. Это готовое решение для изящного сайта-визитки, который можно создать прямо на глазах. Естественно, это не единственное решение, но такой подход дает отличную структуризацию нашего сайта. Некоторые усилия при разработке структуры с лихвой окупятся легкостью последующей поддержки и модернизации. Каркас хранится в auto.p, а все, что относится непосредственно к странице, - в ней самой.

Дальше открываются безграничные просторы для фантазии. Допустим, нам понадобилось поменять внешний вид заголовка страниц на сайте. Мы открываем
auto.p, редактируем один-единственный раз функцию @header[] и на каждой из страниц получаем новый заголовок, по стилю идентичный всем остальным. Для обычного HTML нам пришлось бы вручную переписывать код для каждой страницы. Та же самая ситуация и с остальными модулями. Если возникло желание или необходимость изменить общую структуру страниц, например добавить какой-то блок, достаточно определить его новой функцией и дополнить функцию main в auto.p ее вызовом.

Подобная организация страниц сайта дополняет проект еще одним мощным средством. Предположим, на одной из страниц нам понадобилось получить
footer, отличный от других страниц (напомним, изначально мы предполагали, что footer везде одинаковый). Единственное, что нужно сделать, - это переопределить функцию footer на нужной странице. Например, такое наполнение /contacts/index.html:

@greeting[]
Наша контактная информация

@content[]
Страница контактов тестового сайта

@footer[]
<footer>
   Обращайтесь к нам!
<footer>

изменит привычный
footer на обозначенный выше, т. е., если Parser найдет в тексте страницы код для функции, вызываемой из auto.p, он выполнит именно его, даже если функция определена в самом auto.p. Если же функция не переопределена на странице, то будет использован код из auto.p.

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

Ранее мы использовали в нашем коде конструкцию
$request:uri. Она отличается по синтаксису от всего того, с чем мы имели дело до этого. Что же это такое? Внешне похоже на $объект.свойство (урок 1) - значение полей объекта, только вместо точки использовано двоеточие. На самом деле это тоже значение поля, только не объекта, а самого класса request. В Parser не предусматриваются конструкторы для создания объектов этого класса. Поля подобных классов формируются самим Parser, а мы можем сразу напрямую обращаться к ним. На техническом языке это называется статическая переменная (поле) uri класса request. Она хранит в себе URI текущей страницы. Также, наряду со статическими переменными, существуют статические методы, с которыми мы столкнемся уже на следующем уроке. При этом можно сразу же вызывать их также без создания каких-либо объектов с помощью конструкторов. Обращение к статическим полям и вызов статических методов оформляется с помощью двоеточия. Если встречается конструкция вида $класс:поле, мы получаем значение поля самого класса, а запись ^класс:метод является вызовом статического метода класса. Например, для работы с математическими функциями в Parser существует класс math. В нем используются только статические методы и переменные.

$math:PI -  возвращает число p. Это статическая переменная класса math.

^math:random(100) - возвращает псевдослучайное число из диапазона от 0 до 99; это статический метод класса math.

Отличие от записи методов и полей объектов состоит только в двоеточии.

Подведем итоги второго урока.

Что мы сделали: исправили недостатки в меню навигации, созданном на предыдущем уроке, а также описали новые блоки header, footer и content, формирующие внешний вид страниц нашего сайта. Теперь мы имеем готовое решение для быстрого создания сайта начального уровня.

Что узнали: познакомились с ветвлением кода, научились сравнивать строки и получать URI текущей страницы. Также мы узнали новые методы объектов класса table и класса date и познакомились с мощным механизмом виртуальных функций Parser.

Что надо запомнить: первым методом в файле auto.p допустимо определить функцию main, которая выполняется автоматически. Любая из функций способна вызывать другие функции. Все вызываемые из main функции обязательно должны быть определены или в auto.p или в тексте страниц. В случае если функция будет определена и там и там, больший приоритет имеет функция, определенная в тексте страницы. Она переопределяет одноименную функцию из main (т. н. виртуальная функция) и выполняется вместо нее.

Что будем делать дальше: нет предела совершенству! От создания сайта начального уровня мы переходим к более сложным вещам, таким как работа с формами и базами данных для создания по-настоящему интерактивного сайта. Параллельно с этим познакомимся с новыми возможностями, предоставляемыми Parser для облегчения жизни создателям сайтов.


Copyright © 1997–2024 Art. Lebedev Studio | http://www.artlebedev.ru Дата обновления: 16.10.2024