My first post here so hallo to everybody.

Firstly - sorry for my English. It's not my native language :/

As a newbee in Drupal I have few questions trying converting my site to Drupal. I'm not so good in explaining stuff so... I will show you what I want to achieve in few illustrations.

Let say I have following menu (navigation) structure:

  • X menu item
    • X-sub1
      • page 1
      • page 2
      • story 1
    • X-sub2
      • page 1
      • gallery 1
    • X-sub3
      (...)
  • Y menu item
    (...)
  • Z menu item
    (...)

So there is 3 level depth menu. Level 1 is main navigation manu. Second level links shows only when I click on first level division and so on.

So for example – first state, when user enters on page will be like this:

IMAGE 1

Next – user clicks on “X menu item” in main menu. It should look like this:

IMAGE 2

So as you can see, when user clicks on “X item” it automatically shows first sub division (in second depth) of that main division. In this example it is “X-sub1”. So “X item” it is only a container (has no real content inside, it is only for structured navigation) and it forwards to first subdivision of itself.

Now user can see third level links in sidebar. When he clicks on some link there it should look like this:

IMAGE 3

So now actual page is highlighted in sidebar menu for third depth level links along with parent divisions: “X-sub1” and “X item” in top navigation bar.

I could do it with lat of hacks and tricks, but I'm pretty sure this could be easily done natively in proper way, because this is so common pattern in current webdesign needs and Drupal seems to be very elastic CMS. (at least from what I heard here and there)

So my question is: what is proper way to do things like this. How do you deal with such navigation in your systems.

Thanks

BTW, there is no possibility to show images? That would simplify many things here :)

Comments

sepeck’s picture

You can do it. Each menu creates a block. Each block can be set to display on specific pages.
Check out this post http://drupal.org/node/26384#comment-45860

-Steven Peck
---------
Test site, always start with a test site.
Drupal Best Practices Guide -|- Black Mountain

-Steven Peck
---------
Test site, always start with a test site.
Drupal Best Practices Guide

yoyek’s picture

