Новичкам – разбираемся с шаблоном меню horizontal_multilevel
Опубликовано 19 Июл 2011
![]()
В статье разберем «по строкам» самый частоиспользуемый шаблон компонента bitrix:menu, который позволяет выводить меню произвольного уровня вложенности.
PHP код шаблона
Ниже приведен полный php-код шаблона horizontal_multilevel с подробными комментариями.
<?if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED!==true)die(); // проверяем, загружена ли служебная часть сайта (ядро)?>
<?
/*
Структура массива $arResult
Массив $arResult состоит из вложенных массивов, соответсвующих пунктам меню.
Порядок следования пунктов
Вложенные массивы содержат ключи:
TEXT - текст текущего пункта меню
LINK - ссылка текущего пункта меню
SELECTED - выбран ли пункт меню в данный момент
PERMISSION - доступ на страницу указанную в $LINK, возможны следующие значения:
D - доступ запрещён
R - чтение (право просмотра содержимого файла)
U - документооборот (право на редактирование файла в режиме документооборота)
W - запись (право на прямое редактирование)
X - полный доступ (право на прямое редактирование файла и право на изменение прав доступа на данных файл)
ADDITIONAL_LINKS - дополнительные ссылки для подсветки меню
ITEM_TYPE - "D" - директория (если LINK заканчивается на "/"), иначе "P" - страница
ITEM_INDEX - порядковый номер пункта меню
PARAMS - параметры пунктов меню
DEPTH_LEVEL - уровень вложенности пункта меню (1 для главного, 2 и далее для вложенных)
IS_PARENT - флаг того, что у этого пункта меню будет подменю
Вывод производится вложенными списками вида
<ul id="horizontal-multilevel-menu">
<li><a>Пункт первого уровня вложенности</a></li>
<li><a>Пункт первого уровня вложенности</a>
<ul>
<li><a>Пункт второго уровня вложенности</a></li>
<li><a>Пункт второго уровня вложенности</a></li>
</ul>
</li>
<li><a>Пункт первого уровня вложенности</a></li>
</ul>
*/
?>
<?if (!empty($arResult)): // если есть хотя бы 1 пункт меню, можно начинать вывод?>
<ul id="horizontal-multilevel-menu">
<?
$previousLevel = 0; // переменная содержит значение DEPTH_LEVEL предыдущего пункта
foreach($arResult as $arItem): // пробегаем по пунктам, $arItem - массив с информацией о текущем пункте?>
<?if ($previousLevel && $arItem["DEPTH_LEVEL"] < $previousLevel):?>
<?// если уровень вложенности текущего пункта меню меньше чем у предыдущего, значит "подменю" закончилось и нужно закрыть список?>
<?=str_repeat("</ul></li>", ($previousLevel - $arItem["DEPTH_LEVEL"]));?>
<?endif?>
<?if ($arItem["IS_PARENT"]): //если пункт содержит подменю, выводим ссылку и начинаем новый список (тег <ul>)?>
<?if ($arItem["DEPTH_LEVEL"] == 1): // если уровень вложенности =1, т.е. это главное меню?>
<?// выводим ссылку и добавляем класс "root-item" если пункт неактивный и "root-item-selected" если активный?>
<li><a href="<?=$arItem["LINK"]?>" class="<?if ($arItem["SELECTED"]):?>root-item-selected<?else:?>root-item<?endif?>"><?=$arItem["TEXT"]?></a>
<ul>
<?else: // для остальных уровней вложенности?>
<?// выводим ссылку и добавляем класс "parent". Если пункт активный, для элемента списка <li> добавляем класс "item-selected"?>
<li<?if ($arItem["SELECTED"]):?> class="item-selected"<?endif?>><a href="<?=$arItem["LINK"]?>" class="parent"><?=$arItem["TEXT"]?></a>
<ul>
<?endif?>
<?else: // для пунктов, не содержащих подменю?>
<?if ($arItem["PERMISSION"] > "D"): // проверяем право доступа к пункту?>
<?if ($arItem["DEPTH_LEVEL"] == 1): // если уровень вложенности =1, т.е. это главное меню?>
<?// выводим ссылку и добавляем класс "root-item" если пункт неактивный и "root-item-selected" если активный?>
<li><a href="<?=$arItem["LINK"]?>" class="<?if ($arItem["SELECTED"]):?>root-item-selected<?else:?>root-item<?endif?>"><?=$arItem["TEXT"]?></a></li>
<?else: // для остальных уровней вложенности?>
<?// выводим ссылку. Если пункт активный, для элемента списка <li> добавляем класс "item-selected"?>
<li<?if ($arItem["SELECTED"]):?> class="item-selected"<?endif?>><a href="<?=$arItem["LINK"]?>"><?=$arItem["TEXT"]?></a></li>
<?endif?>
<?else: // для пунктов, к которым запрещен доступ?>
<?if ($arItem["DEPTH_LEVEL"] == 1): // если уровень вложенности =1, т.е. это главное меню?>
<?// выводим пустую ссылку и добавляем класс "root-item" если пункт неактивный и "root-item-selected" если активный?>
<li><a href="" class="<?if ($arItem["SELECTED"]):?>root-item-selected<?else:?>root-item<?endif?>" title="<?=GetMessage("MENU_ITEM_ACCESS_DENIED")?>"><?=$arItem["TEXT"]?></a></li>
<?else: // для остальных уровней вложенности?>
<?// выводим пустую ссылку и добавляем класс "denied"?>
<li><a href="" class="denied" title="<?=GetMessage("MENU_ITEM_ACCESS_DENIED")?>"><?=$arItem["TEXT"]?></a></li>
<?endif?>
<?endif?>
<?endif?>
<?$previousLevel = $arItem["DEPTH_LEVEL"]; // запоминаем уровень вложенности?>
<?endforeach?>
<?if ($previousLevel > 1):// если работа завершилась на пункте меню с уровнем вложенности >1, закрываем вложенные списки?>
<?=str_repeat("</ul></li>", ($previousLevel-1) );?>
<?endif?>
</ul>
<div class="menu-clear-left"></div>
<?endif?>
CSS код шаблона
Кратко пробежимся по css-файлу и выясним, какие правила за что отвечают при визуальном оформлении меню.
/* в соответствии со структурой меню, описанной в template.php контейнер пунтов меню - <ul> контейнер пункта меню - <li> ссылка пункта меню - <a> */ /**Top menu**/ #horizontal-multilevel-menu,#horizontal-multilevel-menu ul /* стили для контейнера пунтов главного и вложенных меню */ #horizontal-multilevel-menu /* стили для контейнера пунктов главного меню */ /*Links*/ #horizontal-multilevel-menu a /* стили для ссылок пунктов меню всех уровней */ #horizontal-multilevel-menu li /* стили для контейнера пункта меню */ /*Root items*/ #horizontal-multilevel-menu li a.root-item /* стили для ссылок главного меню */ /*Root menu selected*/ #horizontal-multilevel-menu li a.root-item-selected /* стили для активной (выделенной) ссылки главного меню */ /*Root items: hover*/ #horizontal-multilevel-menu li:hover a.root-item, #horizontal-multilevel-menu li.jshover a.root-item /* стили для ссылок главного меню при наведении мышью */ /*Item-parents*/ #horizontal-multilevel-menu a.parent /* стили для ссылок НЕглавного меню, у которых есть вложенное меню */ /*Denied items*/ #horizontal-multilevel-menu a.denied /* стили для ссылок, к которым запрещен доступ */ /*Child-items: hover*/ #horizontal-multilevel-menu li:hover, #horizontal-multilevel-menu li.jshover /* стили для для контейнера пункта меню при наведении мышью */ /*Child-items selected*/ #horizontal-multilevel-menu li.item-selected /* стили для контейнера активного (выделенного) пункта вложенного меню */ /*Sub-menu box*/ #horizontal-multilevel-menu li ul /* стили для контейнера пунктов вложенного меню */ /*Sub-menu item box*/ #horizontal-multilevel-menu li li /* стили для контейнера пункта вложенного меню */ /*Item link*/ #horizontal-multilevel-menu li ul a /* стили для ссылки пункта вложенного меню */ /*Items text color & size */ #horizontal-multilevel-menu li a, #horizontal-multilevel-menu li:hover li a, #horizontal-multilevel-menu li.jshover li a, #horizontal-multilevel-menu li:hover li:hover li a, #horizontal-multilevel-menu li.jshover li.jshover li a, #horizontal-multilevel-menu li:hover li:hover li:hover li a, #horizontal-multilevel-menu li.jshover li.jshover li.jshover li a, #horizontal-multilevel-menu li:hover li:hover li:hover li:hover li a, #horizontal-multilevel-menu li.jshover li.jshover li.jshover li.jshover li a, #horizontal-multilevel-menu li:hover li:hover li:hover li:hover li:hover li a, #horizontal-multilevel-menu li.jshover li.jshover li.jshover li.jshover li.jshover li a /* стили для ссылок вложенного меню */ /*Items text color & size: hover*/ #horizontal-multilevel-menu li:hover li:hover a, #horizontal-multilevel-menu li.jshover li.jshover a, #horizontal-multilevel-menu li:hover li:hover li:hover a, #horizontal-multilevel-menu li.jshover li.jshover li.jshover a, #horizontal-multilevel-menu li:hover li:hover li:hover li:hover a, #horizontal-multilevel-menu li.jshover li.jshover li.jshover li.jshover a #horizontal-multilevel-menu li:hover li:hover li:hover li:hover li:hover a, #horizontal-multilevel-menu li.jshover li.jshover li.jshover li.jshover li.jshover a #horizontal-multilevel-menu li:hover li:hover li:hover li:hover li:hover li:hover a, #horizontal-multilevel-menu li.jshover li.jshover li.jshover li.jshover li.jshover li.jshover a /* стили для ссылок вложенного меню при наведении мышью */ #horizontal-multilevel-menu li ul ul /* стили для контейнера пунктов вложенного меню (уровень вложенности >2) */ #horizontal-multilevel-menu li:hover ul ul, #horizontal-multilevel-menu li.jshover ul ul, #horizontal-multilevel-menu li:hover ul ul ul, #horizontal-multilevel-menu li.jshover ul ul ul, #horizontal-multilevel-menu li:hover ul ul ul ul, #horizontal-multilevel-menu li.jshover ul ul ul ul, #horizontal-multilevel-menu li:hover ul ul ul ul ul, #horizontal-multilevel-menu li.jshover ul ul ul ul ul /* обработка реакции на наведение мышью - скрываем вложенные меню уровня, более чем на 1 превышающее выделенный */ #horizontal-multilevel-menu li:hover ul, #horizontal-multilevel-menu li.jshover ul, #horizontal-multilevel-menu li li:hover ul, #horizontal-multilevel-menu li li.jshover ul, #horizontal-multilevel-menu li li li:hover ul, #horizontal-multilevel-menu li li li.jshover ul, #horizontal-multilevel-menu li li li li:hover ul, #horizontal-multilevel-menu li li li li.jshover ul, #horizontal-multilevel-menu li li li li li:hover ul, #horizontal-multilevel-menu li li li li li.jshover ul /* обработка реакции на наведение мышью, показываем вложенные меню */
JS файл шаблона
Этот скрипт существует с одной единственной целью – научить браузер Internet Explorer версии 6 и ниже «понимать» наведение мышью на тег <li>. При наведении элементу присваивается класс «jshover», после «ухода» курсора за пределы элемента – класс снимается.
Заключение
Стандартный шаблон horizontal_multilevel довольно гибкий и позволяет реализовать различные вариации меню правкой только файла стилей. Однако, некоторые необходимые вещи не реализованы – количество пунктов меню n-го уровня можно узнать только полным перебором массива-результата. Еще более сложной задачей является «выделение» в цикле последнего пункта подменю, например, для выделения скругленной рамкой.
Пишите свои вопросы в комментариях, я буду делиться своими наработками конкретно к Вашей задаче.
PS: небольшой привет разработчикам. Этот баг повторяется очень часто при установке продукта из Opera
Похожие записи
Метки: css, javascript, php




