Based on the bluemarine template for the PHP template engine and work by Nick (example menu), the following is a adaptation with working dynamic menu:

page.tpl.php

Change the line reading print my_menu_tree(24); to your menu-id or to 0 to get a complete dynamic menu including administration menu items.

Comments

ronsens’s picture

Thanks a lot! (allthough I haven't understood all the things that you made, it works fine for me).

youngwax’s picture

[revised]
This worked great for the main menu (my_menu_tree(0)), but the admin section had so many entries that it went off the bottom of the screen.

Now, I wanted the admin menu and the settings menu separately, just so I could see them. When I asked for the admin menu, I got expanded contents - each entry as its own menu, that spread out all over the place.

I am not familiar with the territory, but I hacked the my_menu_tree as shown below. I added a second command line variable, "firstcollapse". If I set the "firstcollapse" variable, everything comes out the way I want. The program prints the menu item, not its contents. I get a top menu, an admin menu, a settings menu, and nothing from within any of the above getting in the way. As far as I can tell, it behaves properly concerning permissions of the current user. The site where I applied it is in a sorry state of flux, but it is available (sometimes): recdivers dot com/drupal-4.6.3

Any comments on how to do this more smoothly or simply are welcome.

so here is the call and the code:

print "<ul id='primary-nav'>";
$ralph = split(' ' , my_menu_admin(0) );
print my_menu_tree(0) . ' ';
print my_menu_tree($ralph[0],1) . ' ';
print my_menu_tree($ralph[1],1) . ' ';
print '</ul>';
 function my_menu_admin($pid = 0) {
   $menu = menu_get_menu($pid);
   $ralph = '';
   foreach ($menu['visible'][$pid]['children'] as $mid) {
     if ($menu['visible'][$mid]['title'] == "administer") {
       $ralph .= $mid . ' ';
     }
     if ($menu['visible'][$mid]['title'] == "settings") {
       $ralph .= $mid ;
     }
     if ( count($menu['visible'][$mid]['children']) > 0 ) {
       //$output .= my_menu_admin($mid);
       $ralph .= my_menu_admin($mid);
     }
   }
   return $ralph ;
 }

 function my_menu_tree($pid = 0, $firstcollapse = 0, $debug = 0) { 
 $menu = menu_get_menu($pid); 
 $output = ''; 

 if ($firstcollapse) {
   if ( count($menu['visible'][$pid]['children']) > 0 ) {
     $firstcollapse = 0;
     $fred = 1;
     $mid = $pid;
     if ($debug) {
       $dbg = "$mid ";
     } else {
       $dbg = '';
     }
     $output.= "<li class='menuparent'>" . $dbg . menu_item_link($mid); //."</li>";
       $output.= "<ul>";
         $output.=$dbg . my_menu_tree($mid);
       $output.= "</ul>";
     $output.= "</li>\n";
   }
 }
 else {
   foreach ($menu['visible'][$pid]['children'] as $mid) {
     if ( count($menu['visible'][$mid]['children']) > 0 ) {
       if ($debug) {
         $dbg = "$mid ";
       } else {
         $dbg = '';
       }
       $output.= "<li class='menuparent'>" . $dbg  . menu_item_link($mid); //."</li>";
         $output.= "<ul>";
           $output.= $dbg . my_menu_tree($mid);
         $output.= "</ul>";
       $output.= "</li>\n";
     } else {
      $output.= "<li>" . $dbg  . menu_item_link($mid)."</li>\n";
     }
   }
 }
 return $output; 
}
Hosting Geek’s picture

Cool stuff... I would just make the CSS into a seperate file... so it can be cached correctly... and save tonz of BW... I will hopefully hack on this very soon

canen’s picture

Having the function in the page.tpl.php file is not a good idea. Put it in your template.php, assign the output to a variable and then print the variable in page.tpl.php file.

http://drupal.org/node/16383

jakeg’s picture

Great code. I've implemented it like this to get a drop down admin menu at the top of the page, only if you have permission (otherwise it shows nothing). The menu consists of two top-levels, 'settings' and 'administer':

1. Move all of the admin menu to its own menu item.
2. Create new block, with the following in the body (replacing 63 with the ID of the admin menu) and input filter set to PHP:

<?php 
if ($menu_tree = my_menu_tree(63)) print "<ul id='primary-nav'>".$menu_tree."</ul>";

function my_menu_tree($pid = 0) { 
  $menu = menu_get_menu($pid); 
  $output = ''; 

  foreach ($menu['visible'][$pid]['children'] as $mid) {
    if (count($menu['visible'][$mid]['children']) > 0) {
      $output.= "<li class='menuparent'>".menu_item_link($mid); //."</li>";
      $output.= "<ul>";
      $output.= my_menu_tree($mid);
      $output.= "</ul>";
      $output.= "</li>";
    } 
    else {
      $output.= "<li>".menu_item_link($mid)."</li>";
    }
  }
  return $output;
}
?>

3. The following in your style.css file for your theme (block-block-1 should be changed to the block number of your admin block):

/* admin navigation */
#block-block-1 {
  position: absolute;
  top: 0;
  left: 0;
}
#block-block-1 h2 {
  display: none;
}

