Parents and Children

Events happening in the community are now at Drupal community events on www.drupal.org.
CraigBertrand's picture

Hey Guys I am having trouble getting my primary links to be a.active when I am on a child page of that parent menu item. After searching drupal.org until I was blue in the face I thought this would be a great little check box in the theme settings for zen since I need this on a lot of sites I build. What do you guys think? Do you all have any other ideas about theme settings that would make our lives just a little easier?

Thanks to all those who have helped with zen it really rocks!

PS. How do I make those stinking menu items still appear a.active when you are viewing a child page (url)

Comments

Children have to be in the menu

johnalbin's picture

This is from memory…

If you have a page at /contact and that page is in the primary links menu. And you have a page at /contact/support. Then, if the /contact/support page is not in the primary links menu, the parent item won't get an a.active class.

  - John (JohnAlbin)

  - John (JohnAlbin)

menutrails

andrew.burcin's picture

To keep the menu parents "active" while browsing children, based on node types, try menu trails, at http://drupal.org/project/menutrails. For zen, edit the template.php file in the root (not the sub-theme) and add:

  // set the primary links
  $vars['primary_links'] = menutrails_primary_links(1);
  // you may want to also override secondary_links
  $vars['secondary_links'] = menutrails_primary_links(2);

to the _phptemplate_variables function, for example immediately under global $theme;.

Go to the site configuration > menutrails and set the parent of each node type. This can be a first or second level item. Be careful to only set each node type once, it seems to allow more than 1 entry and then you may find yourself being confused.

Thanks Ill give menutrails a

CraigBertrand's picture

Thanks Ill give menutrails a shot.

Still think this would be a cool theme setting :)


Until all have heard
Craig Bertrand

HansBKK's picture

I don't want to mess with content-types just to get menu highlighting. Taxonomy's an alternative, but having to keep a vocabulary in sync with my node's assigned path's a bit of a pain.

Plus Menu Trail's still dev and not been updated for a while - this is for a production site.

Is there any way if I set my paths up to mirror my primary/secondary structure, to have the highlighting of the menu links be based on the current display page's URL?

e.g. All nodes (and display pages, e.g. Views) assigned a path under /about/facilities would highlight "About" in primary and "Facilities" in secondary, regardless of how the user actually found their way to that location.

I'm a noob, so just assuming that Views can be assigned a path in the first place - can they?

I agree...

Moonshine's picture

and actually it's really only a matter of adding a couple extra conditionals via theme_links() to do it. If you take a look theme_links() you'll see how active is set by default:

<?php

     
if (isset($link['href']) && ($link['href'] == $_GET['q'] || ($link['href'] == '<front>' && drupal_is_front_page()))) {
       
$class .= ' active';
      }
?>

I actually need this functionality for a site I'm working on, so I'll comment back here with the code I'm using when I get a chance. I should qualify things by saying I just want the links to be marked as "childactive" for any path that is under them and "active" if they are the current active page. Then CSS can make the choice.

childactive?

HansBKK's picture

I also haven't ever seen this class, is it used for the parent levels of the current link?

I was just trying to say...

Moonshine's picture

that you could add a class to all "menu links" rather easily that would provide the info I think you are looking for by overiding the theme_links() function. I wrote some code yesterday to do it and it seems to work fine for me here, although I haven't heavily tested it yet. I'll post it here if you want to give it a try.

Basically, let's say you have a Zen subtheme named "mytheme", then in the template.php file for your subtheme you would just add this fuction to overide theme_links() (note the name of the function is based on the name of your subtheme and this is Drupal 6 code)