For each 'menu' you want create a new menu and add the nodes etc. Menu's automatically create new blocks. Go enable the block. Edit and in path, select only show on pages and enter:
aboutus
aboutus/*

If I understand correctly here is a suggestion to create new menu for every new branch (this website will have lots and lots of such menus, it will be mess without logical hierarchy). So as far as I can see it is flat solution, and Drupal menus seems to be hierarchical by nature of node connection.

What more - I don't want my clients to edit blocks, and I don't want give them permission to create new menus (in administer > menus > add menu). There is one menu hierarchy for navigation, with divisions and subdivisions, and when they write new content (page/story) they should only choose where it should be placed in this menu hierarchy (by "parent item" select box) and system should accordingly represent it visual on the site.

Next downside is when url of some page will change - that will require to edit every block accordingly. And changes in names of divisions on a site is not so rare (at least for my clients :) - for example: "our company" -> "about us", "offer" -> "our offer" etc).

It is some kind of a hack for me, because it did not seem like a native way of dealing with navigation (which by nature is hierarchical in Drupal). And it also requires giving permission to menu and block administration to my clients.

yoyek’s picture

[shameless bump]

anyone? :>

sepeck’s picture

menu module doesn't work that way.

Look at the book module for automatic hierarchy building. You can build your site in book module.

-Steven Peck
---------
Test site, always start with a test site.
Drupal Best Practices Guide -|- Black Mountain

-Steven Peck
---------
Test site, always start with a test site.
Drupal Best Practices Guide

yoyek’s picture

Thank you, I'll try this... but... I completly don't know where to start. Even afeter reading all handbook.

Is there any tutorial how to do that, some tips or where to start at least?

yoyek’s picture

Ok, I'm completly lost. Is seems to be an easy task for CMS, but it turns out that a guy with 8 years of php coding experience can't figure out how to make such a basic functionality. Im I as that dumb?

I have read a handbook, forum, finally I found "category module", follow tutorial on their site... and one thing that I found is this quote:

What's all this stuff about 'taxonomy terms' and 'book hierarchies'? He's not creating any terminologies, and he's not writing a book, either! All he wants to do is create some simple sections for his site. He considers ditching Drupal altogether - if it can't even do something this basic, maybe it's not worth bothering with after all.

Really nobody have this kind of problem, with ready solution to this? Well, I don't want do seek through source code of Drupal to understand how sub-menus should be generated automaticly according to place where I'm in. Even "category module" is not so helpfull.

Or maybe there is some other CMS in which it is simplier to create that basic kind of navigation without hacks. It can be even a comercial CMS.

catch’s picture

Enable the book module.

Enable the book navigation block.

Make a book page.

then add a couple of "child" pages.

Then make a new top-level book page, and add child pages to that, then add child pages to the child pages and so on.

That should give you an idea how it works.

OpenChimp’s picture

I'm just interested in this thread.

See this thread for my original post regarding a related need.

Michael
www.webemulsion.com

OpenChimp’s picture

I have just posted a solution that I'm using to achieve a very similar result to what you are looking for which involes the use of the Category Modules and building a few custom blocks. View it here

I just started using the Category module today, and am very happy with it so far, now that I have this part working.

Michael
www.webemulsion.com

brooklynwebguy’s picture

I am, like Yoyek, attempting to create secondary and tertiary submenus that are contingent upon selections in navigations higher up and which are physically separate from their parent items. I want a system that will be friendly to content users -- that is, one in which they are not required to do anything other than assign a piece of content to its proper place.

I have to say I'm really impressed with how powerful Drupal is out of the box and also how helpful and knowledgable the community is. At the same time, I think the hoops one has to go through to get the directory-style navigation that users are generally accustomed to is a bit much. This seems like a big problem to me: the majority of Drupal sites I've seen -- including drupal.org -- don't in my view pass basic usability tests for navigation: Active primary links are neither disabled nor specially formatted. Users are required to keep hitting the back button within a Primary Link topic because there is no context-specific navigation or content on the internal pages.

Is there anyone out there who has gamed Drupal into providing a more conventionally structured user experience that scales as the site grows? What's the optimal way to do this?

To me this is the only thing standing in the way of my adopting Drupal as my for-most-jobs framework. But the navigation complexity and the low weight the matter seems to have generally are potential dealbreakers.

TheWhippinpost’s picture

brooklynwebguy & yoyek, I know what you're going through, trust. I arrived here through the same door and lemme tell ya, as far as 4.7 goes, the functionality you want isn't there.

It can do it, but then any CMS can do anything if you're willing to spend the time coding. If you have a few months to spend learning Drupal, do it - It's a wicked system for a lot of things - but if you haven't, find another solution, because before you know it, you'll be here next month, then the month after... then you'll find yourself in a corner because you will have invested so much, that going back is no longer a valid option.

That's my best advice.

Mike
------------------------------------------------------------------------------------------
A simple thanks to those that help, a price worth payng for future wealth.

patrickharris’s picture

This seems like a big problem to me: the majority of Drupal sites I've seen -- including drupal.org -- don't in my view pass basic usability tests for navigation: Active primary links are neither disabled nor specially formatted.

This annoyed me from day one with Drupal. The only solution I've found, is to create my own primary navigation in the page template with php. I check the url, and depending on the section I'm in (e.g. '/forum/page_1'), I tag the body with that class (e.g. forum), and style it with css (this relies upon using the path module to rewrite urls).
An alternative would be to use taxonomy to do something similar. Both these methods are described in the IBM series of tutorials.

rapidsynergy’s picture

Hello all,

I've just started using Drupal and let me tell you wow! I'm excited! What a great community and what an amazing product. I'm glad to be on board.

Regarding the issue of context sensitive navigation at the tertiary level, why not just extend the menu functionality as needed in your theme?

First off - create a function to generate the needed tertiary links:


/**
 * Returns an array containing the tertiary links based on the primary menu.
 * Tertiary links can be either a third level of the Primary links
 * menu or generated from a second level of the explicitly defined secondary_menu
 */
function menu_tertiary_links() {
  $primary = variable_get('menu_primary_menu', 0);
  $secondary = variable_get('menu_secondary_menu', 0);
  if (!$primary || !$secondary) { //primary and/or secondary links disabled - ergo no tertiary links should be available
    return NULL;
  }	

  if ($secondary != $primary)  //secondary menu is different from primary - return children of explicitly defined secondary 
    return menu_primary_links(2, $secondary);
  else //all based on primary - return the third level accordingly
    return menu_primary_links(3, $primary);  	
}

