Как стать автором
Обновить

Танцы с бубном, часть 2 — tabbed menu в Drupal

Drupal *
Собственно, продолжение вот этого хабратопика, что называется, «по просьбам трудящихся». И прежде чем я начну, я приношу кучу искренних благодарностей хабраюзерам, не ленившимся слать багрепорты и тем самым помогавшим «вылизать» как следует результат. Пусть нет предела совершенству, и пару шероховатостей мне ещё предстоит пофиксить — но в любом случае, лучше, чем было изначально. А теперь я расскажу вам, как я натянула всю эту кухню на систему меню в Drupal.

Для начала — сформулируем задачу. Нам нужно, чтобы:
  1. пункт меню становился активным при выборе соответсвующей ему страницы (ну это ежу понятно, и соответствующий класс на ссылку навешивается Друпалом автоматически)
  2. каждому пункту меню соответствовал уникальный ID для навешивания на него стилей
  3. пункт меню оставался активным при выборе любой ноды с этой страницы или при выборе версии для печати (ссылка на которую имеет вид «имя_страницы-print»)
  4. По умолчанию, на прочих страницах, не имеющих отношения к каталогу, активным должен быть пункт меню «Квартиры»

Ну и чтобы выглядело это всё, соответственно, так:
image

Создаём новое меню («Управление» — «Конструкция сайта» — «Меню»). Запихиваем в него нужные ссылки. Идём в «Управление» — «Конструкция сайта» — «Блоки» и подставляем блок с новым меню в какую-нибудь из видимых областей (не забудьте проверить, выводится ли эта область в шаблоне, и соответствуют ли рабочие div-ы области тем ID, что прописаны в таблице стилей). Получаем «голое» меню, которое и будем сейчас кастомайзить.

Итак, поскольку задача 1 решена Друпалом «из коробки» и уже прописана в нашей таблице стилей из предыдущего топика, перейдём к пункту 2. Как приделать к каждому пункту меню уникальные атрибуты, к примеру, ID? Очень просто — ставим модуль Menu Attributes, включаем его на странице управления модулями, и теперь, заходя в редактирование пункта меню, будем видеть отдельную секцию для добавления атрибутов. В нашем случае, каждой ссылке присваиваем ID: для пункта меню «Квартиры» — «apartments», для «Домов и дач» — «houses», для «Земельных участков» — «ground», ну и для «Промышленной недвижимости» — «business». И после сей процедуры увидим, что теперь меню по крайней мере на страницах каталогов (генерируемых при помощи Views, если что) выглядит как надо.

Поехали дальше. Теперь нам надо сохранить пункт меню активным в случае выбор любой ноды из соответствующего раздела каталога, или же версии для печати страницы. Надо сказать, что у меня каждый тип недвижимости — это отдельный тип ноды, с соответствующими параметрами, поэтому. делая привязку, я буду проверять именно тип ноды, хотя вообще это может быть что угодно (таксономия, поле CCK… да мало ли). Залезаем в папку нашего шаблона и открываем файл template.php, добавляя в него следующие строчки:

function phptemplate_menu_item($link, $has_children, $menu = '', $in_active_trail = FALSE, $extra_class = NULL) {
  $class = ($menu ? 'expanded' : ($has_children ? 'collapsed' : 'leaf'));
  if (!empty($extra_class)) {
    $class .= ' '. $extra_class;
  }
        preg_match("/node\/\d+/", request_uri(), $nid);
	//я знаю, что это тупой подход, но по крайней мере он работает. а извращения с preg_match - почему-то нет
	if (!empty($nid[0])) {
	$nid[0] = ereg_replace("node/", "", $nid[0]);
	$tmp = node_load($nid[0]);
	}
	
  if (ereg('apartments',$link) and !(preg_match("/houses|ground|business/", request_uri()) or preg_match("/house|place|for_business/", $tmp->type) )) {$in_active_trail = true;}
    if ( ereg('/houses',$link) and (ereg("/houses", request_uri()) or $tmp->type=='house') ) {$in_active_trail = true;}
    if ( ereg('/ground',$link) and (ereg("/ground", request_uri()) or $tmp->type=='place') ) {$in_active_trail = true;}
    if ( ereg('/business',$link) and (ereg("/business", request_uri()) or $tmp->type=='for_business') ) {$in_active_trail = true;}
  if ($in_active_trail) {
    $class .= ' active-trail ';
    
  }
  return '<li class="'. $class .'">'. $link . $menu ."</li>\n";
}

Ух… испугались? А вы не бойтесь. сейчас я вам объясню, что здесь происходит. Сама по себе функция переопределяет стандартный друпаловский вывод меню. Поскольку глобальная переменная $node тут (фиг знает, почему, времени не было разбираться) не видна, то номер активной ноды, если есть таковой, мы получаем из текущего URL регулярным выражением. И если таковой всё же есть — подгружаем параметры ноды.

Затем проверяем несколько условий — всего лишь, содержится ли адрес текущей страницы в линке меню (это нужно, чтобы версии для печати, содержащие имя страницы, обрабатывались корректно), а если нет — то соответствует ли тип текущей ноды соответсвующему странице типу недвижимости. Всё! :)

Я знаю, что это наверняка не самый красивый, быстрый, масштабируемый и т.п. способ. Но, во-первых, это мой первый мало-мальски серьёзный проект на drupal, а, во-вторых, мне же пообещали, что структура меню и материалов впредь останется неизменной. Хотя, в принципе, если грамотно подойти к именованию типов материалов и страниц, чтобы все они соответствовали определённому шаблону, то теми же регулярками эту задачу можно экстраполировать и на более серьёзные условия…
Теги:
Хабы:
Всего голосов 7: ↑6 и ↓1 +5
Просмотры 1.3K
Комментарии Комментарии 6