A Practical Tutorial on Drupal's Menu System

In this tutorial, I will explain how to generate custom menus that are fully controlled from the menu administration page. (path: [www.yourdrupalsite.com]admin/menu). These menus can be enormously useful. The can be used for everything from custom user interfaces, to navigation menus. In addition, since they are hooked into Drupal's core, they can be dynamically updated.

In writing this tutorial, I've assumed that the reader already understands to some extent:

  • Drupal Themes
  • How to copy and paste
  • The value of attempting something for the first time. 

theme_menu_tree() = your new best friend

Alright, we're going to call a php function. O, non-php programmers do not flee in horror. PHP is easy, unless you're paying me, in which case its very difficult.

Now open up, your theme's page.tpl.php file. If you don't know where that is, its in themes/box_grey/page.tpl.php. Find the part of the page that you want to insert the new menu. Have you found it? Copy and paste this code into it:

<?php $menuhtml = theme_menu_tree(666);print $menuhtml;?>

As you, dear reader may have noticed, our menu's number is 666! I, for one, don't want to call Satan with our PHP function, so we're going to have to find a new number. As it so happens, you already have a whole set of numbers to choose from.

In your user menu, go to administrate->menus (the path is admin/menu). Now get the menu's number as described by the below visual aid:

drupal menu

In my visual aid's case, the menu number is 392. So we simply replace 666 with 392, a far more Christian number.

<?php $menuhtml = theme_menu_tree(392);print $menuhtml;?>

Quick note, if you just want to call your entire set of menu options insert the number 0 as opposed to whatever menu you've selected from your admin section.

Now, save the changes you've made to your page.tpl.php file. As you can see, assuming I wrote these instructions properly, and you executed them as deftly as I imagined, you now have a menu that is controlled from your menu adminsitration page. Add some new menu items, or create a new menu and insert in to your template. Go wild! Throw a party, and show your friends! I tell you, this trick is a great ice breaker when I'm talking to random girls in bars. And as always, if you have any problems with these instructions, leave a comment, and I'll be happy to help.

Comments

lightbox event attached to menu

I am trying to add a rel=lightbox and a class for lightbox, how would I do that?

Menu links calling ThickBox

Hello,

I have a question related with Custom menu items.

I'm trying to override the menu item link since I want to use thickbox
link there. How can I do that?

For example, I have the main menu and Menu item. So the menu item link
should be something like "a href='path' class = thickbox " How should I do it?

Now another question I have, If I create a Menu_Custom_Menu on the
Hook_menu, is the PID going to be 1? Can I have custom menus with PID = 0
implemented in the hook menu?

Thank you very much!

Add unique ID value for PHPTemplate theme_menu_item list items

Hi, if you want to add unique ids to your menu items, just put this code in your template.php file:

The function will override the built in theme_menu_item function and add the id 'menu-item-xxx' where 'xxx' is the menu item's id (mid)

<?php
/* Theme override for theme_menu_item
* Adds unique id to <li> element based on menu item id
*/

function phptemplate_menu_item($mid, $children = '', $leaf = TRUE) {
  return
'<li id="menu-item-'.$mid.'" class="'. ($leaf ? 'leaf' : ($children ? 'expanded' : 'collapsed')) .'">'. menu_item_link($mid) . $children ."</li>\n";
}
?>

regards,

DT

Drupal 5.x

Menus by Title?

While it's great to be able to do:

<?php
$menuhtml
= theme_menu_tree(666);
print
$menuhtml;
?>

sometimes you need to look up the menu id by title. Is there a function already that does this?

keep menu expanded while browsing

Hi,

I have been looking for an answer to my question for some time now. I am hoping someone here has ran into the same issue and/or has some suggestions.

I have a menu system, let's say:

-A
--a1
--a2
-B
--b1
--b2
-C
--c1
--c2

menu a1 has a view of different posts, and while you are browsing a1, the active menu is highlighted and expanded. So up to this point everything works beautifully. However, once you go and click on one of the links inside a1, the menu collapses!!!
I know I could file every item inside menu a1 at the moment of posting but since this is a site that will be used by many, I'd like to minimize the user input, hence minimizing chances of linking errors, etc.

Is there any way to have the menu expanded while browsing the content inside it?

Thanks!

Hey, I'm looking to keep the

Hey,
I'm looking to keep the menu as it was before clicking on a link.
Do you have any solution?
I'll let you know if I find something, just send me an email and I'll reply you.