Second, make your tertiary menu available as a variable to your PHPTemplate in your theme via the themeable overrides in template.php:

  function _phptemplate_variables($hook, $vars = array()) {
    $vars['tertiary_links'] = menu_tertiary_links();
    return $vars;
  }

Lastly, include the necessary block in your PHPTemplate:


<?php if ($primary_links): ?>
  <div id="primary">
  <?php print theme('menu_links', $primary_links); ?>
  </div>
<?php endif; ?>

<?php if ($secondary_links): ?>
  <div id="secondary">
  <?php print theme('menu_links', $secondary_links); ?>
  </div>
<?php endif; ?>

<?php if ($tertiary_links): ?>		
  <div id="tertiary">
  <?php print theme('menu_links', $tertiary_links); ?>
  </div>
<?php endif; ?>

And voila.... Context-sensitive tertiary links!

You could of course apply the logic to create quaternary, quinary, senary, septenary, octonary and so on and so forth. I can't imagine needing that deeply nested of a nav structure but nothing's stopping you!

I couldn't find information like this anywhere else so hopefully this will be of some help.

Cheers!

-Eric Wright

seanHodge’s picture

Hi,

The code looks good, but I'm a new drupaler. Where do I put the function?

I tried dropping the first two areas of code in template.php and after doing so my page no longer showed up. Not sure what I'm doing wrong. Thanks for help.

rapidsynergy’s picture

Hi seanHodge,

I'm a fairly new Drupaler myself. Welcome aboard!

Re: function placement- the first two snippets should go into your template.php file like you said. Of course depending on the theme you are using I'm thinking there may already a definition in your file for _phptemplate_variables(). PHP will only allow one function per name so make sure there isn't another. If there is, just modify that function to include the 'tertiary_links' variable.

Hope that helps.

Best,
Eric

mrsocks’s picture

Is there an example of how this is working somewhere?

Also, Do I need to change the 'menu_' part of the functions to reflect the name of the theme i am using?

I can only get primary links to show and cant figure out what I am doing wrong.

Zach Harkey’s picture

@Eric: This is awesome. Please contribute this tip to the theme developers handbook.

-zach
--
harkey design

: z

jchatard’s picture

Thanks for the snippet, it works well for me.

But, there's a BUT. It doesn't work all the time.

I have a menu tree like this :

Root
- Sub1
  - Sub1-1
  - Sub1-2
- Sub2
  - Sub2-1
  - Sub2-2

It's working for Sub2, but not Sub1.
i.e. Sub1-2 & Sub1-2 are never displayed.

So I tried to hardcode, like this

<?php
function menu_tertiary_links() {
    // third level nav, from pid 2
    return menu_primary_links(3, 2);
}
?>

Well not better...

menu_primary_links seems to return an empty array, and I can't figure out why.

I'm too tired to fully understand, but I think it comes from function _menu_get_active_trail_in_submenu() from menu.inc.

Any idea...

bsuttis’s picture

Really great code, thanks a lot.

Question -- currently I have 4 levels of navigation, I'm displaying primary, secondary, and tertiary as separate ULs, as in your code above, but I would like to be able to display the 4th level of navigation within the 3rd level, so instead of having a fourth UL with the 4th level navigation, I would like to output the fourth level as a child of the 3rd level.

To help illustrate, I am aiming for:

Primary (separate UL)
Secondary (separate UL)

Tertiary (separate UL)
-- Quad (LIs within tertiary UL)

Any advice? I'm not sure if its something that can be edited within the page.tpl's code, or the template.php function.

bsuttis’s picture

For anyone else looking for the above, Eric (rapidsynergy) provided me with a solution I'd like to share:

Replace the above function in your template.php with the following:

