Построение меню в Nano-CMS.

Место жительства модуля меню.

Модуль оформляется в виде файла с именем _menu.php
Располагается в папке с контентными файлами ./data/content/
Либо во вложенной в неё папке, если ей нужно собственное меню.

Внутри файл модуля меню может быть оформлен разнообразно:

1) Обычный HTML код в виде переменной.

Подход совершенно тот же самый, что и в случае с модулем шаблона дизайна. Возможен простой PHP код со ссылками на документы сайта в HTML контейнере:

<?php /* Выше этой строки в файле ничего не должно быть */

   
$_s['menu']='
<ul class="nav">
   <li class="nolink">Заголовок элемента меню:</li>
   <li><a href="'
.$_s['loc']['base'].'a'.$_s['ext'].'" >Документ a</a></li>
   <li><a href="'
.$_s['loc']['base'].'b'.$_s['ext'].'" >Документ b</a></li>
</ul>'
;

/* Ниже этой строки в файле ничего не должно быть. */ ?>

Вроде бы просто, но есть сразу две проблемы.

  1. Для каждого элемента меню придётся писать окаймляющий HTML код.
    В данном случае он краток и прост, но так бывает далеко не всегда.

  2. Система наследования меню создаст проблемы в случае, если фолдер с собственным дизайном не имеет собственного меню, а получает его от корневой папки c документами. Если шаблоны дизайнов этих папок существенно отличаются, и меню оформляется другими тегами, дизайн поедет.

Из соображений простоты и удобства автор не рекомендует завязываться на HTML код с привязкой его к конкретному дизайну. Есть хороший альтернативный вариант.

2) Абстрагирование от дизайна в коде модуля меню.

Для этого существует специальная функция:

<?php /* Выше этой строки в файле ничего не должно быть */

   
get_menu_html_code(
      
$_s['des'],
      array(
         
'Заголовок элемента меню' => array(
            
$_s['loc']['base'].'a'.$_s['ext'] => 'Документ a',
            
$_s['loc']['base'].'b'.$_s['ext'] => 'Документ b',
         ),
      )
   );

/* Ниже этой строки в файле ничего не должно быть. */ ?>

Данная функция самостоятельно узнает имя дизайна из переменной $_s['des'] (первый аргумент, переменная имени дизайна задаётся в файле настроек), извлекает контейнер для оформления меню из специального файла шаблонов, оборачивает им менюшку, а результат отдаёт переменной $_s['menu'], где этот результат и должен оказаться.

Стоит добавить, что вместо переменной с именем дизайна $_s['des'] никто не запрещает напрямую указывать собственно имя дизайна, например, 'default-left-content', если в папке с данным меню используется какой-то иной дизайн, не такой, как на сайте.

Замечание об абсолютных URL-ах.

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

Рекомендуется именно так всегда и поступать - абсолютная ссылка исключает двойственность толкования URL-а (в написании с www. и без), а также предотвращает создание страниц-фантомов в несуществующих URL-ах при неправильной адресации. Это когда ссылки с меню не абсолютные, а относительные, и бот поисковой системы по ошибочной ссылке попадает в несуществующую директорию. В которой меню создаст линки на несуществующие документы, и, может быть, на другие несуществующие директории с несуществующими в них документами.

Как далеко уйдёт индексирующий бот по такой неисправной навигации, не известно. Но пенальти от поисковой системы Вы совершенно точно получите, даже не сомневайтесь.

Чтобы такого не было, всегда пользуйтесь только абсолютной адресацией. Идеально, если URL-ы при этом собираются из переменных движка. Ошибок не будет.

Меню фолдера.

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

Просто употребите вместо переменной корня сайта переменную этого фолдера (весь путь от корня там уже учтён), и получите более компактную запись с тем же функционалом. Пример:

<?php /* Выше этой строки в файле ничего не должно быть */

   
if (isset($_s['loc']['fold'])) get_menu_html_code(
      
$_s['des'],
      array(
         
'Заголовок элемента меню' => array(
            
$_s['loc']['base'].'f/o/l/d/e/r/s/index'.$_s['ext'] => 'Документ',
            
$_s['loc']['fold'].'index'.              $_s['ext'] => 'Документ',
         ),
      )
   );

/* Ниже этой строки в файле ничего не должно быть. */ ?>

Как бонус ко второму варианту записи - возможность переименования или перенесения всего фолдера со всеми его документами в любое место структуры сайта без переделки его меню. Потому как все абсолютные ссылки на документы в новом месте жительства фолдера откорректируются автоматически.

Расплата за удобство - необходимость проверки существования переменной $_s['loc']['fold'] При не разрешённых элементах в URL-е переменная может быть не определена.

Подсветка элементов меню.

Полезно, когда пользователь сайта, глядя на его меню, чётко представляет, на каком именно документе он сейчас находится (соответствующий элемент меню как-то выделен).