cya

ferran

Great is your tutorial on Menu

I was struggling to implement a menu in the right-side bar and previously i have worked with joomla where there is no coding and i was expecting the same here to finaly i found that i have do some coding and your tutorial was wonderful, was very easy to understand and implement. Than..................ks

Great information...

Some of the elementary tasks of building a web in Drupal seem quite opaque to newcomers. Thank you for this very helpful information.

Regarding menu system in drupal

Dear Mr. Lewis,

I am coming to you in search of any guidance/ lead on doing the following task in drupal 4.7.3.
my task is now to customize a site with a login page followed by two content page.The first content page will look like http://www.penguinprogress.org/layout.PNG which will house a sitemap column where there will be various Headings like taxonomy1 taxonomy2 taxonomy3.... in the menu system. In a scenario when the user clicks taxonomy2 , the site map changes as in the picture http://www.penguinprogress.org/layout2.PNG where all the submenu of taxonomy2 (sub section 1, sub section 2, sub section 3) are displayed.

For developing such work, can any body throw a pointer of how to do it, probably a url to the tutorial is appreciated. I have googled, but other than nick lewis tutorial i cant find any thing closer. Any lead on this please..

Thanking you,

Sincerely

Thyagarajan shanmugham

It seems like

It seems like taxonomy_menu.module would do the trick for you. Maybe I'm missing something. Is your hangup where the user is redirected after logging in?

Looking to break up what theme_menu_item() returns

First of all, thank you very much Nick for the unbelievably useful and simple pointers, and for the wonderful sense of humor! :) Like Gunny's last comment above, I'm also looking to break up the parts of the link text that theme_menu_item() returns so that I can assign my own spans, etc... Specifically, I have the following code in my theme's page.tpl.php: <?php if (count($primary_links)) : ?> <div id="topnav"><div>    <?php foreach ($primary_links as $link): ?>     <span class="topnav">< span><?php print $link;?></span></span>    <?php endforeach; ?> </div></div>  <?php endif; ?> This styles my Primary Links beautifully. Unfortunately, the same doesn't work for theme_menu_item(666) because the ul and li that get returned mess with my span styles. I've tried to add styles to "span ul li" but it's just not working correctly (probably thanks to the very complicated styles that the designer handed me :) ). So I need to get rid of the "ul class=menu" and "li class=leaf" items. Any idea how I can do that? Thanks in advance for any help.

I haven't checked out the

I haven't checked out the code above.. but I did recently transform the generated menu to my new graphicky presentation and ran into similar ul/li styling problems as you. Since I want no indents, no bullets, no menu title and no stupid line under the menu ;) here's what I added to the css: #sidebar-right li.leaf {  list-style-type: none;  list-style-image: none;  padding:0;  margin: 0;}#sidebar-right h2 {display:none}#sidebar-right .block {border-bottom:0} Note that I show my menu in the sidebar-right region, so change that ID to the region you show your menu in. The reason I specify this region is because I use the sidebar-left region to display an admin menu which does use and need the indenting, bulleting, etc. Hope this helps.

Hi Nick! First of all Thanks

Hi Nick! First of all Thanks for the great tutorials and sence of humour ;) And now could you please help me to get throw my problem? I've got "Site Menu Item" (basicaly menu) -S.M.I ----About ---------sub 1 ---------sub 2 ----Contacts ---------sub 1 ---------sub 2 I did the way you are saying : <?php$menuhtml = theme_menu_tree(37);print $menuhtml;?> It render right now About section ('cause it's 37th id) Q: How can I implement in my template that this number "37" depends on arg(0)? so if site.com/about $menuhtml = theme_menu_tree(37); if site.com/contacts $menuhtml = theme_menu_tree(38); P.S. I'm really newbie to drupal and CMS at all :( Thank you in advance! Hope my explanation is clear... sorry for my english :)

this could help you

This worked for me perfectly: http://drupal.org/node/193828

I get a submenu based upon active top level menu item, dynamically without the need to specify on which pages the block can be displayed.

I figure out that rendering

I figure out that rendering menu depending on url isn't really good idea... 'cause it will not work properly if user will forget to specify url alias. right? so now i'm thinking that a better way is to use menu API? But i don't know what function to use. if you are in the about->sub1 this_magick_function() return About ID. and same way if you are in about->sub1->subsub Please, help me to figure it out.

The menu "api" leaves a lot

