Эта задача из разряда useability. Drupal может штатно создавать блоки вертикальных иерархических меню.
Неудобным будет тот случай, когда мы хотим попасть на страницу в глубине иерархии этого меню. Нам придется последовательно заходить на родительские страницы, пока мы не достигнем нужной нам вложенной публикации. А это и нагрузка на сервер и ожидание пользователя загрузки каждой очередной страницы (а они ох как не любят ждать).
Можно, конечно, сделать какие то ветки меню всегда раскрытыми (expanded). Это подойдет для ряда случаев, когда пунктов меню не очень много (20-30). Если же речь идет о каталоге товаров, то раскрывать сразу всю портянку будет не разумно. А с закрытыми (collapsed) подменю Drupal обходится так, что просто их не выводит в шаблон (раз их не видно), пока они свернуты, и вы не активизировали соответствующий пункт меню.
Я покажу как можно, используя jQuery, функции API Drupal Menu и такую то мать (немного PHP), собрать блок вертикального разворачивающегося меню. В конце добавим щепотку CSS для полноты вкуса.
Программируем альтернативный блок меню (PHP и Drupal API)
Стандартная часть объявления блока в drupal, и пара функций реализующих блок нашего меню. Всё действие разворачивается в коде гипотетического модуля MyModule.
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 37 38 39 40 41 42 43 44 45 46 47 |
function MyModule_block($op = 'list', $delta = 0, $edit = array()) { switch ($op) { case 'list': //объявление списка блоков //я назвал его - меню продукции и запретил его кеширование $block = array(); $block[0]["info"] = t('SC: Меню продукции'); $block[0]['cache'] = BLOCK_NO_CACHE; return $block; case 'view': switch ($delta) { //обработчики блоков case 0: return _MyModule_productmenu(); } } } /* товарное меню со сладингом */ function _MyModule_productmenu() { //получим все дерево меню продукции (а не её активную ветку, //как сделано в аналогичном блоке ядра drupal) $tree = menu_tree_all_data('menu-products', NULL); //нам придется вручную отметить active_trail в нашем меню _MyModule_restore_path($tree); //все готово! формируем стандартный html код меню $menu_output = menu_tree_output($tree); return array('content' => $menu_output, 'subject' => ''); } /* надо восстановить активный путь active-trail рекурсивно проходим меню, отмечая текущий путь */ function _MyModule_restore_path(&$tree) { foreach ($tree as &$v) { if ($v['link']['href'] == $_GET['q']) { $v['link']['in_active_trail'] = 1; return true; } if (is_array($v['below']) && _MyModule_restore_path($v['below'])) { $v['link']['in_active_trail'] = 1; return true; } } return false; } |
Следующий этап — вспомогательная функция на javascript (+ jQuery)
Без jQuery сейчас вообще никуда. Раньше приходилось городить страшный огород из кросс-браузерных скриптов, а сейчас весь этот огород давно перепахан и засеян. Просто хеппи-мил какой то.
Логика работы меню такая : по клику на элемент меню, мы должны переходить на соответствующую публикацию сайта, поэтому для того чтобы развернуть меню — нам остается только одно событие — наведение мыши (hover). Но если провести мышью над всем меню, то все пункты должны будут развернуться, а это не то, что нам нужно. Поэтому разворачивать меню мы будем с задержкой, давая пользователю возможность «навести» мышь на нужный пункт меню.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
$(window).load(function() { //цепляем обработчики hover после загрузки документа в браузер //к стандартным классам блочного меню (вы можете добавить //свои фильтры, например, ID контейнера блока меню) $(".block-menu li.expanded").hover( function () { var popup = $(this).children("ul.menu"); //создаем отложенную анимацию (отложенную на 0,650 с) intervalID = setTimeout( function() { popup.slideDown(1000); }, 650 ) }, //вторая часть hover - мышь покинула границы контейнера - //отложенную анимацию следует отменить function () { clearInterval(intervalID); } ); }); |
На этом заканчивается код на javascript.
И ещё каплю CSS.
Чтобы вы там не писали для оформления меню, вам придется добавить примерно такие стили:
1 2 3 4 5 6 |
.block-menu li.expanded ul { display: none; } .block-menu li.expanded.active-trail > ul { display: block; } |
Т.е. надо показать активную ветку и закрыть все прочие.
И это все! Никаких танцев с бубном, друзья. :)