Menus: Can Items Be Separated into Separate Menus on Certain Pages?

Wolfey - March 19, 2007 - 16:53

One part of the site I'm working on has a menu layout which is set up something like this:

Site Menu

  • Departments
    • Department 1
    • Department 2
    • Department 3
  • Services
  • Contact
  • Links

What I am trying to do is - on certain pages - have a certain menu item (and its children) separated from the main menu, but added back in as a top-level menu; that menu's item in the main menu would be hidden as well. For example, if I clicked on the "Departments" menu item (or any item beneath "Departments"), it would split the menu above into two separate menus:

Departments

  • Department 1
    • Sub-Department 1
    • Sub-Department 2
  • Department 2
    • Sub-Department 3
    • Sub-Department 4
    • Sub-Department 5
  • Department 3

Site Menu

  • Services
  • Contact
  • Links

Here, "Departments" now has its own top-level menu, and the items beneath it are one level above where they would have been in the main menu (titled "Site Menu"). In addition, the menu item for "Departments" is removed from the main menu.

Would it be possible to do something like this in Drupal?

Similar

keylope - March 19, 2007 - 17:46

I'm doing something similar in that each main section of my site has it's own menu in the left hand side. The overall navigation is done at the top and simply link to the main sections.

In the menus area, I've defined each individual section menu and when adding it to a block region, define where it can display.

So if theres a section called "company", in the display section, click the radio button to say, only display in the areas below. In the textarea box, add two lines:

company
company/*

This was one of the ways I had to work around this problem. Hope that helps you out.

Module Found!

keylope - March 19, 2007 - 21:06

menu trim module can do exactly this! I just did a quick test and it does exactly what you want. The best thing is that you can have one hierarchical menu and it will do the rest for you! Make sure to read the readme file to figure out how to get the correct menu into your block region and configure it.

http://drupal.org/project/menu_trim

Hope that helps.

It Works, But...

Wolfey - March 20, 2007 - 19:26

Thank you for the suggestion - with this module, the appropriate menu item (and its children) can be shown as a separate top-level menu on the pages it needs to be on, and stay hidden everywhere else.

Unfortunately - unless I overlooked something - I still need a way to hide (or, in some cases, force the collapsing of) certain menu items in the main menu when on certain pages, to avoid having the same link be shown twice (one in the block provided by "Menu Trim", the other in the main menu). Giving those menu items their own menus isn't an option for the project I'm working on. If there's a way to do this, it will cover the rest of what I need here.

even more options

DynV - July 2, 2008 - 15:54

What you do for the top menu Menu Restricter is use the option min. level and or dept. Unfortunately there's no way to split or even have 2 instances, this is a good idea as I suggested in #277752: multiple instances and #277758: block splitting.

Similar

rashmid - April 19, 2007 - 16:38

So if theres a section called "company", in the display section, click the radio button to say, only display in the areas below. In the textarea box, add two lines:

company
company/*

the above solution what you have mentioned is proper, but I am not able to find that radio button "only display in the areas below". Can you tell me exactly where I can find this option. or which modules helps in this setting. Because I remember seeing this option and I am not able to find it now.

blocks

keylope - April 19, 2007 - 23:27

That setting is an option for a block. If you click on the 'configure' link for a block, scroll down to the last section and you should see the visibility section where this applies too.

(Bumping Topic...)

Wolfey - March 22, 2007 - 19:27

I apologize if I seem impatient with bumping this so soon, but I'm still wondering if hiding/collapsing individual menu items in the main menu can be done.

hmmm....

keylope - March 23, 2007 - 17:23

Okay, I just understood what you are trying to do. So far, I've not seen anything that can split or splice menus. You were right in that Menu Trim will only solve half of your problem.

Perhaps you could have a main navigation that will have all the main categories and then use a second menu with menu trim as a secondary navigation so that you don't have to split the menu and still show where someone is on the site?

Currently that's the setup I am using. Sorry I can't be of more help.

Maybe an "If-Else" Statement Involving the Menu ID?

Wolfey - March 26, 2007 - 15:43

Actually, the two-menu system you mentioned is what I've been using lately - one for all of the menu items (the actual main menu) and one just for menu items underneath the current page's menu item (the "Menu Trim" main menu). It's very close to what I want to achieve with the sidebar, and hiding/collapsing individual menu entries would be the last thing I need to complete it.

One thing came to mind recently: could an "if-else" statement be used to check the current page's node ID / content type / taxonomy term(s) / etc., and if it matches, hide or collapse a particular menu ID? That would take care of the last part of this issue, but unfortunately, I don't know how that can be done...maybe with some code in template.php, or a custom .tpl.php file, but I'm not sure what would be needed for it.

Difficult indeed

keylope - March 27, 2007 - 17:54

One thing about the menus that I've found is that it is hard to target specific menu items as they don't have id's. However, you might try using jQuery to accomplish what you want. jQuery is a javascript library that is packaged with Drupal but you would need to specifically call it in all of your page.tpl.php files to ensure that it is available for all pages in your site.

jQuery has some amazing selecting abilities. You could grab the url, parse it to figure out what parts of the menu you need and then use jQuery to (hopefully) target the menu items and hide them.

I've read up on jQuery and am still learning about it, but it's a great quick system and I think you can get the href of a specific link to do your comparison and matching on with the url.

Here is what I did to specifically call jquery so it won't be called twice in cases where it is needed. Your call could be different. This is in all my "page" template files. Be aware that the jquery.js file is about 19kb, which isn't much, but always good to know.

<?php /*print $scripts;*/
$js = drupal_add_js('misc/jquery.js', 'core', 'header');
print
drupal_get_js('header', $js);
?>