<?php
function mytheme_links($links, $attributes = array('class' => 'links')) {
 
$output = '';

  if (
count($links) > 0) {
   
$output = '<ul'. drupal_attributes($attributes) .'>';

   
$num_links = count($links);
   
$i = 1;

    foreach (
$links as $key => $link) {
     
$class = $key;

     
// Add first, last and active classes to the list of links to help out themers.
     
if ($i == 1) {
       
$class .= ' first';
      }
      if (
$i == $num_links) {
       
$class .= ' last';
      }
      if (isset(
$link['href']) && ($link['href'] == $_GET['q'] || ($link['href'] == '<front>' && drupal_is_front_page()))) {
       
$class .= ' active';
      }
     
// *******  BEGIN ADDITION FOR childpathactive class *******
     
if (isset($link['href'])) {
       
$link_path_expression = str_replace("/", "\/", drupal_get_path_alias($link['href']));
        if (
preg_match("/^".$link_path_expression."/i", drupal_get_path_alias($_GET['q']))) {
         
$class .= ' childpathactive';
        }
      }
     
// *******  END ADDITION FOR childpathactive class *******
     
$output .= '<li class="'. $class .'">';

      if (isset(
$link['href'])) {
       
// Pass in $link as $options, they share the same keys.
       
$output .= l($link['title'], $link['href'], $link);
      }
      else if (!empty(
$link['title'])) {
       
// Some links are actually not links, but we wrap these in <span> for adding title and class attributes
       
if (empty($link['html'])) {
         
$link['title'] = check_plain($link['title']);
        }
       
$span_attributes = '';
        if (isset(
$link['attributes'])) {
         
$span_attributes = drupal_attributes($link['attributes']);
        }
       
$output .= '<span'. $span_attributes .'>'. $link['title'] .'</span>';
      }

     
$i++;
     
$output .= "</li>\n";
    }

   
$output .= '</ul>';
  }

  return
$output;
}
?>

90% of this code is is just a copy/paste of Drupal 6 core's existing theme_links() fuction, so things render as normal. I just added the one new section that I've commented above.

After adding this function you will have to clear Drupal's cache so it gets picked up, just like other template.php overides.

With this code, if you have a primary link with a path of say "cookbook" and you are browsing a page with a path of "cookbook/oriental/maincourses" then the primary link would have a class of "childpathactive" that you could use. It will also key on more then one level so if you had a secondary link of say "cookbook/oriental" and where on "cookbook/oriental/maincourses", that link would receive the "childpathactive" class as well. Basically any link that is a parent "path" of the current page being viewed would get that class added.

It should be noted that you might be able to do what (I think) you're after just by using the current Zen CSS "section" markup also. However you would have to more CSS in this case, as you'd be creating CSS targets like "body.section-cookbook li.menu-188 a" for example, to target a single link as having an active subpath. I believe this would also only work where you are keying 1 level deep also as I think the "section-*" class is only uses the first path argument from what I see.

This could be rolled into a module very easliy, but really just tossing it in a theme that uses it makes more sense IMO. :)

If something is confusing, let me know...

Beautiful

Macronomicus's picture

Works wonderfully!!
Thanks a lot for that bit of code!!!
^_^

The pathauto module really helps with this setup too, so you dont have to type out those paths all the time.

Cheers!

Ouch (noob!)

HansBKK's picture

James,

I am amazed and grateful for your extensive reply - thank you!

I was (of course being a noob) hoping there would be a no-coding-required solution to this issue. I will do my best to understand and learn from your code when I get to an appropriate level in my learning curve - I'm hoping within say six months or so!

Your understanding of my (and I'm sure many others') needs seems solid, but while my brain's on this topic I'll just get some more notes down for posterity's sake. From here on this is no longer addressed to James specifically but to "the powers that be" in the general Drupal community.

I'd like the however-assigned URL path of a display page (whatever shows in the visitor's browser) to trigger the "menu path" highlighting trail.

If this could extend beyond the primary/secondary links to lower levels in say sidebar blocks, that would be even better, and if it could actually expand the appropriate branch of the menu's hierarchy tree that would really be the cat's pajamas.

Using your excellent example:

(All URL paths relative to the site root)

All pages under the top-level cookbook path would highlight the primary link labelled Cookbooks