Статья – просто must have для таких нубов в Битриксе, как я! А откуда он тянет $arResult?
$arResult передается из компонента как результат его работы
Алексей! Вот столкнулся с задачей вывода последнего пункта меню в отличном от остальных стиле, подскажите пожалуйста как решить эту проблему.
Андрей, нужно пробежать по всем пунктам и запомнить последний (на нужном уровне). Потом при выводе найти его и выделить:)
Подскажте никак не могу разобраться, как сделать так чтобы вложенность была всего 2.
Тоесть главное меню и их подпапки. больше ничего не надо.
Игорь, вложенность можно задать в настройках компонента
Баг с установкой не только в опере часто встречается. При установке с мака (FF 6.0.2 Chrome Safari 5.1.1) эта ошибка с завидной регулярностью возникает на 75% установки каталога. На Lione’е можно пару раз тыкнуть «Повторить» и поставится, на Snow Leopard’е виснет наглухо.
Тоже новичок ещё в Битриксе. Хочу разобраться с другим типом меню как tree. Можно будет также увидеть разбор этого шаблона. Хотелось бы дописать в него ряд дополнений, но пока разбираюсь ещё только как программировать шаблон.
пишу его для сайта http://medfarma.net. В css я уже немного поправил.
я тоже новичок в Битриксе. Из Vertical_multilevel или Default можно сделат Аккордион меню?
Almat, можно. Из default легче, но одноуровневое, из vertical-multilevel чуть сложнее, но произвольного уровня вложенности.
я видел вашем интернет магазине http://www.autoleon.ru/ левый аккордион меню. Подскажи какой битриксовый шаблон ты там использовал или костомизировал??
заранее благодарю!
Это не меню, а сильно измененный catalog.section.list
я могу сделать типа такого http://dobrovoi.ru/files/accordeon1/index.html с помощью vertical-multilevel?? Я делаю интернет магазин чуть-чуть не хватает функционал и дизайн.
Можно ли сделать из этого меню, что нибудь типа вот такого http://radar-groupe.ru? Этот полностью на HTML. Хочу перетащить его под битрикс но вот сомневаюсь насёт меню. А у VW жосткие стандарты (всё по бренд-буку) и не шагу в сторону.
Михаил, можно, только чуть сложнее с выводом.
А не подскажешь как делают, чтобы на странице отображалось два верхних горизонтальных меню одновременно (то есть меню и подменю)? Пример http://www.ursu.ru
Какой шаблон используют?
Обычно ведь при нажатии кнопки меню, выходит подменю, а меню пропадает.
phisey, нужно модифицировать шаблон компонента меню. Примерно так: определяем активный пункт меню первого уровня – запоминаем его подпункты (отмечая активный, если он есть). Проходим по меню и выводим в строку 1й уровень, затем запомненные подпункты 2й строкой.