Then just create an external js file and go at it.

http://jquery.com/
The documentation area is where I usually spend most of my time but also be aware that Drupal doesn't have the latest version of jQuery. So some things I tried didn't work, so I had to find workarounds, but for the most part, everything was fairly easy.

I hope that might give you a direction. Definitely check out whether you would be able to target specific menu items, because I think that could your biggest hurdle. If you can get that, comparing and hiding should be fairly easy.

What if JavaScript Is Disabled; Found a Way to Hide Menu IDs

Wolfey - March 29, 2007 - 19:53

It does look like jQuery could do the job...but since it's JavaScript, I'm worried it could cause a few problems for those who don't/can't have JavaScript enabled - would menu items show up for those users no matter what in that case? Still, thanks for mentioning it - I'll have to take a closer look at jQuery later on.

Also, after some more searching (I didn't see this the first time I looked), I found information that says menu items do have IDs...and not only that, but it seems there is a way to hide individual menu items after all :)

The code I used is from the page "Expanding a menu tree based on node types" - see it for more details:

  • Add the following to template.php (copied from Step #1 in the above page):

    <?php
     
    function phptemplate_menu_item($mid, $children = '', $leaf = TRUE) {
        return
    _phptemplate_callback('menu_item',
        array(
    'mid' => $mid, 'children' => $children, 'leaf' => $leaf));
      }
    ?>

  • Create a new file, menu_item.tpl.php, and add the following to it (copied from Step #2 in the above page and modified a bit):

    <?php
      $link
    = menu_item_link($mid);

      if (
    arg(0) == 'node' && is_numeric(arg(1))) {
       
    $node = node_load(arg(1));
      }
     
      if (
        (
    $mid == __)
      ) {
      }
      else {
       
    $output = '<li class="'. ($leaf ? 'leaf' : ($children ? 'expanded' : 'collapsed')) .'">'$link . $children ."</li>\n";
      }

      print
    $output;
    ?>

    Replace the "__" in the above code with whatever the menu ID is. More menu IDs can be added to that statement if necessary.

This works, but unfortunately has two (major) drawbacks:

  • The ID of the menu item must already be known...and it can be difficult to find unless you have the master menu list ("/admin/build/menu") open.
  • This will hide that menu item on every page, in any menu - in this case, both the original main menu and the "Menu Trim" main menu.

The drawbacks are, more or less, due to looking at the menu ID ($mid) to determine what should be hidden. I originally tried doing this by looking at the current node ID ($nid) or the current "Views" page (arg(1)), but neither of them had any effect on the menu item(s) I wanted to hide, which is why I tried it once more with the menu ID (and, to an extent, succeeded).

Still, this means that it is possible to hide individual menu items - what needs to be worked on, though, is finding out how to do this based on what page the user is on (by node, "Views" page, taxonomy, etc.) instead of by menu ID, and make sure it only affects the original main menu.

interesting find

keylope - March 30, 2007 - 05:37

Do you think that the majority of your audience might javascript turned off either by choice or some other reason? The only case that I worry about someone not having javascript enabled is a hack attempt and for that, I just make sure that I'm protecting myself at a server level as well as with javascript to ensure that nothing unexpected gets into the system.

I've not seen that post before. It was an interesting read. I had to code some extra stuff in the menu_trim module to do what I needed it to do which is pretty similar to what that post is about as well. If you want to try it out, you can grab the code here: http://drupal.org/node/130583. Just make sure that you copy the original module code so that you can revert the changes if you need too.

Maybe you could use that to help what you're trying to accomplish with a bit of tweaking? But the premise was for menu trim to be able to still show menus for nodes that live under the same menu path based on the url.

I figured it would be easiest for menu trim to "re-work" the menu since it was already going through that stuff! :)

I'm interested to see what you finalize on. And if you're able to post a link to the final product, it'd be great to see.

Most Would Have JavaScript; Other Things Regarding the Menu ID

Wolfey - April 3, 2007 - 17:47

To be honest, I don't think that many visitors will have JavaScript disabled...but I still want to use as little JavaScript as necessary (and only where I really need it) so that, in the event it is disabled, it will cause as few problems as possible.

As for the suggestion, that's pretty interesting, having the full menu be shown (rather than hidden) on any page that doesn't have a trimmed menu :)

Also, I've looked at the code in your post (mainly that which refers to the menu ID) and tried a few things with it, but couldn't get anything that hides just a single entry, unfortunately.

As for the link: I'll be sure to post it once the site goes live - I don't want it to slip out early ;)

How about Roles

