Earlier today I was looking for a way to make the top primary link have both an "active" class and a "first" class. I'm using Nice Menus and Drupal 5.3. I needed this because IE was giving me a stubborn 6 pixel jog that couldn't be fixed any other way. I thought it would be helpful if I posted my solution in case it is helpful to anyone else. But before I post my solution I would like to apologize for not linking to the several posts that contributed to this code working. Normally I would give credit where credit is due, but it's the end of the day and I'm ready for a beer. If your code contributed to this success, thank you, and I hope this can help another...

Post this in your template.php:

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 = '') {

  $item = menu_get_item($mid); // get current menu item



  // decide whether to add the active class to this menu item

  if ((drupal_get_normal_path($item['path']) == $_GET['q']) // if menu item path...

  || (drupal_is_front_page() && $item['path'] == '<front>')) { // or front page...

    $active_class = ' active'; // set active class

  } else { // otherwise...

    $active_class = ''; // do nothing

  }



  return '<li class="'. ($leaf ? 'leaf' : ($children ? 'expanded' : 'collapsed')) . ($extraclass ? ' ' . $extraclass : '') . $active_class .'">'. menu_item_link($mid, TRUE, $extraclass) . $children ."</li>\n";
}

Sincerely,
Adam Hegi
http://www.primalmedia.com

Comments

primalmedia’s picture

This code works well even if you aren't using Nice Menus ;)

codevoice’s picture

Thanks primalmedia for posting this. It works for me, but I see it being applied to the primary menu, not the nicemenus menu. I have nicemenus set to use the Primary Links, but to no avail.

Would you mind sharing what version of nicemenus you are using with this code?

TamboWeb’s picture

Hello there,

I am currently using nice menus on a new Drupal site. The "first" and "last" classes do not get added to menus generated by the Nice Menus module. I am new to drupal and do not yet command the the level of expertise with this CMS package. However, I am committed to use it in various site implementations.

So far, I have been able to determine that the "First" and "Last" classes need to be coded in the Nice Menu Loop that generates the li elements. This loop is located in the nice_menu.module file. From my initial observations, this loop needs to be recoded with some conditional statements.

Once I find a solution for this feature, I will post it for other to use. If you have a solution please let us know.

Thanks.

stevebayerin’s picture

Is there a way to get the same in Drupal 6.

Insert first and last classes into the primary menu items generated by nice menus for Drupal 6.

The code above doesn't seem to work in Drupal 6.

TamboWeb’s picture

Hello Steve,

I was able to add first and last classes to the "nice Menu" UL list. The code presented at top of this thread ("template.php") did nothing in Drupal 5.x.

Instead, I had to modify the code in the module itself (nice_menus.module). To add the first and last classes, I had to add a conditional statement, about three lines of code. I have not posted the code here as I am still new to Drupal and I do not want to pollute any module with my code as I know it is very important to this community to maintain clean code and modularity. However, if you are interested just send me a PM and I will send you the code I have. I am sure it will work just the same in Drupal 6.

Sandro.

stevebayerin’s picture

Hi Sandro,

Since my code review skills aren't quite up to snuff, I think its best to post the code here where more well versed code reviewers can see what can be done to improve it or stablize it.

TamboWeb’s picture

look in the nice.menu.module file for this function:

"function theme_nice_menu_tree($pid = 1, $menu = NULL) "

then replace the whole function with this updated function code:

function theme_nice_menu_tree($pid = 1, $menu = NULL) {
  $menu = isset($menu) ? $menu : menu_get_menu();
  $output['content'] = '';
  $output['subject'] = $menu['items'][$pid]['title'];

  if ($menu['visible'][$pid]['children']) {
    // Build class name based on menu path 
    // e.g. to give each menu item individual style.
		$mycount = 1;
    foreach ($menu['visible'][$pid]['children'] as $mid) {  
		

      // Strip funny symbols
      $clean_path = str_replace(array('http://', '<', '>', '&', '=', '?', ':'), '', $menu['items'][$mid]['path']);
      // Convert slashes to dashes
      $clean_path = str_replace('/', '-', $clean_path);
      $path_class = 'menu-path-'. $clean_path;
			$num_children = count($menu['visible'][$pid]['children']);/// added by sandro.
      if (count($menu['visible'][$mid]['children']) > 0) {
			  $output['content'] .= '<li id="menu-'. $mid .'" class="menuparent '. $path_class .'">'. menu_item_link($mid);
        $output['content'] .= '<ul>';
        $tmp = theme('nice_menu_tree', $mid);
        $output['content'] .= $tmp['content'];
        $output['content'] .= "</ul>\n";
        $output['content'] .= "</li>\n";
      }
      else {
				//if ($mycount == 1) {
				//$output['content'] .= '<li>This is the first count:</li>';
				//}
				$extraclass = $mycount == 1 ? 'first' : ($mycount == $num_children ? 'last' : '');
				$extraclass .= $num_children == 1 ? ' last' : '';
				//if ($mycount == ($num_children)) {
				//$output['content'] .= '<li>This is the last count:' . $mycount . '</li>';
				//}

        $output['content'] .= '<li id="menu-'. $mid .'" class="'. $path_class . ' ' . $extraclass .'">'. menu_item_link($mid) .'</li>'."\n";
      }
					$mycount ++; // added by sandro.

    }
  }
  return $output;
}

I commented out about six lines of code within the else statement of the foreach loop and added three of my own. Be sure to make a back up copy of your .module file just in case. Also keep in mind that this was tested with drupal 5.3. All this does is add a "first" and "last" classes to the list. These classes need to be styled in the css file.

P.S. Sorry for getting back to this post so late.