/**
* Returns an array containing the tertiary links based on the primary menu.
* Tertiary links can be either a third level of the Primary links
* menu or generated from a second level of the explicitly defined secondary_menu
*/
function menu_tertiary_links_revisited() {
  $primary = variable_get('menu_primary_menu', 0);
  $secondary = variable_get('menu_secondary_menu', 0);
  if (!$primary || !$secondary) { //primary and/or secondary links disabled
    return NULL;
  }   

  if ($secondary != $primary)  //secondary menu is different from primary - return children of explicitly defined secondary
  {
    return _render_custom_menu_tree($secondary, 1);
  }
    else //all based on primary - return the third level accordingly
  {
    return _render_custom_menu_tree($primary, 2);     
  }
}

function _render_custom_menu_tree($pmid, $depth) {
  // get the menu items that lead to the current menu item for a specific parent_id
  $active_trail = _menu_get_active_trail_in_submenu($pmid);
  return theme('menu_tree', $active_trail[$depth]);  //create a tree starting from specified label and theme using default engine	
}

Don't forget to change the function's name in _phptemplate_variables to menu_tertiary_links_revisited();

And put this into your page.tpl.php:
print $tertiary_links;

Thanks again to Eric.

jefbak2’s picture

Is there a way to do this using the drupal 5.x interface? I am using content types and need to have some navigation only menus.

bsuttis’s picture

The above is working code for a site that runs 5.1, unless I'm misunderstanding your question.

Rowanw’s picture

To get extra levels in 5.x all you need is this in template.php:

<?php
function _phptemplate_variables($hook, $vars = array()) {
  $primary = variable_get('menu_primary_menu', 0);
  $vars['tertiary_links'] = menu_primary_links(3, $primary);
  $vars['quaternary_links'] = menu_primary_links(4, $primary);
  $vars['quinary_links'] = menu_primary_links(5, $primary);
return $vars;
}
?>

Then use this in page.tpl.php:

<div id="tertiary" class="clear-block">
  <?php print theme('links', $tertiary) ?>
</div>
<div id="quaternary" class="clear-block">
  <?php print theme('links', $quaternary) ?>
</div>
<div id="quinary" class="clear-block">
  <?php print theme('links', $quinary) ?>
</div>

Alternatively, you can use an if statement to have the 3rd, 4th and 5th levels show up in place of eachother:

template.php

<?php
function _phptemplate_variables($hook, $vars = array()) {
  $primary = variable_get('menu_primary_menu', 0);
  $vars['tertiary_links'] = menu_primary_links(3, $primary);
  $vars['quaternary_links'] = menu_primary_links(4, $primary);
  $vars['quinary_links'] = menu_primary_links(5, $primary);

  if (menu_primary_links(5, $primary)) {
    $vars['localnav'] = menu_primary_links(5, $primary);
  } else if (menu_primary_links(4, $primary)){
    $vars['localnav'] = menu_primary_links(4, $primary);
  } else {
    $vars['localnav'] = menu_primary_links(3, $primary);
  }

return $vars;
}
?>

page.tpl.php

<div id="local-nav" class="clear-block">
  <?php print theme('links', $localnav) ?>
</div>
cbrody’s picture

Hi, I've tried your solution but it doesn't seem to generate the links. Does the menu have to be called "primary links" or something else for this solution to work?

Rowanw’s picture

I'm not sure what could be causing a problem, although I haven't used this on a fresh install so it could be dependent on other factors of the site I'm working on.

Do any of the other suggestions in this thread have an effect on your site?

RXM307’s picture

Thanks for this, works fine for me in 5.7

except I added the following to template.php

function _phptemplate_variables($hook, $vars = array()) {
  $primary = variable_get('menu_primary_menu', 0);
  $vars['tertiary_links'] = menu_primary_links(3, $primary);
  $vars['quaternary_links'] = menu_primary_links(4, $primary);
  $vars['quinary_links'] = menu_primary_links(5, $primary);
return $vars;
}

and the following to page.tpl.php under the if (($secondary_links)) section in the marinelli theme

         <?php if (($tertiary_links)) : ?>
      <?php print '<div id="submenu">' ?>
          <?php print theme('links', $tertiary_links, array('class' => 'links tertiary-links')) ?>
          <?php print '</div><div class="stopfloat"></div>' ?>
        <?php endif; ?>
dandaman’s picture

Not surprisingly, the Drupal 6 API changed so this is how to do this in Drupal 6:

Actually, I just wanted the tertiary navigation in a block that shows up on the left side. So I created a block in the admin system after enabling the "PHP Filter" module and gave it this code:

$primary = variable_get('menu_primary_links_source', 'primary-links');
print theme('links', 
    menu_navigation_links($primary, 2),
    array('class' => 'menu', 'id' => 'left-nav'));

Alternatively, to just do this directly in your template, add this function to your theme's template.php:

function zen_classic_preprocess_page(&$vars, $hook) {
  $primary = variable_get('menu_primary_links_source', 'primary-links');
  $vars['tertiary_links'] = menu_navigation_links($primary, 2);
  $vars['quartiary_links'] = menu_navigation_links($primary, 3);
}

Then, of course, put this in your page.tpl.php:

<?php print theme('links', $tertiary_links, array('class' => 'links tertiary-links')) ?>
<?php print theme('links', $quartiary_links, array('class' => 'links quartiary-links')) ?>

Dan "da Man"
Webmaster
http://cMusicWeb.com/
http://da-Man.com/

Dan "da Man" Ficker
http://da-Man.com/

Rick Hood’s picture

Thanks this seems to work great. For all: remember to clear cache: admin/settings/performance (button at bottom) - I keep forgetting.

My use case is to have automatic menus built via taxonomy menu module http://drupal.org/project/taxonomy_menu and I think above will let me do that. I imagine I can go as deep as want but just continuing to add new depth after:

$vars['quartiary_links'] = menu_navigation_links($primary, 3);
dandaman’s picture

Yes, you definitely can keep going deeper. Make sure to update the number on the right as you keep going as well, e.g.:

$vars['5th_level_links'] = menu_navigation_links($primary, 4);
$vars['6th_level_links'] = menu_navigation_links($primary, 5);
$vars['7th_level_links'] = menu_navigation_links($primary, 6);

Dan "da Man"
Webmaster
http://cMusicWeb.com/
http://da-Man.com/

Dan "da Man" Ficker
http://da-Man.com/

helloari’s picture

thanks for posting this great code. i found i had to change "zen_classic" to my theme name and it worked.

but it didn't give a nested ul list of menu items. that's what i really need. basically just like the "navigation menu" does automatically.

perhaps my complication is that i'm using the primary menu as the secondary menu?

dandaman’s picture

First, to make sure it's not showing a nested version, you should check if those items are "Expanded" in the main menu administration page. If they are not "Expanded", the sub-items will only show up if you are in a sibling or child item of that menu item.

If you want to make hierarchical menus such as this and not just basic primary links style menus, I also recommend checking out the Menu block module and maybe just putting a block region there and styling the block as needed.

Dan "da Man" Ficker
http://da-Man.com/

ericbroder’s picture

Thanks Dan, your method works for me. I'm using a custom Zen sub-theme. I wanted to add third-level menu items to my theme.

template.php:

/**
 * Override or insert variables into the page templates.
 *
 * @param $vars
 *   An array of variables to pass to the theme template.
 * @param $hook
 *   The name of the template being rendered ("page" in this case.)
 */
function mycustomtheme_preprocess_page(&$vars, $hook) {

  // Add third-level menu items to page template.
  // http://drupal.org/node/86890#comment-1211618
  $vars['third_level_links'] = menu_navigation_links('primary-links', 2);

}
// */

page.tpl.php:

          <?php print theme('links', $third_level_links,
            array(
              'id' => 'third-level-menu',
              'class' => 'links clearfix',
            ),
            array(
              'text' => t('Third level menu'),
              'level' => 'h2',
              'class' => 'element-invisible',
            ));
          ?>
Unkhakook’s picture

use SPIP:

http://www.spip.net

:)

alimosavi’s picture

what is way for solving it in drupal 6

you know that menu Function have several change in the drupal 6
now can i add this ability to drupal 6

robinhood1362’s picture

How do we manage to overcome this obstacle in drupal 6.x regarding the fundamental changes in the menu system? The above mentioned functions and php snippets that are supposed to return sub-menus just bring back "0" (as in print "0") in drupal 6.x... Any ideas? Or should I continue the subject in a discussion filed under 6.x (and not 4.7!).
UPDATE: OK I guess I found what I needed: http://drupal.org/project/local_menu

