Add unique class to menu items

Last modified: January 24, 2009 - 09:39

There are many times that I prefer to css my menus using individual classes. I am very happy with the results I get with this snippet in Drupal 6:

<?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;
  }
  if (
$in_active_trail) {
   
$class .= ' active-trail';
  }
 
  if (!empty(
$link)) {
           
// remove all HTML tags and make everything lowercase
           
$css_id = strtolower(strip_tags($link));
           
// remove colons and anything past colons
           
if (strpos($css_id, ':')) $css_id = substr ($css_id, 0, strpos($css_id, ':'));
           
// Preserve alphanumerics, everything else goes away
           
$pattern = '/[^a-z]+/ ';
           
$css_id = preg_replace($pattern, '', $css_id);
           
$class .= ' '. $css_id;
    }
    return
'<li class="'. $class .'">'. $link . $menu ."</li>\n";
}
?>

Which provides me with great themable output in the form of:

<li class="leaf myaccount"><a href="/user/1">My account</a></li>
<li class="leaf nodelocations"><a href="/map/node">Node locations</a></li>

Remove after colon? Unique ID? Performance?

David Stosik - December 11, 2008 - 16:00

Hello,
Why do you

<?php
// remove colons and anything past colons
if (strpos($css_id, ':')) $css_id = substr ($css_id, 0, strpos($css_id, ':'));
?>
?

Does that mean that, if I create a menu item which label is, say, "News: all news", the css_id will only be news?

I have two another remarks:
Don't you think this technique is a performance leak, when many menu items are displayed?

This technique doesn't assure the CSS id will be unique, as many menu items can have identical label.

By the way, thank you for this snippet I will use until I find better. ;)

David

Getting it more usable would be GREAT!!

webthingee - December 11, 2008 - 18:21

I have had a tough time finding something that works in Drupal 6 and as a themer, I rely on this awesome community to help with the php. Figured i'd get the ball rolling. I am hoping that some of the master coders in the community will "enhance" it. I would really like if the menu css was the $mid, but I have been unsuccessful in creating that function in the last 24 hours or so.

(repeat class names) By using classes, I have been using the ID or Class of the container to achieve specific theming for specific menu items.

(individual menu's only) I believe there is a solution here http://www.jakob-persson.com/node/535, and/or here http://programmingbulls.com/drupal-how-theme-menu to make them menu specific, haven't figured it out yet.

Another option I have been looking at is:

<?php
function YourThemeName_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;
  }
  if (
$in_active_trail) {
   
$class .= ' active-trail';
  }
 
$id = preg_replace("/[^a-zA-Z0-9]/", "", strip_tags($link));
  return
'<li id="'.$id.'" class="'. $class .'">'. $link . $menu ."</li>\n";
}
?>

from http://drupal.org/node/67457#comment-864218

ideas, help, and improvements are very welcomed!!!

Add IDs only for one ore more special menu?

aaki - March 25, 2009 - 17:42

If I do so as mentioned, all the links in all the menues all over my page are rendered by this function. but i only need the id's in special cases. Is there a chance to do a more specific override? Like:

function themename_menu__primary_links_menu_item($link, $has_children, $menu = '', $in_active_trail = FALSE, $extra_class = NULL) {
...
}

And BTW whats up with that $extra_class?

Issue created

Darren Oh - May 28, 2009 - 19:20

I created issue 475734 to discuss this.

Awesome!

loydbrahn - May 6, 2009 - 13:48

This is exactly what I was looking for. Thanks!

 
 

Drupal is a registered trademark of Dries Buytaert.