[РЕШЕНО] Как изменить HTML-код меню, возвращаемый модулем superfish? (вставка тегов span)
Прислано: Lex-DRL
вс, 14/03/2010 - 18:02
На сайте стоит модуль
Superfish, позволяющий создавать красивые выпадающие меню. Для пунктов меню он генерирует HTML-код такого вида (разбил на строки для наглядности):
<li class="sfHover" id="menu-132-1"> <a href="/foo" title="bar">Menu Item</a> </li>
Из соображений темизации необходимо привести этот код к такому виду:
<li class="sfHover" id="menu-132-1"> <a href="/foo" title="bar"> <span class="back"><span class="bg1"></span> Menu Item <span class="foreground"></span></span> </a> </li>
Т.е. добавить несколько тегов span вокруг, до и после текста ссылки, но внутри тега < a >.
В коде модуля я нашёл такие строки:
if ((!empty($menu_item['link']['has_children'])) && (!empty($menu_item['below'])) && $depth != 0) { $children = theme('superfish_build', $id, $menu_item['below'], $depth, $trail); $parent_class = $children ? 'menuparent ' : ''; $output .= '<li id="menu-'. $mlid .'-'. $id .'"'; if (!empty($parent_class) || !empty($class)) { $output .= ' class="'. $parent_class . $class .'"'; } $output .= '>'. theme('menu_item_link', $menu_item['link']); if ($menu_item['link']['depth'] <= $depth || $depth == -1) { if ($children) { $output .= "<ul>\n $children \n</ul>\n"; } } $output .= "</li>\n"; } else { $output .= '<li id="menu-'. $mlid .'-'. $id .'"'; if (!empty($class)) { $output .= ' class="'. $class .'"'; } $output .= '>'. theme('menu_item_link', $menu_item['link']) .'</li>'."\n"; }
Как я понял, код самого текста ссылки получается вот здесь:
$output .= '>'. theme('menu_item_link', $menu_item['link']);
Однако, поскольку я php владею ооочень поверхностно, я не понимаю, что это за theme('menu_item_link', $menu_item['link']), и как его изменить (да, я пытался разобраться в API - но только больше запутался).
Поэтому обращаюсь с вопросом:
можно ли только средствами темизации (не модифицируя файлы самого друпала) изменить код, возвращаемый этим выражением, и как это сделать?
Насколько смог, попытался разобраться сам. Похоже, что это то ли какая-то процедура, то ли функция - но где она находится и как её изменить файлами tpl.php - простите, не знаю.
- Lex-DRL's blog
- Для комментирования войдите или зарегистрируйтесь
Отчаянные времена требуют отчаянных мер. Даже не верится, что залез так глубоко...
Насколько я разобрался, в данном коде ссылка формируется за счёт обращения к функции theme_menu_item_link, которая может быть перекрыта аналогичной phptemplate_menu_item_link в файле template.php темы.
Однако такое решение нехорошо - т.к. искомый код будет добавлен вообще ко всем менюхам на сайте, а не только к нужной. Стал копать дальше.
Выяснил, что при обращении к функции theme_menu_item_link в качестве аргумента передаётся массив. Стало быть, мы можем перекрыть саму функцию модуля superfish, чтобы отправляемая в качестве текста ссылки переменная уже имела всю "обёртку" тегами span. В template.php вставляю изменённую функцию:
function phptemplate_superfish_build($id, $menu, $depth = -1, $trail = NULL) { ... $menu_item['link']['title'] = '<span class="back"><span class="hover"></span></span><span class="text">' . $menu_item['link']['title'] . '</span><span class="front"></span>'; ... }
Сделал. Даже получилось. Однако все пункты меню Superfish стали в качестве текста ссылки выдавать то, что по идее должно обрабатываться как код внутри тега < a >. Посмотрел на итоговый html - все символы открывающей и закрывающей скобок в добавленной "обёртке" заменены на их HTML-коды.
Похоже на то, что это дело где-то прогоняется через фильтр ввода, потому что когда попробовал поменять в функции theme_menu_item_link - primary и secondary links, которые вызываются из темы напрямую, отобразились нормально.
Теперь загвоздка в следующем: как можно изменить фильтр ввода для не-php блоков (тех, которые предоставляются модулями)? Тут уж сам не смог найти - как ни искал.
- Для комментирования войдите или зарегистрируйтесь
Ночь почти не спал... зато получилось.
Сделал по аналогии с этим (вместо вызова функции menu_item_link() обращаюсь напрямую к l() ).
Вот код, вставляемый в template.php (для Superfish 6.x-1.3)
// Override theme_superfish_build function provided by Superfish module. function phptemplate_superfish_build($id, $menu, $depth = -1, $trail = NULL) { $output = ''; foreach ($menu as $menu_item) { $mlid = $menu_item['link']['mlid']; if ($menu_item['link']['hidden'] == 0) { if ($trail && in_array($mlid, $trail)) { $class = ' active-trail'; } // Wrap necessary span code around anchor text. $menu_item['link']['title'] = '<span class="back"><span class="hover"></span></span><span class="text">' . check_plain($menu_item['link']['title']) . '</span><span class="front"></span>'; // Define $menu_item['link'] array as that which contains HTML code. $menu_item['link']['html'] = TRUE; if ((!empty($menu_item['link']['has_children'])) && (!empty($menu_item['below'])) && $depth != 0) { $children = theme('superfish_build', $id, $menu_item['below'], $depth, $trail); $parent_class = $children ? 'menuparent ' : ''; $output .= '<li id="menu-'. $mlid .'-'. $id .'"'; if (!empty($parent_class) || !empty($class)) { $output .= ' class="'. $parent_class . $class .'"'; } /* Generate menu link using core l() function directly instead of theme('menu_item_link', $menu_item['link']) to prevent converting "<" and ">" characters to their HTML code. */ $output .= '>'. l($menu_item['link']['title'], $menu_item['link']['href'], $menu_item['link']); if ($menu_item['link']['depth'] <= $depth || $depth == -1) { if ($children) { $output .= "<ul>\n $children \n</ul>\n"; } } $output .= "</li>\n"; } else { $output .= '<li id="menu-'. $mlid .'-'. $id .'"'; if (!empty($class)) { $output .= ' class="'. $class .'"'; } // The same replacing with l() function one more time. $output .= '>'. l($menu_item['link']['title'], $menu_item['link']['href'], $menu_item['link']) .'</li>'."\n"; } } } return $output; }
P.S.: Похоже, что за эти 2 дня я освоил столько инфы, сколько, наверное, за последние полгода не перерабатывал. Надеюсь, мой опыт пригодится.
P.P.S.: указания на кривость кода приветствуются! Попутный вопрос: в чём разница в перекрывании функции через phptemplate_функция и МояТема_функция?
- Для комментирования войдите или зарегистрируйтесь
О, спасибо, что расписал весь процесс познания, понял теперь что такое хуки и зачем они нужны. Об этом почему-то никто нигде не пишет.
- Для комментирования войдите или зарегистрируйтесь
Благодаря тому, что я не забил на полурешённую проблему, и идентичную issue открыл к модулю на друпал.орге, теперь надобность в этом хуке отпала: автор сделал интерфейс к этому хуку, я подправил кой-какой баг, и в версии 1.6 модуль уже может вставлять кастомный код "из коробки".
Можно сказать, что это какой-никакой, но мой первый contribution. :)
P.S.: Вообще, автор молодец. После того, как я обратил его внимание на решение моей частной проблемы, он сам в новой версии не только закопипастил решение, но и добавил несколько других фич, имеющих отношение к темизации: зебра, первый/последний, id...
- Для комментирования войдите или зарегистрируйтесь



Комментарии