If you're like me, you use Drupal 5.x, use Nice Menu's and really, really, really want to have Icons, additional Hyperlinks and a bit of HTML formatted description text in your Nice Menu's.
Well after a week of work .. mostly CSS formatting .. I do and thought I would share it.
You can view the finished product at www.3xlogic.com so you can understand what I am talking about.
The first thing I need to say is that this is not a module solution. It probably could be turned into a module rather simply by doing the required coding with an override to theme_menu_item_link in the template.php. I am new to Drupal so not quite familiar with how to do this just yet.
The second thing I need to say is that I customized the function theme_nice_menu_tree in the Nice Menu's module, nice_menus.module. This is another, and probably more direct method, that this functionality could be turned into a module because I believe this also can be overridden.
By editing the Nice Menu's module I can no longer apply any updates to Nice Menu's unless I also edit each update. However, considering the age of 5.x I doubt there will be many updates.
I am sharing what I did because I could not find the information I needed and my questions went unanswered as you can see here: http://drupal.org/node/460610.
Here are the basics of how this was accomplished:
1) How the menu link are built by default.
By default Nice Menu's uses it's function theme_nice_menu_tree to build the list items, li's that make up each menu item. It builds the anchor tag inside the menu li y calling the system function menu_item_link which wraps the url you entered in the menu admin page in anchor tags.
$output['content'] .= '<li id="menu-'. $mid .'" class="'. $path_class .'">'. menu_item_link($mid) .'</li>'."\n";
2) Editing the Nice Menu's Module (nice_menus.module)
a) I needed additional containers inside of the list item to hold the icon image and also the description text. I did it by adding a div with a class="m-in-l", and a div with the class"m-in-r" on each side of the normal anchor tag. When looking at the code above and below, the part that say's menu_item_link($mid) is where the hyperlink anchor tag you normally get is generated. Below you can see I simply add the additional containers on the left and right of that tag.
$output['content'] .= '<li id="menu-'. $mid .'" class="'. $path_class .'">' . '<div class="m-outer" id="m-outer-' . $mid . '"><div class="m-in-l" id="m-in-l-' . $mid . '"></div><div class="m-in-r" id="m-in-r-' . $mid . '">' . menu_item_link($mid) . '<div class="m-desc" id="m-desc-' . $mid . '">' . c_menu_item_description($mid) . '</div></div></div>' . '</li>'."\n";
b) You will notice that I also added an ID to each div with the unique Menu-Id-Number ($mid) so that I could reference specific items through CSS if needed, which was for the first level.
c) The function called c_menu_item_description is a custom function I wrote which returns the text (including html tags) from the description field of a menu item. You can see this below the Title when you are editing a menu item in admin. The function simply takes the menu id and returns everything from the description field including html tags and places it inside of the m-in-r div.
d) Here's the complete new Nice Menu's function. Notice there are two lines with my edits since one is for menuparent list items and one is for non-menuparent list items. Menuparent are menu items that have sub menus.
3) Editing the template.php file
a) Since I wanted to get the description text from my menu item, I needed a custom function to retrieve it. The nice thing about the description field is that you can enter html into it and it is not cleaned up so you can render it right to the screen. Be aware however that there is a length limit as to how many characters you can enter in the description field. I am sure this could be changed somewhere but I haven't looked yet.
b) Adding a new function was easy .. you just inssert it in the template.php, call it from somewhere else .. and it works. Nice.
function c_menu_item_description($mid) {
$item = menu_get_item($mid);
$descrip = '';
$descrip = $item['description'];
return $descrip;
}c) All my function does is use the menu id to get the array of info for one menu item using the drupal function menu_get_item. I then extract the description text from the array using $item['description'], pass it to my variable $descrip and return it. Easy huh?
4) How about that image?
a) If you are wondering where we are going to get the image from, it is by using the background image properties which can be set with CSS.
b) If you are wondering why I didn't simply apply the background image to the actual original menu item container it is because menuparent items already have a little arrow image applied to the background to signify a sub menu, so I needed my own container for the icon.
5) The CSS. Oww.
a) Yeah .. the CSS was a headbanger but I have it all working for my site. I need to spend many hours cleaning it up to get rid of redundant stuff and I still need to test IE compatibility .. specifically IE6 and it may require some additional trickery.
b) The basics are to get your new elements to be where you want, to get everything the size you want, and to hide stuff you don't want showing.
c) On the first horizontal row I didn't want any icons or descriptions so I hid them like this:
#block-nice_menus-1 li ul li.menuparent a.m-desc { background: none; }
#block-nice_menus-1 li a#m-desc-189 {display:none !important;}
#block-nice_menus-1 li div#m-desc-189 {display:none !important;}You have to explicitly hide the containers for each top-level menu item. This is where my ID tags came in handy so I could select just those items.
d) Next I needed to apply the background image to my m-in-l div. Again each item has to individually have it's icon applied as such:
#block-nice_menus-1 li ul li div#m-in-l-136 { background: #fff url(images/menu/management.gif) center center no-repeat;}
Of course there was much, much, much more CSS needed to make everything the size I wanted with the behavior I wanted but you can see that on the live site with Firebug or Web Developer.
That's basically it. Let me know what you think.
Dave
Comments
=-=
great write up, should be a handbook page attched to the nice menus section.
the end product is slick.
Menu description(title) showing on hover in Firefox - FIXED
Thanks for the comments VeryM. How do I add it to the handbook?
If you use Nice Menu's you've noticed that in certain browsers it will display the anchor tag's 'Title' when you hover over the menu item (like a tool tip). This was more of an annoyance than a real problem, although sometimes it could cause your menu to close unexpectedly if your mouse gets over the tool tip element.
With the changes I've made to Nice Menu's to allow the menu's description field to show in the menu, I've started adding a lot more stuff to the menu's description field including HTML. This caused the undesirable effect of showing all of this html and extended description text in the hover tool tip .. so I had to turn it off.
In order to do this I used a patch found here: http://drupal.org/node/247904 The patch adds two new functions to the nice_menus.module which replace the system calls to menu_item_link and theme_menu_item_link which are the functions Nice Menu's calls to build the anchor tag for your main menu link. NOTE: The patch function nice_menus_item_link should actually be nice_menu_item_link since that's the one we are calling.
I didn't apply the patch directly, but simply added the two new functions and then edited my already edited theme_nice_menu-tree function to call these replacement functions instead of the system functions. Here's the relevant portions of the nice_menus.module with original, my edits, and patch applied for completeness.
+- = First edits/additions (only two), to get the icon & description functionality.
+ = Second edits/additions to remove the hover tooltip.
=-=
How do I add it to the handbook?
you click on create content in your drupal.org navigation menu and use the book page content type.
IE7 Bugs - Cleaning Up
So now that I am adding HTML to the description tags and using my new menu's I am trying to work out a few bugs. The first two I solved, but still working on the third.
1) On IE7 no text at all showed up on the menu's. I guess IE7 doesn't like block elements not having a height and it gets all weird. So setting an explicit height fixes it as follows:
But I only wanted to present this (and other IE7 fixes) to IE7 browsers only so I included this in my page.tpl.php file:
I already had one for IE6 so figured I'd just do the same even if there ends up being crossover. I then created an ie7.css and put it in my theme directory with the bug fix code above.
Bug 2 was where the description text was running outside of the div container instead of wrapping. For some reason this fixed it. Go figure.
BUG 3 The last and most troubling bug I am still working on as that I am putting anchor tags in my Menu Description which now shows up in my menu which is great, but it's not respecting the inline nature of the anchor tag and it is stacking them. I tried making adding the following:
and a bunch of other stuff. I got the elements to at least move around a bit off the left margin, but something is still pushing them down .. been messing with margin stuff .. but ..
Anyways, here's a picture of what's happening. If anyone has any ideas I would sure welcome it. You can see how it all goes together at www.3xlogic.com.
umm .. how do I attach files? Oh well .. here is the screen shot: http://www.3xlogic.com/files/inline_error.jpg
Dave
Added to the Nice Menu's Handbook
This has all been rewritten and added to the Nice Menu's Handbook.
http://drupal.org/node/470558
Dave
is there any way to apply this to drupal 6.13?
Hi,
very interesting, so I like to use this version of nice menu within my site...
But what should I do to convert this to drupal 6.13 (the version I use)?????
I' ve tried to adapt this to 6 for some days now but without success. All starts with differences of the versions, e.g. that there isn't a menu_item_link call in 6.
The theme_menu_item_link call is different either. cause in 6 there isn't a call of $link_item within this one....
Aren't there any user who have translated this one to 6 now?
Any help would be appreciated!
Cheers,
Here's what I've done so far...
I've done all the conversions from http://drupal.org/node/470558 and this is what I got:
"Fatal error: Cannot use string offset as an array in ...\sites\all\themes\MYTHEME\template.php on line 208"
In line 208 I find the following:
$output['subject'] = check_plain($menu['items'][$pid]['title']);
When I change the function name from phptemplate_nice_menu_tree to MYTHEME_nice_menu_tree and vice versa without clearing the sites cache I can see my site without showing the nice menu but showing the following warning:
"warning: call_user_func_array() [function.call-user-func-array]: First argument is expected to be a valid callback, 'ninefiftyrobots_nice_menu_tree' was given in ...\includes\theme.inc on line 617."
After clearing the cache I get the "Fatal error: Cannot use string offset as an array in ...\sites\all\themes\MYTHEME\template.php on line 208" again.
So where to start?
Is it possible?
Please help...
What I've done in the meantime - part 2
Now I've changed the 2 output strings in the template php:
and altered the function c_menu_item_description to:
To report the good news: I don't get a fatal error anymore
Here's what I can see so far (unfortunately I' not allowed to post pics...). The nice menu now shows up and works as normal.
There are 2 additional menu parent items on the first position with the following code (firebug):
Seems that the divs have benn called as supposed but not within my menu structure, cause my "normal" parent menu points look as follows:
As you can see there aren't any div calls within the menu structure....
Any idea what has to be modified?
Any help would be much appreciated...
Check out this other thread
Ingo,
Check out this other thread: http://drupal.org/node/460610
I think under version 6 your output should look more like this, but I have not tested it on 6.
On that same thread Maluco Marinero left a new function for getting the description text, but again I have not tested this either:
If you get a Version 6 working please post your results. Thanks - Dave
Dave, thans a lot for your
Dave, thans a lot for your reply.
I'll try to get this to work...
Best regards,
Ingo
It works now but...
Got this finally to work.
The div's are called in a right way and HTML-description works within all levels.
But at the moment I only got the test.gif (displayed within all menus) working properly.....
Your code to add specific icons to the menu's
doesn't seem to work at all and I still haven't any idea why????
I tried to replace the # with ".", left it allone, deleted the"-" in front of the menuID, replaced this one and many more. Nothing works....
What I'm missing???
Can you
Can you paste the HTML from your page? Do a view source and copy the part that shows the menu html.
Of course :-) <div
Of course :-)
Thanks a lot for helping!!!!!
Seems that my m-in-l div's
Seems that my m-in-l div's have no id at all!?!?!
First I called them with
Now I tried with
No luck either...
Yes, you have no menu id's
Yes, you have no menu id's so it would appear $mlid is not returning the menu ID.
Without really diving into this, I think you might want to take another look at Maluco Marinero's post. It seems he accomplished this by overriding D6 Nice Menu's theme_nice_menu_build.
(http://drupalcontrib.org/api/drupal/contributions--nice_menus--nice_menu...)
Note also that that function is deprecated and replaced by theme_nice_menus_build().
Maluco's post at http://drupal.org/node/460610#comment-1723406
Also note that # in CSS is used to select an object id and the . is used to select an object by class such as
<div id="myid" class="menu-123">In css #myid would select this div as well as .menu-123 would do the same thing.
In my example I am using classes and ID's such as
class="m-i-r" id="m-i-r-289"so that every item in the menu can be reached by CSS ... individually (using ID's) or by class to format many items at once exactly the same. An ID can only apply to a single object and therefore must be unique to each object, while a class can be applied to many objects.Hmmm...
There is one thing I simply don't understand.
When I inspect the menu with Devel Themer Info, I can see clearly that that the li id is contributed by mlid.
Within every single menu item one found mlid which holds the menu id.... and that's no surprise!
Otherwise the nice menu couldn't display the right menu item with the correct title and menucaption...
So why this doesn't work with the included div containers?
I really don't see another way to put the right id# in.... What the heck I have overlooked?
Victorious at the end!
Oh my goodness..... It's always the same old story...
The source of errors is sitting in front of the monitor... and after a neverending search for the reason of the malfunction he would like to kick himself... grrrr
I wrote $lmid instead of $mlid. This way it couldn't work...
Now all is working fine.
To sum things up so far...
To implement Dave's modifications of nice menu to Drupal 6 simply do the following:
1. Copy the entire theme_nice_menu_build function from the nice_menus.module in YOURTHEME.template and change the "theme_" part of the function name to "phptemplate_".
2. Take his (dnieweg) div calls and the code additions from Maluco Marinero and melt them into this file.
What you should get is the following:
And that's it so far. Dave's custom function that gets the description text from the menu item is dispensable and therefore doesn't needs to be changed, cause Maluco Marinero's code segment does the same.
The rest will be css...
Now I'll try to position the hole thing to the right place within the header of my modified ninesixtyrobots theme and will have a look if I could kick in some superfish code....
Thanks a million Dave for your help :-)