« Making MenuTrails Work with Views 2 in Drupal 6.x
» Enable Keyword-Search Within a View

Drupal, Programming

Full Menu Tree with Active Trail in Drupal 6

04.27.09 | 12 Comments

One of the issues I wrestled with in building websites with Drupal was how difficult it seemed to access the entire menu tree in your page template. There are several modules available that people use to “solve” this issue, but at the cost of overcomplexity and one specific feature: knowing which menu item is active or in the active trail.

At first I wrote some code to make it work, until I discovered I was duplicating code already present in Drupal. So in the end the solution turned out to be extremely simple as it is based on a small tweak in the menu_tree() function.

The code below generates a nested unsorted list (UL) which you can style in any way you like. You should be able to paste the code in any template.php file and see it working by calling print menu_tree_full(’primary-links’);.

<?php

function menu_tree_full($menu_name = 'navigation') {
  static $menu_output = array();

  if (!isset($menu_output[$menu_name])) {
    $tree = menu_tree_all_data($menu_name); // This is the tweak!
    $menu_output[$menu_name] = menu_tree_output($tree);
  }
  return $menu_output[$menu_name];
}

The problem with this is that it doesn’t really tell us the active trail to the menu; it shows which menu leafs are expanded, but if you have other branches expanded by default (in menu administration), then it’s not obvious how we can tell which is which using CSS. The next code fixes that by adding active and active-trail to the LI classes. It includes a slightly modified menu_tree_full().

function menu_tree_full($menu_name = 'navigation') {
  static $menu_output = array();

  if (!isset($menu_output[$menu_name])) {
    $tree = menu_find_active_trail(menu_tree_all_data($menu_name));
    $menu_output[$menu_name] = menu_tree_output($tree);
  }
  return $menu_output[$menu_name];
}

/**
 * Wrapper function
 */
function menu_find_active_trail(&$menu_tree) {
  $item = menu_get_item();
  _menu_find_active_trail($menu_tree, $item);
  return $menu_tree;
}
/**
 * Recursive function to find the active menu and the active trail in the given tree.
 */
function _menu_find_active_trail(&$menu_tree, $item) {
  $level_is_expanded = FALSE;
  foreach($menu_tree as &$menu_item) {
    $link = &$menu_item['link'];
    if ($link['href']==$item['href']) { // Found the exact location in the tree
      $link['active'] = TRUE;
      $link['in_active_trail'] = TRUE;
      return true;
    } else {
      if ($link['has_children']) {
        $result = _menu_find_active_trail($menu_item['below'], $item);
        $link['in_active_trail'] = $result;
        if ($result) $level_is_expanded = TRUE;
      }
    }
  }
  return $level_is_expanded;
}

12 Comments

have your say

You can skip to the end and leave a response. Pinging is currently not allowed.

Be nice. Keep it clean. Stay on topic. No spam.

You can use these tags:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

:

:


« Making MenuTrails Work with Views 2 in Drupal 6.x
» Enable Keyword-Search Within a View