The menu "api" leaves a lot to be desired. In general, using theme_menu_tree($mid) is safe because it uses the menu's id ($mid), thereby making aliases irrelevent.

I'm trying to make context

I'm trying to make context sensitive menu. Maybe you can point me towards? where should I check for this function or $identifier? that will return me About or Services ID? Thanks

I figure out that rendering

I figure out that rendering menu depending on url isn't really good idea... 'cause it will not work properly if user will forget to specify url alias. right? so now i'm thinking that a better way is to use menu API? But i don't know what function to use. if you are in the about->sub1 this_magick_function() return About ID. and same way if you are in about->sub1->subsub Please, help me to figure it out.

Your funny.

"...non-php programmers do not flee in horror. PHP is easy, unless you're paying me, in which case its very difficult." Your funny. Good work. :)

how to create horizontal

how to create horizontal menu bar which is having inner links or the sublinks
please give the information in detail

linking to things outside of Drupal?

Hi, I am really quite a newbie, but making progress building my Drupal site (or rather, it will be the guts, the "community plumbing," so to speak, of my site). If this one question were answered, a LOT of problems could be solved tomorrow: how does one make a menu link to the outside of Drupal? I ask this because I've modified my menu to include some new menu items, and I need to link these menu items to URLs which were already established as pages on the website I have going already. So I put that URL in a box which asks for the Drupal path that the link attaches to - and every time, when I click on what should be the menu item that links to something else - it says that that page is "not found." What can I do? This has got to be simpler than the nervewracking hours I've spent trying to figure this out.

How to use theme_menu_tree with primary links ?

When I read your article a big smile came upon my face : "yeah, that is THAT simple !" Several hours later, I feel depression is going to kill me... No, just kidding ! Well, I find that theme_menu_tree is my new friend ONLY IF I want it on the side of the main content. But if I want to use your tutorial to make a wonderful international navigation bar, it's becoming tricky. How do I make an horizontal navigation bar ? Help me ! Else I have to find a rope on ebay to hang me... ;-p

Well, here's the bad news....

You'll have to use CSS to accomplish that task. Luckily, I've already written on the basics in the following two tutorials. Start here: http://nicklewis.smartcampaigns.com/using-css-to-generate-expanding-horizontal-navigation-menus-in-drupal

Where'd the code go?

Um, your code segments have disappeared during your recent theme change. I'm interested in your technique, but of course, can't follow it without the code. :) (Firefox 1.0.6/Mac)

Where'd the code go?

Abracadabra! Heh. Oh, I'm an idiot, and forgot to install the code module when a did yesterday's full brain transplant. Also, thank you for giving me an opprotunity to say abracadabra. Understand its not something which happens often.

Cannot find .php files as well

Hmm, I am using standard theme chameleon but cannot find page.tpl.php . Were to look for it? I checked themes/chameleon for it and found the style.css and some other stuff, but thats it. Do I need another theme to do this?

 

That's correct. Chameleon,

That's correct. Chameleon, like blue-marine, uses the X-Template engine which uses different syntax, if I'm not mistaken. This tutorial requires a PHP-Template driven theme such as Box_grey, Clean Slate, ect... The good (or bad) news is that in the next release of drupal, all themes will be driven by php-template.

Can't find the PHP file

"Now open up, your theme's page.tpl.php file. If you don't know where that is, its in themes/box_grey/page.tpl.php." No such file on my Linux box, neither in that location nor anywhere else.

no:/usr/share/drupal# find *.php
cron.php
index.php
update.php
xmlrpc.php

So the question is: Where to put your snippet?

 I'm really keen on testing this menu because imo the main drawback with drupal is its too complicated menu system.

tia 

You're search seems to only

You're search seems to only have looked in your drupal directory, but not in the directory's subfolders. Open the "themes" folder within your drupal directory, and assuming your theme runs off of PHP template, simply open the folder (i.e. box_grey) of the theme you wish to test this on. Within that folder you will find style.css, and page.tpl.php, in addition to other files.

primary_navigation

I have made an attempt to get this in drupals core, in a uch friendlier way, but choked on bnoth timeshortage and the complexity of menu code. However, primary menu is a module that works kinda well: http://cvs.drupal.org/viewcvs/drupal/contributions/sandbox/ber/primary_links/ please give it a try, and get me feedback. After positive feedback, i can go and release it :)

primary_navigation

