Identify DOM element of navigation item in drupal

This article explains how to modify Drupal system to enable identification of every element in Navigation menu.

This may be used to do some additional work in JavaScript or just add more personalization to menu items through CSS.

The code for the menu item with submenu looks by default like this:

<li class="expand">
  <a href="/link_to_menu_item">Menu item name</a>
  <ul class="menu">
    <li class="leaf">
      <a href="/link_to_submenu_item">Submenu item title</a>
    </li>
    <!-- more submenu items -->
  </ul>
</li>

It is created by two functions defined in file includes/menu.inctheme_menu_item (li) and theme_menu_item_link (a).

Because Drupal 5.x provides very functional theme coding support there is no need to change any of its PHP functions. It is just enough to edit appropriate theme file and in there define replacement functions.

Depending of template code functions may be found in themes/yourthe­me/yourtheme.the­me or themes/yourthe­me/template.php and they will be called yourtheme_menu­_item or phptemplate_me­nu_item. (Just change „yourtheme“ to your real theme name).

The best way to add unique information is to use an XHTML id attribute. It is useful to identify both – li and a tags. Let's say li id attribute will start with „li_“ and a's one – with „a_“.

function yourtheme_menu_item($mid, $children = '', $leaf = TRUE) {
  $item = menu_get_item($mid);
  $link_item = $item;
  while ($link_item['type'] & MENU_LINKS_TO_PARENT) {
    $link_item = menu_get_item($link_item['pid']);
  }
  $link = '';
  return '<li id="li_' . str_replace('/','_',$link_item['path']) . '_' . str_replace(' ','_',$item['title']) . '" class="'. ($leaf ? 'leaf' : ($children ? 'expanded' : 'collapsed')) .'">'. menu_item_link($mid) . $children ."</li>\n";
}
function yourtheme_menu_item_link($item, $link_item) {
  return l(
    $item['title'],
    $link_item['path'],
    array(
      'title' => !empty($item['description']) ? $item['description'] : '',
      'id' => 'a_' . str_replace('/','_',$link_item['path']) . '_' . str_replace(' ','_',$item['title'])
    ),
    isset($item['query']) ? $item['query'] : NULL);
}

The functions above will create such code:

<li id="li_node_5_Menu_item_name" class="expanded">
  <a id="a_node_5_Menu_item_name" title="" href="/link_to_menu_item">Menu item name</a>
  <ul class="menu">
    <li id="li_link_to_submenu_item_Submenu_item_name" class="leaf">
      <a id="a_link_to_submenu_item_Submenu_item_name" title="" href="/link_to_submenu_item">Submenu item name</a>
    </li>
    <!-- more submenu items -->
  </ul>
</li>

Now it is possible to change elements style with simple CSS:

#li_node_5_Menu_item_name a { color: red }
#a_node_5_Menu_item_name { color: green }

This solution is not perfect – the str_replace functions should use more sophisticated method to remove not wanted characters. If you will create it – feel free to drop me a note. You may always use the $mid variable, but it's just a number and will create something like id=‚li_34‘.

Digg the story

Trackback URL for this post:

http://piotr.zalewa.info/trackback/24