Summit’s picture

Hi,

Great post about 3th level links. I am interested in a complete hierarchical solution based on panels 2:
As Earl said:
Since the URLs are built through pathauto, all the URLs as far as panels is concerned are taxonomy/term/TID regardless of the depth.
Upon loading the taxonomy term, you can load the taxonomy tree and discern the depth of the current term. Once you have this number, you can easily make a determination of which 'display' to use, much the same way that it currently will do for vocabulary.

Coul anybody make some panels 2 code from this? Thanks a lot in advance!

See my post: http://drupal.org/node/231911#comment-847519
Subscribing, greetings, Martijn

hansBKK@drupal.org’s picture

So I thought I'd post it somewhere - eventually I'll do that "corporate brochure" recipe I swear :)

I've been struggling with this issue - an easy (at least somewhat automated) way to:

  • build a site hierarchy with a SINGLE menu tree that controls primary/secondary as horizontal top-navs AND context-sensitive tertiary+ menu blocks for sidebar placement
  • in the 3+ sidebar blocks, only show a depth of a few levels, no matter how deep the overall hierarchy
  • always keep the visitor oriented as to where they are in the hierarchy, even when users arrive at a given path via search/term/link from outside etc, with:
    • the menus showing the proper context, automatically opened to the appropriate level
    • proper "active" CSS class generation at all levels (primary/secondary and all parent links showing)
    • breadcrumbs filling in the gaps between the secondary level (always visible) and the top of the currently visible segment of the deeper hierarchy
  • automated synchronization at node creation time between the menu/breadcrumb tree and pathauto-generated URLs
  • ability to re-order and re-parent nodes, changing the URL and menu tree at the same time

OK, so I haven't got all of everything, but 90% is delivered with these modules (on v5):

Node Hierarchy
Menu Trim
Pathauto
Path Redirect (helps compensate for Pathauto's messing with my URLs everytime I touch a node!)

Yes Drupal's the bee's knees, it really is, thanks to all involved (but) [soapbox] I'm not saying making this all work ended up being so hard to actually do once I found these modules, but IMO it really shouldn't be so &%*#$) difficult to just FIND OUT HOW to implement a set of features that (again IMO) should be available out of the box, since they deliver functionality that the newcomer would expect to be in such a technically advanced project. [/soapbox]

esmailzadeh’s picture

hansBKK@drupal.org’s picture

If I did actually test the category module, the answer is no. I have done a lot of googling around it, and it seems that the original intentions were good, but we all know where those can lead . So no, I haven't bothered actually setting it up on a test site. Reasons:

  • It seems to mess with core functionality, both book (which I might be able to live without) and taxonomy (definitely not)
  • It apparently messes with the database schema
  • It apparently doesn't have a clean uninstall routine (and IMHO a module shouldn't even really need one)
  • It doesn't seem to have much support by the mainstream community
  • It doesn't seem to have been maintained much lately - I'm not implementing modules that aren't well on the way to v6 by now

To put it bluntly my opinion (based admittedly on pretty cursory research) is that it seems to be more of a Drupal fork than a clean add-on, and a relatively dead one at that. And I didn't see much about Views integration, which seem to me at this point to be the way to go with "term pages" rather than actual nodes.

But thanks for the suggestion, and if the above points are wrong or there are compelling reasons to check it out I may have missed I'm certainly open to corrections.

esmailzadeh’s picture

i think category module add a lot of trash to drupal's db and code and change a lot of things,
i have same problem, and i could not wait for new version of panels module and ....
so i use a simple very different way for building my navigation:
i use taxonomy redirect for redirecting taxonomy pages to my custom pages.
i use a module and build a menu with menu hook and made my custom pages with addresses that taxonomy redirect linked to these path.

mistresskim’s picture

rapidsynergy: What is the code to return one array which has the siblings of a menu item, and another array which has the children as I would like to publish them in separate blocks rather than as a nested tree at each level of the hierarchy?

joachim’s picture

I couldn't find anything about this in the handbook, so I've added a snippet with one of the solutions from this thread: http://drupal.org/node/333849