I have made an attempt to get this in drupals core, in a uch friendlier way, but choked on bnoth timeshortage and the complexity of menu code. However, primary menu is a module that works kinda well: http://cvs.drupal.org/viewcvs/drupal/contributions/sandbox/ber/primary_links/ please give it a try, and get me feedback. After positive feedback, i can go and release it :)

Ber, i did try this module (

Ber, i did try this module ( http://drupal.org/node/28095#comment-48903 ), but i couldnt understand the help comments like "You have only one container." After installing this module i assigned menus to primarylinks (here user encounter the term container) but how do i call this in theme.

how anchors are added to menu items

i looked at theme_menu_item() in docs to figure out where the anchor tag (precisely) is added to the menu items (otherwise menus) http://drupaldocs.org/api/head/function/theme_menu_item but couldnt figure out the anchors in the function. though there are theme_menu_item_link() and menu_item_link(), it doesnt give more information would appreciate your comments

By anchors you mean how do

By anchors you mean how do you add custom icons for each list item such as I have here, correct? Its very very easy.

First step:Check your page source, and find the ID of the block you want to customize. For example, let's use the source code from a project I'm currently working on:

<div class="block block-blog" id="block-blog-0">  <h2>Recent blog posts</h2>  <div class="content"><div class="item-list"><ul><li><a href="/node/3447">Hey nick</a></li><li><a href="/node/3446">Of Wizards, Geeks, and Nets</a></li><li><a href="/node/3445">Data, Theory and Design of Online Communities</a></li><li><a href="/node/17">my first posting as The Monkey</a></li></ul></div><div class="more-link"><a href="/blog" title="Read the latest blog entries.">more</a></div></div></div>

You will use CSS to add an icon of a blogpost to the left of each link.

First, let's setup a simple CSS rule that overrides most drupal theme's default method of handling item-lists, in addition to properly displaying our .item-list's icons.

.sidebar li a, .sidebar .menu li a  {   background-repeat: no-repeat;   display:block;   background-position:left;   padding:0 0 0 15px;   margin:0;}

Note that we've told this link to display as a "block". This centers the icon properly when a list item takes up more than one text row in the sidebar. In addition, note the padding -- we've set it to push to make 15px of room in the left part our link's text block. With this simple rule (theoretically), you'll now only have to specify the block's background-image to reach your goal.

Because our above CSS rule is generic enough to apply to all list items, and specific enough to override default settings, we are able to add our icon to the example source code with this simple CSS declaration. We assume that the "img" folder is in the same folder as your page.tpl.php file.

#block-blog-0 .item-list li a {background-image:url(img/docbullet.gif);} 

Now for comments

#block-comment-0 .item-list li a {background-image:url(img/commentbullet.gif);} 

And so on and so on, and so on. Let me know if it doesn't work. This should be a silver bullet, though.

menu_item_link() generates

menu_item_link() generates links for menus, it calls internal link format function l() defined in common.inc which returns anchor on a array in our case its menu items. in order to add span tag the following code <?php // common.inc...return '<a href="/'. check_url(url($path, $query, $fragment, $absolute)) .'"'. drupal_attributes($attributes) .'>'. ($html ? $text : check_plain($text)) .'</a>';}...?> should be <?php // common.inc...return '<a href="/'. check_url(url($path, $query, $fragment, $absolute)) .'"'. drupal_attributes($attributes) .'><span id="whatever">'. ($html ? $text : check_plain($text)) .'</span></a>';}...?> i think this is the only way to add span tags within anchors in drupal.

cool. well, i was looking

cool. well, i was looking precisely to know where anchor tag is defined for menu items that gets generated. So that i can add a span tag after an anchor for menu items for eg: now the menu items are generated as ...    <ul>    <li class="collapsed">        <a href="/taxonomy_menu/17" title=""> Politics </a>    </li>    <li class="expanded">   <a href="/taxonomy_menu/21" title="" class="active"> Technology</a>       <ul>           <li class="leaf">                <a href="/taxonomy_menu/21/5"> Blogging </a>           </li>     ... thus it is possible to override list classes like "expanded", "leaf" and "collapsed" and also anchor class "active" defined in drupal.css in to style.css (as per the menu tutorial). But if i want to add (not override) a span tag after an anchor to the above css, how do i go about it? that's the reason why i was looking precisely the code where the anchor is defined in menu list functions. looking for desired result like this, ...    <ul>    <li class="collapsed">        <a href="/taxonomy_menu/17" title="">            <span class="s1"> Politics </span></a>    </li> ...