Усовершенствованный компонент 1С-Битрикс bitrix:menu
Апр 25, 2010 1С-Битрикс, CMS, JavaScript, PHP, Программирование, Работа
Добрый день, дорогие читатели!
Если Вы следите за моим twitter‘ом, то наверное, читали твит анонс, в котором я говорил про пост о 1С-Битрикс и jQuery меню. В данный момент, решил не много отдохнуть от работы и диплома, поэтому выкладываю пост.
Как видно из названия, в данном посте пойдет речь о стандартном компоненте 2.0 CMS 1С-Битрикс, который я немного усовершенствовал под свои нужды. Начну из далека, по работе дали задание, в котором требуется реализовать раскрывающиеся меню с сохранением раскрытых пунктов при переходе и реализовать все это на файлах меню (.left.menu.php). Как только я получил данное задание, задумался о том, как же реализовать меню на файлах? До этого я сталкивался только с меню строящимся из информационных блоков. Сразу бросается в глаза, что можно использовать стандартный компонент bitrix:menu, в котором есть все необходимые настройки, кроме одной: вывод полного меню на любой странице, даже после перехода.
Формулировка задачи
Во-первых, необходимо доработать компонент bitrix:menu и научить его всегда выводить выбранное меню (left) от корня сайта. Во-вторых, привязать меню на jQuery с плагином jQuery.cookie. Со вторым пунктом все намного проще, так как наработки в данном направлении уже имеются и о них я писал на блоге (пост “Меню на jQuery“). С первым в общем-то тоже проблем не было, нужно было только придумать как все красиво подправить, чтобы это работало, было удобно и можно было использовать в других проектах. С постановкой задачи мы определились, пора приступать к реализации.
Реализация
Перед реализацией, необходимо провести подготовительную работу, т.е. скопировать компонент bitrix:menu в папку components/ИМЯ_НАШЕГО_NAMESPACE/, так же стоит поменять название, например на left.menu.
Теперь у нас все готово для правки кода. Открываем основной файл компонента component.php и ищем вот такую строчку (в районе 28):
28 | $curDir = $APPLICATION->GetCurDir(); |
Именно этот кусок кода нам и надо отредактировать, функция GetCurDir() – возвращает рабочий каталог, именно эта функция заставляет наш компонент искать файлы меню в отличных от “/” каталогах, после перехода, нам же надо заставить искать файлы всегда, начиная с корня.
Самое простое было бы просто убрать эту функцию и поставить “/”, но тогда данный компонент будет, узкоспециализированным, а нам бы все таки хотелось универсальный инструмент, поэтому мы пойдем немного другим путем. Заменяем данную строку, на такой код:
28 29 30 31 32 33 34 35 | /* Расширение компонента, если параметр $arParams["PATH_MENU"] == "", то меню выводиться свое для каждого уровня, если имеет параметр /, то всегда полное меню */ if(!$arParams["PATH_MENU"]) $curDir = $APPLICATION->GetCurDir(); else $curDir = $arParams["PATH_MENU"]; |
После этого добавления, нам нужно поправить файл .parameters.php и внести следующие строчки кода:
1 2 3 4 5 6 | "PATH_MENU" => Array( "NAME" => "Выводить все уровни, начиная с", "TYPE" => "TEXTBOX", "DEFAULT" => "", "PARENT" => "BASE" ), |
Тут особо комментировать нечего, так что воздержусь. Подведем итоги первой части работы: мы выполнили первую часть задания, при этом сохранили стандартный функционал, что, по-моему мнению, является правильным. Теперь для работы нам просто, необходимо поменять компонент и в настройках поставить “/” для нашей опции (параметра).
Вторая часть задания – привязка jQuery меню
Копируем шаблон и начинаем редактировать его, проще сразу все удалить и вставить следующий код:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | <?if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED!==true)die();?> <script src="<?=SITE_TEMPLATE_PATH?>/components/bitrix/menu/LMenu/script.js"></script> <? function Img($res, $lvl, $j) { if(isset($res[$j+1]) && ($res[$j+1]["DEPTH_LEVEL"] > $lvl)) { $img = '<img style="padding-top: 6px;" id="plus'.$j.'" name="plus'.$j.'"/>'; } return $img; } ?> <?if (!empty($arResult)):?> <ul id="menuLeft" class="padding1"> <?$realLevel = 1; $idParent = 0;?> <?foreach($arResult as $i=>$arItem):?> <?if($arItem["DEPTH_LEVEL"] == ($realLevel+1)):?> <?$realLevel++;?> <ul id="splus<?=$idParent;?>" style="padding-left: 10px; display: none;"> <?endif;?> <?if($arItem["DEPTH_LEVEL"] < $realLevel):?> <?$realLevel--;?> </ul> <?endif;?> <?if($arItem["DEPTH_LEVEL"] == $realLevel):?> <li style="background-image: none;"><?=Img($arResult, $realLevel, $i);?><a href="<?=$arItem["LINK"]?>"><?=$arItem["TEXT"]?></a></li> <?endif;?> <? //устанавливаем нового Папу :-) $idParent = $i; //echo $idParent."-".$i."<br/>"; ?> <?endforeach?> </ul> <?endif?> |
Во-второй, строке я сознательно “жестко” подключил файл JS, для наглядности.
Листинг JS файла:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | $(document).ready(function(){ $("ul#menuLeft img").each(function() { if($.cookie('submenuM-' + this.id)){ document.images[this.id].src = '/bitrix/templates/binran/images/list-marker1.gif'; $("ul#s"+this.id).show(); }else{ document.images[this.id].src = '/bitrix/templates/binran/images/list-marker.gif'; $("ul#s"+this.id).hide(); } }); $(document).ready(function(){ $("ul#menuLeft img").click(function(){ if($("ul#s"+this.id).css('display') == 'none') { cookieSet(this.id); $("ul#s"+this.id).slideDown(200); document.images[this.id].src = '/bitrix/templates/binran/images/list-marker1.gif'; $("ul#s"+this.id).css('display') = ''; }else{ cookieDel(this.id); $("ul#s"+this.id).slideUp(200); document.images[this.id].src = '/bitrix/templates/binran/images/list-marker.gif'; } }); }); }); function cookieSet(index) { $.cookie('submenuM-' + index, 'opened', {expires: null, path: '/'}); // Set mark to cookie (submenu is shown): } function cookieDel(index) { $.cookie('submenuM-' + index, null, {expires: null, path: '/'}); // Delete mark from cookie (submenu is hidden): } |
Тут код, должен быть понятен, если Вы читали прошлый пост про меню на jQuery, поэтому опять таки комментировать не буду, если возникнут вопросы, то задавайте в комментариях.
Все. Вроде все задания выполнены, есть результат и что самое важное все работает как часы
Подписывайтесь на RSS и Twitter, чтобы не пропустить интересные посты!
С уважением, Главный Лаборант.
Советуем почитать:
Метки: 1С-Битрикс, JQuery, Компонент 2.0, Пример, программирование




Алексей Валеев, написал:
апреля 25, 2010 в 22:39
Если решать именно Вашу задачу (меню от корня всегда), то можно сделать так:
1. в корне переименовываем .left.menu.php в .lefttop.menu.php
2. подключаем компонент menu vertical-multilevel с параметрами – меню первого уровня lefttop, остальных уровней left, вложенность – какое-нибудь большое число
3. все тоже самое что и в статье, начиная со 2го задания.
Собственно плюс один – заюзанный компонент дефолтный и не теряет обновления
[Ответить на комментарий]
Главный Лаборант ответил на комментарий:
26 Апр 2010 в 1:09
Да это выход – не знал, но что делать с тем, что меню должно показывать уровень вложенности, т.е. можно в пункт меню “Институт” включить подпункты, такой подход как Вы описали подойдет? И еще вопрос в каких редакциях есть такой компонент? Просто я его что то не видел
Или не заметил, я делал на редакции Старт.
[Ответить на комментарий]
Алексей Валеев, написал:
апреля 26, 2010 в 7:14
Компонент bitrix:menu, в его настройках Шаблон->vertical_multilevel (в старте есть)
С вложенностью проблем не возникнет, меню будет строиться с произвольным уровнем глубины. В результате получится тот же массив что и использовался в шаблоне (с arItem["DEPTH_LEVEL"])
Хотя есть вариант что я неправильно понял задачу
[Ответить на комментарий]
Главный Лаборант ответил на комментарий:
26 Апр 2010 в 9:03
А да есть такой шаблон, но скорее всего Вы чуть чуть не до конца поняли задачу, задача заключается в том что на главной (index.php) мы должны показать все меню с вложениями (например, /institut/, а в данной папке второй уровень и так далее) и при переходе на данную страницу (опять таки, как пример /institut/), мы должны показать меню начиная с главной.
В общем вот так вот.
[Ответить на комментарий]
Алексей Валеев ответил на комментарий:
26 Апр 2010 в 9:46
Видимо задачу я понял все-таки правильно:)
Попробую объяснить идею подробно:
1. в корне сайта переименовываем .left.menu.php в .lefttop.menu.php – это надо для того, чтобы в самом верхнем уровне структуры тип меню отличался
2. подключаем стандартный компонент menu с параметрами как в первом комментарии
3. принцип действия – в каком уровне вложенности бы мы не находились, битрикс строит меню от корня, потому что .lefttop.menu.php есть только там
[Ответить на комментарий]
Главный Лаборант ответил на комментарий:
26 Апр 2010 в 10:08
Хммм….посмотрел, да Вы правы!
Очень хороший способ
Спасибо, учту на будущее, сейчас переделывать уже не буду, так как работа сдана и то задание принято.
Еще раз спасибо!
Алексей Валеев, написал:
апреля 26, 2010 в 7:19
Кстати, с vertical_multilevel я загнул, этот шаг не нужен)) Вы же все равно полностью заменяете содержимое template.php в шаблоне, так что какой именно кастомизировать не важно)
[Ответить на комментарий]