I modified theme_nice_menu_build function to add leaf, first, last classes to menu items.

I need to create submenus with 2 and 3 columns, so i add some extra classes to child ul and li.

Comments

jjemmett’s picture

Thanks for the patch, I needed the first/last classes for my theme.

One thing I don't understand is why do you use the following logic?

$col_count = ceil( count($menu) / 7 );

and

$child_col_count = ceil( count($menu_item['below']) / 7 );

What significance does '7' have?

add1sun’s picture

Title:add class to items» add first and last class to items

Setting better title. @jjemmett that was their code for making columns, which isn't something that would go into NM.

mdupont’s picture

Hello,

What would this patch need to go into NM?

mdupont’s picture

StatusFileSize
new2 KB

Based on the original, here is a patch with the columns code removed. It is made against the latest 6.x-2.x-dev (Feb 7). It's incomplete since the .last class doesn't seem to be applied to the last first level item, but at least .first works ^^

mdupont’s picture

StatusFileSize
new2.11 KB

Forget the comment above, .last class is correctly applied, but only if you have no disabled menu entry in a given level.

So here attached is a rough working version that can be used.

mdupont’s picture

Status:Needs work» Needs review
mdupont’s picture

Since I've issued it, I have no trouble using Nice Menus patched with the above. Can someone confirm if it's working well?

jpdaut’s picture

vince

This is exactly what I need but I am using 5.x. Would you have written this patch for 5.x also by any chance?

redhatmatt’s picture

Same here, need 5.x version. I will try and make a patch later if no one already has one... not an immediate need for me, just would be nice to have while I am building the custom look.

mdupont’s picture

I'll try to make a 5.x version these days.

mdupont’s picture

Assigned:tikaszvince» mdupont
StatusFileSize
new1.99 KB

OK, here is a quick patch I made against the latest D5 stable version and it seems to work. I'd really like that someone reviews this one as well as the D6 one.
I think I can assign this issue to me since vince.tikasz hasn't made an answer since August.

mdupont’s picture

