Set active menu trail CSS selectors - backport to 6.x-1.3
Mark B - May 18, 2009 - 09:51
| Project: | Nice Menus |
| Version: | 6.x-1.3 |
| Component: | Code |
| Category: | feature request |
| Priority: | normal |
| Assigned: | Unassigned |
| Status: | reviewed & tested by the community |
Description
I really need the active trail classes to be applied to my menus, as discussed in 219804, but I don't want to use the dev branch of the module for a production site. Issue 219804 includes a patch for 6.x-2.x (http://drupal.org/node/219804#comment-1131533) which I've backported to 6.x-1.3

#1
#2
Thank you! I'll drop a msg if I run across any problems with this patch.
The site I'm using this for will be going up in a week or two and this is one of the few issues left. Thanks!
#3
This is exactly what I needed for a couple of sites that I'm getting ready to launch. I was even considering launching them with the 2.x dev version of nice_menus installed just for this capability, which is just bad form.
I applied the patch successfully on one of my simpler D6 sites. I'll try it out on my larger almost-launched sites and let you know if I have any problems.
Many thanks to you and add1sun!
#4
Mark, this is strange. I've applied the patch - but nothing changes. everything works as it did. cleared all caches and saved the modules page, but nothing. I would expect it not to work if something was wrong - not to work as it did before the patch ;)
Clues...?
I'll play around some more...
#5
Ok found it...
This patch successfully adds an 'active' class to menuparents - but not to menu items which are not parents.
To fix, i added these line:
<?php+ // check if this item is in the active trail
+ if ($trail && in_array($mlid, $trail)) {
+ $trail_class = 'active-trail ';
+ }
+ else {
+ $trail_class = '';
+ }
?>
again just before the second output in the file, which after applying the patch above becomes line 365, so the function now looks as such:
<?php
function theme_nice_menu_build($menu, $trail) {
$output = '';
foreach ($menu as $menu_item) {
$mlid = $menu_item['link']['mlid'];
// Check to see if it is a visible menu item.
if ($menu_item['link']['hidden'] == 0) {
// Build class name based on menu path
// e.g. to give each menu item individual style.
// Strip funny symbols.
$clean_path = str_replace(array('http://', '<', '>', '&', '=', '?', ':'), '', $menu_item['link']['href']);
// Convert slashes to dashes.
$clean_path = str_replace('/', '-', $clean_path);
$path_class = 'menu-path-'. $clean_path;
// If it has children build a nice little tree under it.
if ((!empty($menu_item['link']['has_children'])) && (!empty($menu_item['below']))) {
// Keep passing children into the function 'til we get them all.
$children = theme('nice_menu_build', $menu_item['below'], $trail);
// Set the class to parent only of children are displayed.
$parent_class = $children ? 'menuparent ' : '';
// check if this item is in the active trail
if ($trail && in_array($mlid, $trail)) {
$trail_class = 'active ';
}
else {
$trail_class = '';
}
$output .= '<li id="menu-'. $mlid .'" class="'. $parent_class . $trail_class . $path_class .'">'. theme('menu_item_link', $menu_item['link']);
// Build the child UL only if children are displayed for the user.
if ($children) {
$output .= '<ul>';
$output .= $children;
$output .= "</ul>\n";
}
$output .= "</li>\n";
}
else {
if ($trail && in_array($mlid, $trail)) {
$trail_class = 'active ';
}
else {
$trail_class = '';
}
$output .= '<li id="menu-'. $mlid .'" class="'. $trail_class . $path_class .'">'. theme('menu_item_link', $menu_item['link']) .'</li>'."\n";
}
}
}
return $output;
}
?>
#6
For anyone wondering, the change made in #5 by asak is included in the patch in #1.
This works fine for me. Thank you asak and Mark B!
#7
Thanks a lot for this patch, I was surprised this wasn't included in the module.
Contrary to #6's comment, when I just patched using #1 it was still only setting the active class on menu items that were parents / had submenu items. I had to replace the entire function with the function from #5 to get it to work for menu items that didnt have any children.
Thanks again everybody!
#8
For my use, I didn't need the additional change added in #5 because on non menuparent items, we still have the active class on the anchor tag itself, and I'm targeting the anchor tag anyway. This might explain why some users didn't need this.
#9
I have to apologize in advance, I don't really know the correct way to comment on this. :-)
I had to add the $trail_class to the final output to get it to work, otherwise, the info in #5 doesn't ever use it:
Old line:
$output .= '<li id="menu-'. $mlid .'" class="'. $path_class .'">'. theme('menu_item_link', $menu_item['link']) .'</li>'."\n";New line:
$output .= '<li id="menu-'. $mlid .'" class="'. $trail_class . $path_class .'">'. theme('menu_item_link', $menu_item['link']) .'</li>'."\n";There seems to be a discrepency between what's in the patch and what's in #5. but when I added the first part of #5 and then also the updated output line to the patched code from #1, it worked for me.
#10
this needs an updated patch then
#11
The patch above and the changes in #5 (and #9) are working fine for me.
I've created a patch. Please review and hopefully commit it to the next stable 6.x-1.4 release. Thanks.
#12
Wonderfful ! I was exactly looking for this for many weeks. Thanx :)
#13
i gather other people have successfully gotten these patches to work, but i tried both tonight and neither one worked for me.
1st patch resulted in entire menu disappearing completely.
2nd patch resulted in no visible change to existing menus.
i think i am doing it correctly, but i'm no whiz at patching.
i get no hunk fails. looks to patch correctly. i checked the physical file and the changes appear to have been made (though I didn't examine every single line).
am using cygwin on windows vista 64 machine.
perhaps i will just upgrade to the dev version.
#14
Thanks for the patch ositoblanco. It works great. Hope to see it in 6.x-1.4.
#15
tried again. worked!!
i'm a patching newbie, so must have done something wrong in earlier attempt.
#16
Great patch, works wonderfully! even when using in one's own theme's template.php doing some overrides.
#17
just looking a bit more, it seems that it does not work when items are more than one level deep.
Example 1:
Example 2:
Example 1 displays the proper active trails when the bolded item is active, but example 2 does not display correct active trails when the bolded menu item is active.
#18
might be a CSS issue. i had to fiddle with mine to get it to work properly at each level, but now it does. i have 3 level menus like you.
you can look at mine in case that helps: http://www.aboutcallingcards.com/callingcard-review
as with other nice_menu css, it was a bit of a project to get it exactly right.
#19
I doubt it would be a css issue as the active-trail and active classes are output via php.
#20
oh, you are saying the classes are simply not present to style against. i misunderstood.
#21
It is however interesting that your site seems to be outputting the classes. It may have to do with some sort of difference between placing the theme function within one's template.php file or not. I have it in my template.php so that I could add an extra span to each link.
#22
i simply patched the module. perhaps try that to see if it works? putting it in template.php is well beyond my technical know how, so can't help you there.
#23
well, I applied the patch to my module already. Then I copied out the modified/patched theme function and put it in my template.php. It doesn't seem to be working correctly when doing that.
#24
Works fine for me. I suspect something else is interfering with your active trail, nicholas. =/
Are you overriding any of the theme functions in template.php of your theme, by any chance? Could have old copies sticking in there?
Setting back to R&TBC, since it works for amogiz, VladRM, John and it works for me.
#25
Can anyone confirm that the menuitems show "activetrail" classes when the "active" menuitem is two levels deep? Like my previous example:
Example 1 (works, all classes show within my links properly):
Example 2 (doesn't work, active-trail classes are not shown on any parents):
#26
@nicholas.alipaz I can confirm Example 2 works for me. I'm going to load that on to our client preview server later - I'll send you a link via the contact form so you can see for yourself. Your problem is very strange... I don't have it at all. =/
#27
likewise, #2 works for me -- as you saw on the link i gave you earlier.
i am not clear if, at this point, you have installed only the module -- or are still making modifications to template.php, as well. and i'm sure you've tried clearing caches and so forth to ensure you are seeing the thing clean. otherwise, no idea.
#28
I am actually using this modified theme function, but don't really expect any help on it, since it has been pretty heavily modified. This is in my theme's template.php
BTW, wouldn't it be better if the theme function we have here did more like what I have done in my theme function?
classes[] = ....instead of concatenating them together as a string as we go along?<?phpfunction mytheme_nice_menu_build($menu, $trail) {
$output = ''; //the output menu
$i = 0; //the indexed menuitem
$c = 0; //the total count of menuitems
// find out the count for the non-disabled links
foreach ($menu as $menu_count) {
if ($menu_count['link']['hidden'] == 0) {
$c++;
}
}
foreach ($menu as $menu_item) {
$mlid = $menu_item['link']['mlid'];
$classes = array();
// Check to see if it is a visible menu item.
if ($menu_item['link']['hidden'] == 0) {
$i++;
// setup first/last/even/odd/active classes
$classes[] = ($i == 1) ? 'first' : '';
$classes[] = ($i == $c) ? 'last' : '';
$classes[] = ($i % 2 == 0) ? 'even' : 'odd';
$classes[] = (preg_match("/class=\"active\"/", theme('menu_item_link', $menu_item['link']))) ? 'active' : '';
$classes[] = 'menu-path-'. mytheme_id_safe($menu_item['link']['href']);
// If it has children build a nice little tree under it.
if ((!empty($menu_item['link']['has_children'])) && (!empty($menu_item['below']))) {
// Keep passing children into the function 'til we get them all.
$children = mytheme_nice_menu_build($menu_item['below'], $trail);
// Set the class to parent only of children are displayed.
$classes[] = $children ? 'menuparent' : '';
// check if this item is in the active trail
if ($trail && in_array($mlid, $trail)) {
$classes[] = 'active-trail';
}
else {
$classes[] = '';
}
}
else {
// check if this item is in the active trail
if ($trail && in_array($mlid, $trail)) {
$classes[] = 'active-trail';
}
else {
$classes[] = '';
}
}
$classes = array_filter($classes);
$classes = implode(' ', $classes);
$output .= '<li id="menu-'. $mlid .'" class="'. $classes .'"><span>'. theme('menu_item_link', $menu_item['link']) .'</span>';
// Build the child UL only if children are displayed for the user.
if ((!empty($menu_item['link']['has_children'])) && (!empty($menu_item['below']))) {
if ($children) {
$output .= '<ul>';
$output .= $children;
$output .= "</ul>\n";
}
}
$output .= "</li>\n";
}
}
return $output;
}
?>