Создание логичного меню в Drupal
Наверное, не изобрету велосипед, но задача подчас встает и нашла много нового и полезного в поисках решения, безусловно. Конечно опыт нельзя оставлять в себе, так как он имеет свойство улетучиваться. Поэтому приступим.
Возьмем обычный ничем не примечательный корпоративный сайт не на Drupal - sponda.fi. Меню на нем организовано очень логично и просто. Вверху строка основных разделов (первого уровня), слева при выборе раздела появляется меню подразделов, причем уровней несколько - это второй и третий уровни меню (иногда четвертый). Также мы видим что все пункты, через которые мы пришли на данную страницу (родительские пункты - и в первом уровне и в последующих) активны вместе с текущим активным пунктом меню. Как в Drupal организовать подобную структуру?
Все это подходит под версию Drupal 5.*
Метод №1
Есть хороший и очень удобный способ - сделать одно меню, создавая структуру через выбор родительских пунктов (все пункты меню можно оставить неразвернутыми), а потом в настройках меню выбрать основным (primary) и дополнительным (secondary) одно и то же это самое меню, а в page.tpl.php прописать расположение этих самых меню в виде 'links'
.
Все это по шагам можно описать так:
- Перейти: Админка → Конструкция → Меню
- Создать меню (можно создать необходимые пункты прямо в primary links - меню уже создано по умолчанию). Чтобы сделать его двухуровневым, выбирайте у пунктов родителя. Не нужно создавать 2 отдельных меню.
- Зайти на вкладку
Меню, содержащее основные ссылки: ваше меню (Primary links)
Меню, содержащее дополнительные ссылки: ваше меню (Primary links)
- выбрать: - Написать в нужном месте в page.tpl.php такой код:
Для primary_links<?php if (isset($primary_links)) { ?><?php print theme('links', $primary_links) ?><?php } ?>
Для secondary_links:
<?php if (isset($secondary_links)) { ?><?php print theme('links', $secondary_links) ?><?php } ?>
Но недостаток этого метода в том, что он применим только при двухуровневой иерархии, то есть существуют только разделы вверху и подразделы слева, а под-подразделов уже быть не может, так как их secondary menu не покажет.
Метод №2
Поэтому расположим слева в page.tpl.php левую колонку:
<?php if ($sidebar_left) { ?><?php print $sidebar_left ?><?php } ?>
Далее создадим блок в админке и поместим туда вот такой PHP код (источник):
<?php
$primary_menu_id = variable_get('menu_primary_menu', 0);
if (menu_in_active_trail($primary_menu_id)){
// get the menu items that lead to the current menu item
$active_trail =_menu_get_active_trail();
// get the menu id of the active top-level link
$mid = $active_trail[1];
$menu_item = menu_get_item($mid);
$menu_tree = menu_tree($mid);
print '<ul class="ВАШ КЛАСС ДЛЯ ЛЕВОГО МЕНЮ">'.$menu_tree.'</ul>';
}
?>
Тестируем, действительно, работает. Показывает ссылки слева в левой колонке.
Теперь прикрепим class="active"
к родительскому пункту в самом верхнем уровне меню (primary links). Для этого воспользуемся TemplatePHP сниппетом с этой страницы. Вставляем в template.php данный код (без закрывающего ?>
). Для моей ситуации ссылка на главную страницу не имеет дочерних меню, поэтому можно сократить код до такого состояния:
<?php
function phptemplate_links($links, $attributes = array()) {
if (!count($links)) {
return '';
}
$level_tmp = explode('-', key($links));
$level = $level_tmp[0];
$output = "<ul class=\"links-$level ".$attributes['class']. "\">\n";
foreach ($links as $index => $link) {
$output .= '<li';
if (stristr($index, 'active')) {
$output .= ' class="active"';
}
$output .= ">". l($link['title'], $link['href'], $link['attributes'], $link['query'], $link['fragment']) ."</li>\n";
}
$output .= '</ul>';
return $output;
}
?>
Код для page.tpl.php также не обязательно повторять за автором статьи, так как он оптимизирован для его меню, нам будет достаточно:
<?php if (isset($primary_links)) : ?>
<?php print theme('links', $primary_links) ?>
<?php endif; ?>
Теперь самая сложная для нас задача. Если бы я была программистом, то я бы с легкостью написала какой-нибудь TemplatePHP сниппет, и автоматом все родительские ссылки имели class="active"
, однако я не программист, поэтому решим эту проблему с помощью CSS.
Такое меню генерирует код из блока.
<ul class="sbtree">
<li class="leaf"><a href="/Company_History">Company History</a></li>
<li class="expanded"><a href="/Business_Units">Business Units</a>
<ul class="menu">
<li class="expanded"><a href="/Property_Development">Property Development</a>
<ul class="menu">
<li class="leaf"><a href="/board_committees" class="active">Board Committees</a></li >
<li class="leaf"><a href="/Rules_of_Procedure">Rules of Procedure</a></li>
</ul>
</li>
<li class="leaf"><a href="/Real_Estate_Funds">Real Estate Funds</a></li>
<li class="leaf"><a href="/Russia">Russia</a></li>
</ul>
</li>
<li class="leaf"><a href="/Corporate_Governance">Corporate Governance</a></li>
</ul>
Такие классы меню нужны мне чтобы полностью проследить 4 уровня вложенного меню.
ul.sbtree li a.active - просто активное меню второго уровня
ul.sbtree li.expanded a - родительский пункт развернутого меню, содержащего активный пункт - хотим чтобы он был как активный
ul.sbtree li.expanded ul.menu li a - дочерний неактивный пункт меню третьего уровня - хотим чтобы он был как неактивный
ul.sbtree li ul.menu li a.active - дочерний активный пункт меню третьего уровня
ul.sbtree li.expanded ul.menu li.expanded a - родительский пункт развернутого меню в развернутом меню - хотим чтобы он был как активный
ul.sbtree li.expanded ul.menu li.expanded ul.menu a - дочерний неактивный пункт развернутого меню в развернутом меню - хотим чтобы он был как неактивный
ul.sbtree li.expanded ul.menu li.expanded ul.menu a.active - - дочерний активный пункт меню четвертого уровня
Итак, используя 2 сниппета и одно меню, стилизованное через CSS мы получили меню, которое удовлетворяет нашим требованиям:
- Разделение расположения основных и второстепенных разделов меню.
- Второстепенные разделы показываются только при выборе одного из основных.
- Выделение активным классом всех родительских пунктов на всех уровнях.
- Возможность вывода дерева меню (много уровней) в подразделах (чего нельзя добиться при использовании secondary_links)
PS:Если вам нужно чтобы при просмотре определенного типа документов или термина таксономии было активным какое-то меню, воспользуйтесь замечательным модулем - menutrails.
Ссылки по теме:
http://www.drupal.ru/node/3573
http://www.drupal.ru/node/3335
http://www.drupal.ru/node/8581
http://www.drupal.ru/node/12210
http://www.drupal.ru/node/10894
http://drupal.org/node/183266
http://drupal.org/node/46020
http://drupal.org/node/77099
http://drupal.org/node/86890
http://drupal.org/project/local_menu