/* admin drop down bits */

ul#primary-nav,
ul#primary-nav ul {
	width: 150px; 
	margin: 0;
	padding: 0;
	background: #000; /* IE6 Bug */
	font-size: 100%;
	}
	
ul#primary-nav {
	float: left;
	/* width: 600px; */
	width: 300px;
	}
	
ul#primary-nav:after {
	  content: "."; 
    display: block; 
    height: 0; 
    clear: both; 
    visibility: hidden;
	}

ul#primary-nav li {
	position: relative;
	list-style: none;
	float: left;
	width: 150px; /* Width of Menu Items */
	}

ul#primary-nav li a,
ul#primary-nav li li a {
	display: block;
	text-decoration: none;
	color: #fff;
	padding: 3px;
}

/* Fix IE. Hide from IE Mac \*/
* html ul#primary-nav li { float: left; height: 1%; }
* html ul#primary-nav li a { height: 1%; }
/* End */

ul#primary-nav ul {
	position: absolute;
	display: none;
	}
	
ul#primary-nav ul ul {
	left: 100px;
	top: 0;
	}

ul#primary-nav li ul li a { padding: 2px 5px; } /* Sub Menu Styles */

ul#primary-nav li:hover ul ul,
ul#primary-nav li:hover ul ul ul,
ul#primary-nav li.over ul ul,
ul#primary-nav li.over ul ul ul { display: none; } /* Hide sub-menus initially */

ul#primary-nav li:hover ul,
ul#primary-nav li li:hover ul,
ul#primary-nav li li li:hover ul,
ul#primary-nav li.over ul,
ul#primary-nav li li.over ul,
ul#primary-nav li li li.over ul { display: block; } /* The magic */

ul#primary-nav li.menuparent { background: transparent url(arrow-down.gif) right center no-repeat; }
ul#primary-nav li li.menuparent { background: transparent url(arrow-right.gif) right center no-repeat; }

ul#primary-nav li a:hover { color: yellow; }

ul#primary-nav li.menuparent:hover,
ul#primary-nav li.over {background: #666 !important;}

4. Add the JavaScript mentioned in the post above to the head section of page.tpl.php:

(NOTE: is there somewhere else the JavaScript could go instead?)

5. Should work. Fingers crossed.

I've got this working in 4.7 HEAD.

jakeg’s picture

I've made this code into a module now, which seems to work really well :) You can find it here.

The module enables you to set how many (unlimited) independent dropdown menus you want, creating a new block for each one. You then set for each block the ID of the menu item to use for the menu's root.

Tested so far in IE6 and Firefox 1.5. Probably works in more browsers etc.

CSS still needs a lot of work. Currently just works for vertical dropdowns, but should work for horizontal too shortly. Let me know if anyone gets the module from me and whats to make some changes.