Great Menu Theme with url_alias based Section, First, Last, & Active Classes

aferra - December 7, 2007 - 06:32

Hi Folks,

Lately I've been struggling with the concept of a url_alias aware menu theme that would apply a class I could hook onto so menu's can be styled when sub sections are active.

For example, you have an item in Menu A (probably your sites high level navigation) that has a link pointing to '/about/main' and Menu B with several items pointing to url_aliases beginning with '/about/' (i.e. '/about/services', '/about/contact', etc) but, you want the Menu A item to exhibit it's active style while you browse the other Menu B items that begin with '/about/'.

I got it working today and I thought the code would be handy. Many thanks to the folks who wrote the indispensable code which generates the 'active', 'first' and 'last' classes. It all works quite well together.

FYI, it works whether you have clean_urls enabled or not.

function phptemplate_menu_tree($pid = 1) {
  if ($tree = phptemplate_menu_tree_improved($pid)) {
    return "\n<ul class=\"menu\">\n". $tree ."\n</ul>\n";
  }
}

function phptemplate_menu_tree_improved($pid = 1) {
  $menu = menu_get_menu();
  $output = '';

  if (isset($menu['visible'][$pid]) && $menu['visible'][$pid]['children']) {
    $num_children = count($menu['visible'][$pid]['children']);
    for ($i=0; $i < $num_children; ++$i) {
      $mid = $menu['visible'][$pid]['children'][$i];
      $type = isset($menu['visible'][$mid]['type']) ? $menu['visible'][$mid]['type'] : NULL;
      $children = isset($menu['visible'][$mid]['children']) ? $menu['visible'][$mid]['children'] : NULL;
      $extraclass = $i == 0 ? 'first' : ($i == $num_children-1 ? 'last' : '');
      $output .= theme('menu_item', $mid, menu_in_active_trail($mid) || ($type & MENU_EXPANDED) ? theme('menu_tree', $mid) : '', count($children) == 0, $extraclass);    
    }
  }

  return $output;
}

function phptemplate_menu_item($mid, $children = '', $leaf = TRUE, $extraclass = '') {

// Build the full menu URI for comparison to request URI
global $base_path;
$item = menu_get_item($mid);
$clean_urls_enabled = variable_get('clean_url', 0);
if ($clean_urls_enabled) {
$item_path = $base_path.drupal_get_path_alias($item['path']);
} else {
$item_path = $base_path.'?q='.drupal_get_path_alias($item['path']);
}

// Get Request URI
$current_path = $_SERVER['REQUEST_URI'];

// Break Down the Menu Item
$item_path_chunks = explode('/', $item_path);
$item_page = array_pop($item_path_chunks);
$item_path = implode('/', $item_path_chunks);

// Break Down the Request URI
$current_path_chunks = explode('/', $current_path);
$current_page = array_pop($current_path_chunks);
$current_path = implode('/', $current_path_chunks);

// Build The Class for the Menu List Item
$classes = array();
if ($item_path == $current_path) {
$classes[] = 'section';
}
if ($children) {
$classes[] = 'expanded';
} else {
$classes[] = 'collapsed';
}
if ($extraclass) {
$classes[] = $extraclass;
}
$class_string = implode(' ', $classes);

return '<li class="'.$class_string.'">'. menu_item_link($mid, TRUE, $extraclass) . $children ."</li>\n";
}

?>

Lemme know if there's anything about it that doesn't make sense or if you have any suggests about the implementation.

Best.

extraclasses?

vthirteen - December 12, 2007 - 13:01

thank you for sharing this!
could you please explain how you got it working?
i inserted the php functions in my template.php but i don't get the extraclasses printed.

Thanks!

rickvug - December 14, 2007 - 08:17

Thanks for sharing this snippet, I'll have to try it on an upcoming project. Really, I think that this should be the default behavior but that's another issue.

 
 

Drupal is a registered trademark of Dries Buytaert.