A page withing cookbook/oriental/maincourses highlights both that and the secondary link Oriental Cuisine, the block containing the "Oriental Cuisine" menu becomes visible as a result of the admin-build-block attributes, and within that menu the Main Courses link (top-level within that block) is highlighted.

It would be great if the URL cookbook/oriental/maincourses/thai/spicy would do all the above, plus expand the Thai branch down to the next Spicy level, with all these links highlighted.

All the content contributing user needs to do is assign the path to the page and make sure those paths are assigned to menu items.

If this correspondence partially "breaks" when a visitor gets to a URL not assigned to a specific menu item (say via Search, View, Term page, etc) then the module would ensure that as much of the menu tree as possible is opened and highlighted in a top-down, left-to-right manner. So if the lowest level of this menu's branching is Spicy/Salads the recipe for the "Poo Pla" variety of "Som Tam", which is found at the URL cookbook/oriental/maincourses/thai/spicy/salads/smelly would at least trigger that much of the menu.

And in an ideal world, the corresponding breadcrumbs could also be optionally made to show in the same way, with the user able to specify from what level down (e.g. if Primary/Secondary navs show on every page, just start the breadcrumb trail from the "tertiary" level down. That way even if there were no menu nav at all at a lower level, the user could at least navigate their way back up the content hierarchy by clicking in the breadcrumb trail, exactly as if they were manually navigating via their browser's address bar by editing the URL, deleting from the right side to go "up" (many users do this when exploring a site anyway, but even more have no idea how).

BTW I'm not kvetching but IMHO this type of visitor-orientation functionality should be part of Drupal out of the box, whether part of core or an included module, and implementing it in such a simple transparent way from the developer's POV would help ensure that the many many ways of implementing taxonomy-cck-views based displays don't break the basic visitor navigation experience.

This functionality would go a long way toward enabling users new to Drupal to more easily construct a familiar if somewhat conventional site in Drupal from their existing static content (see the abandoned brochure-news corporate site recipe thread), and then add the social/interactive bells and whistles incrementally as they climb the learning curve.

If this were implemented as a generic v5/v6 module that would work with if not all themes implementing primary/secondary links, then at least the more common base/starting point themes like:

I'm sure the author of such a module would achieve everlasting fame and glory :-)

v5 code

HansBKK's picture

It's a long time later and I'd pretty much given up on this, but in getting to the implementation details of my theming this issue's become important again. Also, my learning curve has started to climb (just a little) past the newbie stage, so I feel ready to give something this complex a shot.

However in the meantime I've decided to use D5 for the greater module availability, is there any chance someone could post an adaptation of the above code that would work for v5.7?

Or perhaps a noob-friendlier solution has come up in the meantime?

With the other solutions I've tried, they keep the primary links highlighted, but nothing seems to get the secondary ones to stick around once the user gets deeper into the menu tree (using Menu Trim to put the tertiary+ levels as a vertical hierarchy in the sidebar).

I tried using Node Hierarchy and I thought it was working, but now it's not.

Another possible complicating issue: should my menu links point to the path alias or the "real" node URL?

Thanks in advance. . .

Found a reliable fix

HansBKK's picture

Found a reliable fix overriding theme_links that works with Zen, but of course this only applies to theme-generated menu links (at least it takes care of primary/secondary menus).

Cleaned-up version in my comment toward the end:

http://drupal.org/node/140491

Still looking for the more functional solution (based on the URL path rather than the menuing path as described above), any help welcome!

How could I extend this to

Fa-sum's picture

How could I extend this to all menu types (not just primary links)?

Thanks in advance.

satish21's picture

Hello Guys,

Greetings for a day.

I m new with Drupal.

I have primary links in horizontal menu bar.

I wants,

When user click on any primary link then submenu's related to this primary link will be loaded on executing page.

And when user click on any of this submenu , appropriate submenu page will be load with list of all submenus(same as above line.) of primary key.

If you all have any help then let me know.

Thanks and regards,
Satish.