Чтобы так и происходило, в файле шаблонов для соответствующего дизайна ./data/design/_template_default.php есть пара строк:

   $_s['template']['menu']['link']=  '<li><a href="===url===" >===ancor===</a></li>';
   
$_s['template']['menu']['select']='<li><a href="===url===" class="selected" >===ancor===</a></li>';

Элемент массива с ключом link определяет шаблон неактивной ссылки меню (пользователь НЕ находится на документе, который эта ссылка открывает). Вместо макросов движок Nano-CMS подставит реальные значения. Полный URL документа и текст ссылки (иначе его ещё называют анкором).

Элемент массива с ключом select задаёт шаблон "подсвеченной" ссылки, то есть той, на документе которой находится пользователь. Фактически это предыдущий шаблон, но оборудованный каким-то специальным классом, заданным в CSS файле движка, и призванным визуально модифицировать ссылку меню. Изменить цвет её текста, покрасить кнопку в другой цвет, как-то по особому отбросить тень, и т.п.

Обратите внимание, что действие по выделению ссылок применяется только к модулю меню. Если Вы пропишите какой-то кусок меню прямо в шаблон дизайна, что ни разу не запрещено, то там подсветки ссылок уже не будет.

Маленькие хитрости (подсветка раздела сайта).

Корневой элемент папки сайта обычно имеет имя index плюс какое-то расширение. И к нему можно обратиться как напрямую (имя документа видно в URL-е), так и не явно (в URL-е только имя его папки, со слэшем на конце). Сразу пример такой двойственной адресации:

<?php /* Выше этой строки в файле ничего не должно быть */

   
get_menu_html_code(
      
$_s['des'],
      array(
         
'Заголовок элемента меню' => array(
            
$_s['loc']['base'].'f/o/l/d/e/r/index'.$_s['ext'] => 'Документ',
            
$_s['loc']['base'].'f/o/l/d/e/r/'                 => 'Документ',
         ),
      )
   );

/* Ниже этой строки в файле ничего не должно быть. */ ?>

Оба этих варианта написания функционально равнозначны, то есть верно адресуют пользователя к документу. Но подсветка навигации ведёт себя различным образом.

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

Если Вы присмотритесь к навигации данного сайта, то поймёте, как именно это может быть использовано. При наличии отдельного меню по фолдеру, а также глобального меню по сайту с упоминанием в нём этого фолдера, можно добиться от глобального меню обозначения раздела, в пределах которого пользователь находится. Достаточно в меню фолдера употребить первый вариант записи, а в глобальном меню - второе написание.

Интерактивность модуля меню навигации.

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

<?php /* Выше этой строки в файле ничего не должно быть */

   
get_menu_html_code(
      
$_s['des'],
      (
is_admin() ?
         array(
            
'Админу:' => array(
               
$_s['loc']['base'].'a'.$_s['ext'] => 'Документ для админа',
            ),
         ):
         array(
            
'Посетителю:' => array(
               
$_s['loc']['base'].'b'.$_s['ext'] => 'Документ для пользователя',
            ),
         )
      )
   );

/* Ниже этой строки в файле ничего не должно быть. */ ?>

Могут быть и какие-то другие варианты реакции меню на внешний фактор (не на факт авторизованности юзера, а на что-то другое) - как это достигается на уровне кода, должно быть понятно.

Конструирование меню из нескольких.

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

<?php /* Выше этой строки в файле ничего не должно быть */

   
if (isset($_s['loc']['fold'])) get_menu_html_code(
      
$_s['des'],
      array(
         
'Заголовок документов фолдера' => array(
            
$_s['loc']['fold'].'index'.$_s['ext'] => 'Корень фолдера',
            
$_s['loc']['fold'].'file' .$_s['ext'] => 'Файл фолдера',
         ),
         
'Заголовок корневой папки' => array(
            
$_s['loc']['base'].'index'.$_s['ext'] => 'Главная страница сайта',
            
$_s['loc']['base'].'file' .$_s['ext'] => 'Файл в корне сайта',
         ),
      )
   );

/* Ниже этой строки в файле ничего не должно быть. */ ?>

можно заменить вариантом без попугайства, с подгрузкой уже готового меню прямо из корня:

<?php /* Выше этой строки в файле ничего не должно быть */

   
if (isset($_s['loc']['fold'])) get_menu_html_code(
      
$_s['des'],
      array(
         
'Заголовок документов фолдера' => array(
            
$_s['loc']['fold'].'index'.$_s['ext'] => 'Корень фолдера',
            
$_s['loc']['fold'].'file' .$_s['ext'] => 'Файл фолдера',
         ),
      )
   );
   include(
$_s['loc']['cont'].'/_menu.php');

/* Ниже этой строки в файле ничего не должно быть. */ ?>

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