Discover cascadingStyle

Drupal Primary Menus with Better Active Trail

Sometimes you are using Drupal's built in Primary and Secondary menus and you'd really like that primary menu item to stay "active" on a secondary page. Drupal's default behavior for the primary links is to add classes along the entire "active trail" of the primary links menu with classes such as this:

menu-1-2-1-active

This is great, but if you already have made an "active" class for your nav elements, there would be a lot of style repitition to apply it also to all of your active trail classes, not to mention you'd need to add a new style definition anytime you added something to your menu. Not fun. Luckily, it's simple to override the default Primary links theming code to add the class "active" to all links in your active trail!

Add this snippet to your theme's template.php: (this is for Drupal 5.x)

function phptemplate_menu_primary_links($start_level = 1, $pid = 0) {
  if (!module_exists('menu')) {
    return NULL;
  }
  if (!$pid) {
    $pid = variable_get('menu_primary_menu', 0);
  }
  if (!$pid) {
    return NULL;
  }
  if ($start_level < 1) {
    $start_level = 1;
  }
  if ($start_level > 1) {
    $trail = _menu_get_active_trail_in_submenu($pid);
    if (!$trail) {
      return NULL;
    }
    else {
      $pid = $trail[$start_level - 1];
    }
  }
  $menu = menu_get_menu();
  $links = array();
  if ($pid && is_array($menu['visible'][$pid]) && isset($menu['visible'][$pid]['children'])) {
    $count = 1;
    foreach ($menu['visible'][$pid]['children'] as $cid) {
      $index = "menu-$start_level-$count-$pid";
      if (menu_in_active_trail_in_submenu($cid, $pid)) {
        $index .= "-active active";
      }
      $links[$index] = menu_item_link($cid, FALSE);
      $count++;
    }
  }
  // Special case - provide link to admin/build/menu if primary links is empty.
  if (empty($links) && $start_level == 1 && $pid == variable_get('menu_primary_menu', 0) && user_access('administer menu')) {
    $links['1-1'] = array(
      'title' => t('Edit primary links'),
      'href' => 'admin/build/menu'
    );
  }
  return $links;
}

The key part is the change right here:

      if (menu_in_active_trail_in_submenu($cid, $pid)) {
        $index .= "-active active";
      }

While most certainly not the only way to add the active class to your menu trails (I tried the Menutrails module but couldn't seem to get it working in any reasonable amount of time) and only works in the primary/secondary links metaphor, it's a quick fix to a common problem.

Hi there im having this very

Hi there im having this very issue in drupal 6, things have really changed around this..

Iv been doing a bit of reading here is the link to all the stuff i have found http://drupal.org/node/243156 . If you have this working for D6 would you be so kind as to let me know.

Thanks.

Hi, I can't get this to work

Hi, I can't get this to work - I've put the snippet in my template.php file, but I'm not clear about what to do with the style sheet.

I've tried

.active {
text-decoration: underline;
}

and

.menu-active {
text-decoration: underline;
}

but none of them work. Which is the right class?

I'm impressed with your

I'm impressed with your approach to problem solving.
Nice drupal theme snippet, thanks.

I tried to get a patch into

I tried to get a patch into Drupal 6 that would address this issue, but it was deferred to Drupal 7. I am not happy about this, so I marked it (I think properly) as wontfix for Drupal 6. If Drupal 7 is as different as many have mentioned, I think the entire approach will be different.

In all events, all such hacks add unnecessary overhead and complexity to your app, simply because Drupal strips out the relevant information before it is delivered to the theme. Bummer.

Hi, this looks great - the

Hi,

this looks great - the second great snippet I've come across today! Any chance you could make the code available as a text file though? It's quite a messy cut & paste job from the above :)

Thanks!

--Nik

Nik, Try it again - I've

Nik,

Try it again - I've disabled line numbering, which will make it quite non-messy to copy and use in your own site.