Still nobody to review these two patches (the one at #11 and the one at #5)?

mdupont’s picture

Now that the column code is removed, would these patches be good enough to go into NM?

TravisCarden’s picture

Subscribing. (Hoping for a backport to 6.1.)

add1sun’s picture

Status:Needs review» Postponed (maintainer needs more info)

Another issue with first/last as well as odd/even. Is this useful? How does that patch compare to this one? Please continue this discussion in this thread so we have one place to talk about it.

#403772: add 'first', 'odd', 'even' to listing

mdupont’s picture

Status:Postponed (maintainer needs more info)» Needs review
StatusFileSize
new2.08 KB

The patch from #403772: add 'first', 'odd', 'even' to listing is more concise and adds some useful classes as well; it may be better to use this one.
I have hacked in the support for 'last' and moved the code into the "if ($menu_item['link']['hidden'] == 0) {" block, so the classes will display correctly even if you have hidden items in the menu. Given my PHP skills it is likely not to be pretty code, but it seems to work. The patch was made against the brand new 6.x-2.x-dev release from today. Feel free to improve it!

Jolidog’s picture

StatusFileSize
new2.12 KB

Works great for me the patch from #16.

But I have a sugestion, the first item should also receive the odd class since there might be designers interested in the first/last class and others interested in the odd/even class.

Here is a modified patch, also I added a space next to every new class name, like it's used on code already present in the module, for example:

$parent_class = $children ? 'menuparent ' : '';

so that the output is clean of spaces:

$output .= '<li id="menu-'. $mlid .'" class="'. $path_class . $first_class . $oddeven_class . $last_class .'">'. theme('menu_item_link', $menu_item['link']) .'</li>'."\n";

This is for the DEV release from 26 of March 2009

CKIDOW’s picture

Title:add first and last class to items» "active-trail" Class

What about the "active-trail" class? Before applying the patch there was the active-trail class. But now it's gone. Any suggestions? :)

CKIDOW’s picture

Title:"active-trail" Class» add first and last class to items

sorry... didn't wanted to change the title :(

Jolidog’s picture

I'll try to find out if I changed anything that might have affected the active trail.

Jolidog’s picture

StatusFileSize
new2.47 KB
Jolidog’s picture

Found the problem!

mdupont patch was a mix between his and djkim patch, along the way, the $class got lost from the output preventing the active trail from being added.

Above is version 4 of this patch that fixes this. $class is back, and $parent_class is gone since it wasn't used anymore.

Please report back so we can change this issue status to reviewed and tested by the comunity.

Thank you!

PS: I has doing some back and forth with firefox and I guess that's why the text wasn't posted with the patch, so another post was required.

datawench’s picture

I'd like to note that the patch given in #21, while apparently meant for version 2, works for me in 6.x-1.3.

mdupont’s picture

Status:Needs review» Reviewed & tested by the community

Worked great for me.

nstrassner’s picture

Mmm. tried to patch 6x-1.3 and got 4 hunk errors. Would not patch!

Jolidog’s picture

I made it against the dev release from 26 of March, perhaps datawench in #23 patched it manually...

mdupont’s picture

StatusFileSize
new2.42 KB

Note : although the patch in #23 is for 6.x-2.x-dev from March 26th, it applies cleanly on the latest (May 7th) dev version.

mdupont’s picture

StatusFileSize
new1.9 KB

For a 6.x-1.x backport version, try this one (untested, but should work as the code is almost the same).

nstrassner’s picture

mdupont,
Yes! That puppy did it. Thanks so much!

vivianspencer’s picture

subscribing

alisonjo2786’s picture

#21 was PERFECT for me, thank you thank you Jolidog and everyone who made this happen!! you're all lifesavers!!

osopolar’s picture

I don't like to patch modules if it's not necessary. The patch in #21 applies only to a theme function and so you can override it in your template.php by adding this function (its mostly the same as the patch in #21):

<?php
/**
 * Helper function that builds the nested lists of a nice menu.
 *
 * @param $menu
 *   Menu array from which to build the nested lists.
 */
function THEME-NAME_nice_menu_build($menu, $trail) {
 
$output = '';
 
$index = 0;
 
$count = 0;
  foreach (
$menu as $menu_count) {
    if (
$menu_count['link']['hidden'] == 0) {
     
$count++;
    }
  }

  foreach (
$menu as $menu_item) {
   
$mlid = $menu_item['link']['mlid'];
   
// Check to see if it is a visible menu item.
   
if ($menu_item['link']['hidden'] == 0) {
     
//prepare marking of li tag as odd, even, first or last
     
$index++;
     
$first_class = $index == 1 ? ' first ' : '';
     
$oddeven_class = $index % 2 == 0 ? ' even' : ' odd';
     
$last_class = $index == $count ? ' last ' : '';
     
     
// Build class name based on menu path
      // e.g. to give each menu item individual style.
      // Strip funny symbols.
     
$clean_path = str_replace(array('http://', '<', '>', '&', '=', '?', ':'), '', $menu_item['link']['href']);
     
// Convert slashes to dashes.
     
$clean_path = str_replace('/', '-', $clean_path);
     
$path_class = 'menu-path-'. $clean_path;
     
// If it has children build a nice little tree under it.
     
if ((!empty($menu_item['link']['has_children'])) && (!empty($menu_item['below']))) {
       
// Keep passing children into the function 'til we get them all.
       
$children = theme('nice_menu_build', $menu_item['below'], $trail);
       
// Set the class to parent only of children are displayed.
       
$parent_class = $children ? 'menuparent ' : '';
       
// check if this item is in the active trail
       
if ($trail && in_array($mlid, $trail)) {
         
$trail_class = 'active-trail ';
        }
        else {
         
$trail_class = '';
        }
       
$output .= '<li id="menu-'. $mlid .'" class="'. $parent_class . $trail_class . $path_class . $first_class . $last_class . $oddeven_class .'">'. theme('menu_item_link', $menu_item['link']);
       
// Build the child UL only if children are displayed for the user.
       
if ($children) {
         
$output .= '<ul>';
         
$output .= $children;
         
$output .= "</ul>\n";
        }
       
$output .= "</li>\n";
      }
      else {
       
// check if this item is in the active trail
       
if ($trail && in_array($mlid, $trail)) {
         
$trail_class = 'active-trail ';
        }
        else {
         
$trail_class = '';
        }
       
$output .= '<li id="menu-'. $mlid .'" class="'. $trail_class . $path_class . $first_class . $last_class . $oddeven_class .'">'. theme('menu_item_link', $menu_item['link']) .'</li>'."\n";
      }
    }
  }
  return
$output;
}
?>

[edit]
sorry, this is not correct, see #44 and 45.

jsimonis’s picture

I tried this, but get the following error:

warning: Missing argument 2 for theme_nice_menu_build() in /var/www/username/sites/themes/theme/template.php on line 7.

jsimonis’s picture

Ok, I realized I had the wrong version. I upgraded to the dev version and made the template.php change. I refreshed, cleared cache, etc. No change.

jsimonis’s picture

Tried patching mine, but I just got errors and all of the changes were skipped.

Would someone be able to post the working version?

osopolar’s picture

Sorry, I have overlooked that the patches above are for 6.x-2.x-dev, I wrote the theme override for the template.php in #32 for nice menus version 6.x-1.3 ... and its working well. I don't to change the version of this issue ... it's just a solution for 6.x-1.3 (so there is no need to backport it from HEAD). Please report if the template solution works or don't work.

@jsimonis what's your theme name (is it really theme)? I am not sure if you can call your theme "theme" because this may redeclare all theme-functions you want to overwrite in template.php. What is the name of your THEME-NAME_nice_menu_build($menu, $trail) function?

jsimonis’s picture

No, I really did have a theme name in the places where it asked. I just removed that personal info from the file and inputted "theme" where my theme name actually was located.

I originally tried using your solution since it was for the version we were using. When that didn't work, I did the upgrade and then tried the patch. That didn't work either.

But since then the client has decided to go with a custom created drop down menu so that they get complete control over everything in it.

RockSoup’s picture

I am using 6x-1.3 on and I am getting an error with the theme function (from #32) when I override in template.php

my theme name is aha and the error is:

warning: Missing argument 2 for aha_nice_menu_build() in C:\xampp\htdocs\aha\sites\all\themes\aha\template.php on line 259.

here is the function name from my template.php file:

function aha_nice_menu_build($menu, $trail) {}

Thanks in advance for any help.

RockSoup’s picture

Ok, I played with this and I think I have it working, here is what I came up with(replace the "THEME-NAME" with the name of your theme and place this in your template.php file):

<?php
/**
 * Helper function that builds the nested lists of a Nice menu.
 *
 * @param $menu
 *   Menu array from which to build the nested lists.
 * @param $depth
 *   The number of children levels to display. Use -1 to display all children
 *   and use 0 to display no children.
 * @param $trail
 *   An array of parent menu items.
 */
function THEME_NAME_nice_menus_build($menu, $depth = -1, $trail = NULL) {
 
$output = '';
 
$index = 0;
 
$count = 0;
  foreach (
$menu as $menu_count) {
    if (
$menu_count['link']['hidden'] == 0) {
     
$count++;
    }
  }
   
  foreach (
$menu as $menu_item) {
   
$mlid = $menu_item['link']['mlid'];
   
// Check to see if it is a visible menu item.
   
if ($menu_item['link']['hidden'] == 0) {
     
//prepare marking of li tag as odd, even, first or last
     
$index++;
     
$first_class = $index == 1 ? ' first ' : '';
     
$oddeven_class = $index % 2 == 0 ? ' even' : ' odd';
     
$last_class = $index == $count ? ' last ' : '';
       
     
// Build class name based on menu path
      // e.g. to give each menu item individual style.
      // Strip funny symbols.
     
$clean_path = str_replace(array('http://', 'www', '<', '>', '&', '=', '?', ':'), '', $menu_item['link']['href']);
     
// Convert slashes to dashes.
     
$clean_path = str_replace('/', '-', $clean_path);
     
$class = 'menu-path-'. $clean_path;
      if (
$trail && in_array($mlid, $trail)) {
       
$class .= ' active-trail';
      }
     
// If it has children build a nice little tree under it.
     
if ((!empty($menu_item['link']['has_children'])) && (!empty($menu_item['below'])) && $depth != 0) {
       
// Keep passing children into the function 'til we get them all.
       
$children = theme('nice_menus_build', $menu_item['below'], $depth, $trail);
       
// Set the class to parent only of children are displayed.
       
$parent_class = $children ? 'menuparent ' : '';
       
$output .= '<li id="menu-'. $mlid .'" class="'. $parent_class . $class . $trail_class . $path_class . $first_class . $last_class . $oddeven_class .'">'. theme('menu_item_link', $menu_item['link']);
       
// Check our depth parameters.
       
if ($menu_item['link']['depth'] <= $depth || $depth == -1) {
         
// Build the child UL only if children are displayed for the user.
         
if ($children) {
           
$output .= '<ul>';
           
$output .= $children;
           
$output .= "</ul>\n";
          }
        }
       
$output .= "</li>\n";
      }
      else {
       
$output .= '<li id="menu-'. $mlid .'" class="'. $class . $trail_class . $path_class . $first_class . $last_class . $oddeven_class .'">'. theme('menu_item_link', $menu_item['link']) .'</li>'."\n";
      }
    }
  }
  return
$output;
}
?>

Basically, I took the

<?php function theme_nice_menus_build($menu, $depth = -1, $trail = NULL) {}
?>

that starts around line 390 of the 6.x-2.x-dev version I just downloaded and overrode it.

I am getting the excellent active classes as well as first and last which is all a themer like me can ask for. w00t!

edit to mention, that I am using menu trails for my menu as the nodes I need the active class on are not actually in the menu system.

bcobin’s picture

I'd wanted this for some time and just decided to go a-hunting today and found this post. Works great! Thank you SO much, RockSoup - the Drupal community rocks!

MadtownLems’s picture

I really want/need this functionality, but can't make it work.

I added the code from #39 to my template.php, and renamed it:

function zen_nice_menus_build($menu, $depth = -1, $trail = NULL) {

but it's not adding first or last classes anywhere in my primary links drop down nice menu as I expected.

Can you think of what I might be missing or doing wrong? It seems to have no effect.

thanks!

RockSoup’s picture

Is the name of your theme zen? If you are using a sub theme(which you should be since Zen is a base theme) then you should add the name of your theme at the beginning of the function.

zen_nice_menus_build($menu, $depth = -1, $trail = NULL) {

should be:

subthemename_nice_menus_build($menu, $depth = -1, $trail = NULL) {

does that make sense? one way to try it out would be to add the function to the garland template.php like:

garland_nice_menus_build($menu, $depth = -1, $trail = NULL) {

and switch themes to garland and see if the classes are appearing, then you will know if it is just a naming issue.

osopolar’s picture

You should carefully check the version you are using. RockSoup is right with his solution for the current dev version (as this thread is about). As I explained in #36 I overwrote the theme in #32 for the 6.x.1.3 version.

for any doubts check the function in nice_menus.module:
6.x-1.3: function theme_nice_menu_build($menu, $trail)
6.x-2.x-dev: function theme_nice_menus_build($menu, $depth = -1, $trail = NULL)

[edit] sorry, in 6.x-1.3 it's just: function theme_nice_menu_build($menu) (see #45).

morningtime’s picture

@#43: your solutions from #32 really doesnt work for 6.x-1.3, the error as mentioned is Missing argument 2 for phptemplate_nice_menu_build() in template.php on line 119

The solutions is to change the function to:

function phptemplate_nice_menu_build($menu, $trail = null) {

So make it $trail = null.

How come it did work for you? Amazing.

osopolar’s picture

oops, sorry for the confusion. I double-checked the module function theme_nice_menu_build I use and the one from the module I have downloaded again ... I noticed that my function is theme_nice_menu_build($menu, $trail) so I guess I have changed it accidentally.

@44 (mxistence ) is your solution working well? I didn't know that the overwritten function can have a more parameters than the original one theme_nice_menu_build($menu) vs. theme_nice_menu_build($menu, $trail = NULL).

remaye’s picture

Hi
I used the code of #32 (for D6.x-1.3) modified with #44
and it's running well regarding the first/last/odd/even tags
but ... my menu sub-items have all disappered ! (only the first level is displayed)
does anybody experience the same ?
or did I miss something (I'm not Drupal expert).

Thanks.

Well, sorry, finally it works fine ... I had mix #32 and #39 code for some unknown reason...
Thanks everybody for this very helpfull thread !

Danny Englander’s picture

I can confirm #39 works for me with 6.x-2.x-dev, on a zen sub theme. I substituted in my sub theme name for the code function 'THEME_NAME_nice_menus_build'.

I am now getting first, last, odd, even classes. This will be good as I have different background images for last and sometimes the last item in the menu will change depending on the role of the user.

greg.harvey’s picture

#32 works for the 6.x-1.3 package, but drop $trail - it shouldn't be there for 6.x-1.3.

RobLoach’s picture

Version:6.x-2.x-dev» 6.x-1.x-dev
Priority:Normal» Critical
StatusFileSize
new1.9 KB

This is the patchthat works from mdupont up there. Let's fix it in the module instead of fixing it in the theme.

Standart’s picture

Title:add first and last class to items» add classes 'first', 'last', 'even', 'odd'
Version:6.x-1.x-dev» 6.x-2.x-dev
Assigned:mdupont» Unassigned
Priority:Critical» Normal
Status:Reviewed & tested by the community» Needs review
StatusFileSize
new2.22 KB

let's do this in 2.x-dev first, backporting later.

Here's an updated patch which does not remove the new classes from #219804: Set active menu trail CSS selectors.

RobLoach’s picture

Status:Needs review» Reviewed & tested by the community
+    //prepare marking of li tag as odd, even, first or last

........... Punctuation and sentence casing would be nice to have. But we just really need this in.

Jolidog’s picture

StatusFileSize
new2.14 KB

Punctuations and sentence casing correction.

Standart’s picture

I'm using this patch on an site and it works as expected.

jcmarco’s picture

StatusFileSize
new1.96 KB

The patch works great.
There is only a buzz of 2 lines in the hunk #1.
Re-rolled again.

avner’s picture

Version:6.x-2.x-dev» 6.x-1.3
Status:Reviewed & tested by the community» Active

Adding multilingualism support

problem is that nice_menus will show all lang's menu item, same issue goes for this patch
personally i prefer not to touch the module so i used this function in the template.php
Note: This function is tested for 6.x-1.3 but i see no reason why it should not work for 6.x-2x as well

<?php
function theme_nice_menu_build($menu) {

  global
$language;

 
$output = '';
 
/* according to http://drupal.org/node/301247#comment-1497198 */
 
$index = 0;
 
$count = 0;
 
//count only if item is not hidden and is same as page language
 
foreach ($menu as $menu_count) {
    if ( (
$menu_count['link']['hidden'] == 0) && ($menu_count['link']['localized_options']['langcode'] == $language->language) ) {
     
$count++;
    }
  }
var_dump($count);
  global
$language;

  foreach (
$menu as $menu_item) {
   
$mlid = $menu_item['link']['mlid'];
   
// Check to see if it is a visible menu item.
   
if ($menu_item['link']['hidden'] == 0) {
     
//check page language and render the menu only item if same as page language
     
if ( $menu_item['link']['localized_options']['langcode'] == $language->language ){
       
//prepare marking of li tag as odd, even, first or last
       
$index++;
       
$first_class = $index == 1 ? ' first ' : '';
       
$oddeven_class = $index % 2 == 0 ? ' even' : ' odd';
       
$last_class = $index == $count ? ' last ' : '';

       
// Build class name based on menu path
        // e.g. to give each menu item individual style.
        // Strip funny symbols.
       
$clean_path = str_replace(array('http://', 'www', '<', '>', '&', '=', '?', ':'), '', $menu_item['link']['href']);
       
// Convert slashes to dashes.
       
$clean_path = str_replace('/', '-', $clean_path);
       
$class = 'menu-path-'. $clean_path;
        if (
$trail && in_array($mlid, $trail)) {
         
$class .= ' active-trail';
        }
       
// If it has children build a nice little tree under it.
       
if ((!empty($menu_item['link']['has_children'])) && (!empty($menu_item['below'])) && $depth != 0) {
         
// Keep passing children into the function 'til we get them all.
         
$children = theme('nice_menus_build', $menu_item['below'], $depth, $trail);
         
// Set the class to parent only of children are displayed.
         
$parent_class = $children ? 'menuparent ' : '';
         
$output .= '<li id="menu-'. $mlid .'" class="'. $parent_class . $class . $trail_class . $path_class . $first_class . $last_class . $oddeven_class .'">'. theme('menu_item_link', $menu_item['link']);
         
// Check our depth parameters.
         
if ($menu_item['link']['depth'] <= $depth || $depth == -1) {
           
// Build the child UL only if children are displayed for the user.
           
if ($children) {
             
$output .= '<ul>';
             
$output .= $children;
             
$output .= "</ul>\n";
            }
          }
         
$output .= "</li>\n";
        }
        else {
         
$output .= '<li id="menu-'. $mlid .'" class="'. $class . $trail_class . $path_class . $first_class . $last_class . $oddeven_class .'">'. theme('menu_item_link', $menu_item['link']) .'</li>'."\n";
        }
      }
    }
  }
  return
$output;
}
?>

hope this helps

avner’s picture

I am a newbie here,
dont know why the

Version: 6.x-2.x-dev » 6.x-1.3
Status: reviewed & tested by the community » active

was added, hope it doesnt cause any one problems
would appreciate it if anyone can correct it

jcmarco’s picture

Version:6.x-1.3» 6.x-2.x-dev
Status:Active» Reviewed & tested by the community

Hi Avner, that seems to be a new nice feature that could be in a new issue

avner’s picture

done
Please refer to http://drupal.org/node/742502
the code i entered here is a bit buggy please refer to the code in the new issue i posted

add1sun’s picture

Status:Reviewed & tested by the community» Fixed

OK, little bit of commenting and I removed the $path_class variable since that is no longer used (it got incorporated into the $class var a while ago). Committed to HEAD (*not* in Alpha 1). I won't backport this 1.x since the idea is for 2.x to become the standard stable version (soon hopefully).

RobLoach’s picture

Status:Fixed» Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.