Download & Extend

add classes 'first', 'last', 'even', 'odd'

Project:Nice Menus
Version:6.x-2.x-dev
Component:Code
Category:feature request
Priority:normal
Assigned:Unassigned
Status:closed (fixed)

Issue Summary

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.

AttachmentSize
nice_menus.module.patch2.73 KB

Comments

#1

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?

#2

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.

#3

Hello,

What would this patch need to go into NM?

#4

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 ^^

AttachmentSize
"clean" patch 2 KB

#5

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.

AttachmentSize
nice_menus.module.r2.patch 2.11 KB

#6

Status:needs work» needs review

#7

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

#8

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?

#9

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.

#10

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

#11

Assigned to:tikaszvince» mdupont

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.

AttachmentSize
nice_menus-extra_classes-d5-r1.patch 1.99 KB

#12

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

#13

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

#14

Subscribing. (Hoping for a backport to 6.1.)

#15

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

#16

Status:postponed (maintainer needs more info)» needs review

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!

AttachmentSize
nice_menus_listingposition_r2.patch 2.08 KB

#17

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

AttachmentSize
nice_menus_listingposition_r3.patch 2.12 KB

#18

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? :)

#19

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

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

#20

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

#21

AttachmentSize
nice_menus_listingposition_r4.patch 2.47 KB

#22

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.

#23

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.

#24

Status:needs review» reviewed & tested by the community

Worked great for me.

#25

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

#26

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

#27

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.

#28

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

AttachmentSize
6.x-1.x backport 1.9 KB

#29

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

#30

subscribing

#31

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

#32

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.

#33

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.

#34

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.

#35

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

Would someone be able to post the working version?

#36

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?

#37

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.

#38

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.

#39

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.

#40

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!

#41

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!

#42

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.

#43

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).

#44

@#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.

#45

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).

#46

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 !

#47

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.

#48

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

#49

Version:6.x-2.x-dev» 6.x-1.x-dev
Priority:normal» critical

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

AttachmentSize
nice_menus_listingposition_6.x-1.x_backport_r1_0.patch 1.9 KB

#50

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
Priority:critical» normal
Assigned to:mdupont» Anonymous
Status:reviewed & tested by the community» needs review

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.

AttachmentSize
classes.patch 2.22 KB

#51

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.

#52

Punctuations and sentence casing correction.

AttachmentSize
classes.patch 2.14 KB

#53

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

#54

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

AttachmentSize
classes.patch 1.96 KB

#55

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 <a href="http://drupal.org/node/301247#comment-1497198" title="http://drupal.org/node/301247#comment-1497198" rel="nofollow">http://drupal.org/node/301247#comment-1497198</a> */
 
$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

#56

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

#57

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

#58

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

#59

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).

#60

#61

Status:fixed» closed (fixed)

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

nobody click here