NancyDru - April 3, 2007 - 00:21

Set each department to a separate role and then use the Menu Per Role module.

Nancy W.
now running 5 sites on Drupal so far
Drupal Cookbook (for New Drupallers)
Adding Hidden Design or How To notes in Your Database

How Would Roles be Changed?

Wolfey - April 3, 2007 - 16:27

Thank you for the module suggestion, and that does seem like it could work...but wouldn't there have to be some way of changing a visitor's role depending on the department they visit - to ensure the correct menu item(s) are hidden - if each department has a separate role?

Ahhh

NancyDru - April 3, 2007 - 17:14

I think I see better what you're trying to do. Do me a favor and go to this site. Click on the "Products" menu item, look to the left side (a new menu block appears), and tell me if this is something along the lines of what you want.

Nancy W.
Drupal Cookbook (for New Drupallers)
Adding Hidden Design or How To notes in Your Database

Can "Products" be Hidden; Two Examples

Wolfey - April 3, 2007 - 19:18

I checked that out, and if "Products" could be hidden when it's clicked on, that would do what I need.

This makes more sense for the site I'm working on, due to how the menu has to be set up (something which was not my idea): the original main menu has all its entries expanded by default; child menu items are hidden until the parent menu item is hovered over using CSS. The "Menu Trim" main menu (provided by the module keylope mentioned) shows the child menu items of the parent menu item for the current page (if any) as a separate menu above the original main menu and is not shown otherwise, leaving just the original main menu.

The final step - which I haven't figured out how to do yet - is to hide (or, depending on the case, collapse) the parent menu item in the original main menu, depending on the current page. Two examples (which are pretty similar):

  1. If I click on "Departments" (a top-level parent menu item), it shows a list of departments in the sidebar (as a "Menu Trim" menu), but doesn't hide the "Departments" menu item in the original main menu, which leaves two sets of links for "Departments".
  2. If I click on "Elections" (a child menu item underneath "Departments"), it shows the child menu items for "Elections" as a "Menu Trim" menu, but doesn't collapse the menu item for "Elections" in the original main menu, leaving two sets of links for "Elections".

More or less, what I'm trying to do is keep a set of links from appearing twice in the sidebar.

I think what you need

NancyDru - April 3, 2007 - 21:54

I think what you need is to move the menus into blocks. Then you can set the visibility of the blocks to only show on certain pages. It sounds easier than it might be. But I would start with even getting the menus to appear (that's not so hard). Then work on hiding them, possibly with Menu_Per_Role or with a specific taxonomy.

Nancy W.
Drupal Cookbook (for New Drupallers)
Adding Hidden Design or How To notes in Your Database

Menus into Blocks?

Wolfey - April 12, 2007 - 15:29

(Sorry for taking so long to reply - I got sidetracked with a few other things to do for the site...)

Uh...moving the menus into blocks? From what I've read (at least as far as the "/admin/build/block" page shows), the menus are blocks, so I'm a little confused here...

Also, I need to hide individual items, not the entire menu - otherwise, your solution would have worked in this case.

Still, this brought up something very interesting - I did another search, found the handbook page "Create more readable (and portable) block id attributes based on the block title", and noticed that - if I read it right - blocks have IDs as well...which means if the original and "Menu Trim" main menus have different block IDs, there just might be a way to hide a menu item in one and leave it in the other, like I attempted to do in the "What if JavaScript Is Disabled; Found a Way to Hide Menu IDs" comment above :)

Sure you can control where blocks are shown

NancyDru - April 12, 2007 - 17:12

For example, here's what I do for the Author Information block on one site. This goes in the "Show block on specific pages" control.

<?php
 
global $user;
 
$match = FALSE;
 
$types = array('pinkslip' => 1, 'faq' => 1, 'recipe' => 1);
  if (
arg(0) == 'node' && is_numeric(arg(1))) {
   
$nid = arg(1);
   
$node = node_load(array('nid' => $nid));
   
$type = $node->type;
    if (isset(
$types[$type])) { $match = TRUE; }
    if (
$node->uid == 1) { $match = FALSE; }
  }
  return
$match;
?>

It only shows the block when the content type is "pinkslip," "faq," or "recipe" and the node was not created by the admin (user/1).

Nancy W.
Drupal Cookbook (for New Drupallers)
Adding Hidden Design or How To notes in your database

Hi Nancy!

arindamghatak794 - May 24, 2007 - 17:02

Hi Nancy!

I am not sure if I got you correctly here but is the above snippet for not publishing author information for certain content types ? Where does it go ? I am looking for something wherein anything that the admin publishes doesn't have his authorship info so that people can't click on his link to go to his profile....is this something similar ?

Thanks,
Arindam

www.MyResearchFunds.com
The World's Fastest Growing Network of Researchers

tracking...

lsabug - June 1, 2007 - 20:55

tracking...

bumping this... I also am

lucidmedia - November 13, 2007 - 22:52

bumping this...

I also am using menu trim, and I have a few pages with user generated content that do not wind up in the menu. I want those pages to share a specific trimmed menu as thier parent.

 
 

Drupal is a registered trademark of Dries Buytaert.