I have a problem like this...

when i click on primary link menu item it will return the submenu items and primary link also highlighted. if i click submenu item the primary link hightlighting is gone. i need to maintain the primary link highlighting also...
advance thanks,
sivarajan

Comments

sivarajan’s picture

I think this post will help lots of people here, as i was unable to find the solution for "highlighting" primary links, when the secondary link is selected

Steps:

1. Need to add a new function in template.php , you can give any name you like.
2. Copy all the code present in theme_links function present in theme.inc and put in this function as is.
3. In my case the function name is phptemplate_generatexyz_primarylinks. The new lines highlighted in the funtion are added by me.


function phptemplate_generatexyz_primarylinks($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 = '';

      // Automatically add a class to each link and also to each LI
      if (isset($link['attributes']) && isset($link['attributes']['class'])) {
	$link['attributes']['class'] .= ' ' . $key;
        $class = $key;
      }
      else {
        $link['attributes']['class'] = $key;
        $class = $key;
      }

My new lines are

 $explode_array = explode('-',$link['attributes']['class']);
		if(count($explode_array)== 5)
		{
			array_push($explode_array,'active');
			$link['attributes']['class'] = implode('-',$explode_array);
			$pos = strrpos($link['attributes']['class'], "-");
			$link['attributes']['class'] = substr_replace($link['attributes']['class'], ' ', $pos, -6);
			
			
		}

      // Add first and last classes to the list of links to help out themers.
      $extra_class = '';
      if ($i == 1) {
        $extra_class .= 'first ';
      }
      if ($i == $num_links) {
        $extra_class .= 'last ';
      }
      $output .= '<li class="'. $extra_class . $class .'">';

      // Is the title HTML?
      $html = isset($link['html']) && $link['html'];

      // Initialize fragment and query variables.
      $link['query'] = isset($link['query']) ? $link['query'] : NULL;
      $link['fragment'] = isset($link['fragment']) ? $link['fragment'] : NULL;

      if (isset($link['href'])) {
        $output .= l($link['title'], $link['href'], $link['attributes'], $link['query'], $link['fragment'], FALSE, $html);
      }
      else if ($link['title']) {
        //Some links are actually not links, but we wrap these in <span> for adding title and class attributes
        if (!$html) {
          $link['title'] = check_plain($link['title']);
        }
        $output .= '<span'. drupal_attributes($link['attributes']) .'>'. $link['title'] .'</span>';
      }

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

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

  return $output;

}

4. Customize page.tpl.php

 if (isset($primary_links)) : 

My new line is

		 print phptemplate_generatexyz_primarylinks($primary_links, array('class' => 'links primary-links'));

          //print theme('links', $primary_links, array('class' => 'links primary-links'));
		  

And Wow, primary links are getting highlighted now, when we select any of the secondary links.

:)

osxpert’s picture

I am using the Zen-Theme, where I centered the primary and secondary links. In my case I had to put into my page.tpl.php:

print phptemplate_generatexyz_primarylinks($primary_links, theme('menu_links', $primary_links));

sudomaster’s picture

I'm sorry, but I really don't understand your instructions. Perhaps I'm just tired today, but I've read and re-read your instructions and can't make any sense of them - I can't tell what lines to insert, what to remove, and where to do it all. Please help - I've been wanting this to work for a long time!

osxpert’s picture

Hi, do you mean sivarajan's insctructions or mine?

Can you follow steps 1./2./3. or is your problem right there?

We can help - it's easy at the end ...

lejon’s picture

I need to do this too, but I can't understand sivarajan's instructions either. Can you re-phrase them in terms of:

1) Open file X
2) Replace this code ... with this code ...
3) Save and upload

4) Open file Y
5) Replace this code ... with this code ...
6) Save and upload

At the moment it's not clear what's going in and what's being replaced

Cheers!

tj2653’s picture

I got very close with this solution, but it's not working for everything. I have and audio, video, and some other content types. "audio" and "video" were both set up with CCK, and are virtually identical in every aspect. However, for whatever reason, the "audio" tab isn't being highlighted for audio/* and audio/*/* whereas the video tab IS highlighted throughout the video/* and video/*/*. Any ideas? I'm using Drupal 5.3 and modules I have that might be affecting it are: Pathauto and Custom Breadcrumbs.

EDIT: I have figured out a commonality between the content types that are working. They are the only Primary Links that have "No" set in the "Expanded" column of the Menu settings page. All the other menu items don't have anything in that column, and I can't even set them to No unless I put another item underneath them (which still doesn't fix the problem).

lejon’s picture

The previous comment just clarified things a bit for me...

I don't want to use any secondary links. But I do want my primary links to stay on when, as the previous commentator says, I am in a sub-section.

i.e. I have a section called 'progress' and I would like the 'progress' primary link to remain highlighted for all pages connected to 'progress' i.e. progress/*

This must be easy?!

Can someone clarify?

tj2653’s picture

lejon,

Try the code that was posted above. As I said, it partially worked for me, so it might work for you. Just:

1) Copy the first three code blocks to your template.php file
2) Get rid of all the opening and closing PHP tags for those blocks
3) Try the code block in bold in step 4 (without the PHP tags), in the same area sivarajan has it. I think people are confused because he put other blocks in to reference where you should put the new (bolded) code, and the PHP tags are throwing people off too. Or, try the code that osxpert has instead of the bolded code in 4 (that one worked for me).

Now can anyone help me with my problem? :)

hansBKK@drupal.org’s picture

For those who found the OP's instructions difficult, they do work just fine for D5 once you figure it out - here's a re-cap: find theme.inc and copy the function theme_links() into your template.php, then make the addition commented below with //customization of course changing yourthemename

function yourthemename_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 = '';

      // Automatically add a class to each link and also to each LI
      if (isset($link['attributes']) && isset($link['attributes']['class'])) {
        $link['attributes']['class'] .= ' ' . $key;
        $class = $key;
      }
      else {
        $link['attributes']['class'] = $key;
        $class = $key;
      }

//customization - from drupal.org/node/140491

 $explode_array = explode('-',$link['attributes']['class']);
        if(count($explode_array)== 5)
        {
            array_push($explode_array,'active');
            $link['attributes']['class'] = implode('-',$explode_array);
            $pos = strrpos($link['attributes']['class'], "-");
            $link['attributes']['class'] = substr_replace($link['attributes']['class'], ' ', $pos, -6);
        }

// end customization


      // Add first and last classes to the list of links to help out themers.
      $extra_class = '';
      if ($i == 1) {
        $extra_class .= 'first ';
      }
      if ($i == $num_links) {
        $extra_class .= 'last ';
      }
      $output .= '<li class="'. $extra_class . $class .'">';

      // Is the title HTML?
      $html = isset($link['html']) && $link['html'];

      // Initialize fragment and query variables.
      $link['query'] = isset($link['query']) ? $link['query'] : NULL;
      $link['fragment'] = isset($link['fragment']) ? $link['fragment'] : NULL;

      if (isset($link['href'])) {
        $output .= l($link['title'], $link['href'], $link['attributes'], $link['query'], $link['fragment'], FALSE, $html);
      }
      else if ($link['title']) {
        //Some links are actually not links, but we wrap these in <span> for adding title and class attributes
        if (!$html) {
          $link['title'] = check_plain($link['title']);
        }
        $output .= '<span'. drupal_attributes($link['attributes']) .'>'. $link['title'] .'</span>';
      }

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

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

  return $output;
}

Then in your page.tpl.php (this example is from zen starterkit), anywhere you see a call to the theme() function, replace it with something like the code below (sorry for the bizarre php/html code formatting here - can anyone tell me how to make the whole code set display as a single code block?)

if ($primary_links):

// customization from drupal.org/node/140491
// original code: print theme('links', $primary_links); 
 print yourthemename_links($primary_links, array('class' => 'links primary-links'));

</div> <!-- /#primary -->
endif;

if ($secondary_links):
<div id="secondary">

// customization from drupal.org/node/140491
// original code: print theme('links', $secondary_links);
print yourthemename_links($secondary_links, array('class' => 'links $secondary_links'));

</div> <!-- /#secondary -->
endif;

Note this doesn't affect other normal menu-module-generated menus on your site, just the ones explicitly output from your page.tpl.php, but that seems to be where most people are getting the problems.

A currently open issue to fix this in the next core D5 release is here: http://drupal.org/node/274532 and what I'd really like (much more extensive setting of active class based on URL) is here: http://drupal.org/node/248522#comment-931724

dgoldenbaum’s picture

Has anyone gotten this working in 6? If so, what alterations did you have to make?

dtabach’s picture

I also would like to see this for D6. There's this Menu Trails module, but I was not lucky enough to make it work.

Durval Tabach

mcrittenden’s picture

Did you ever get this working in D6?

- Mike, from Little Blue Labs and Drupal Check

smacphail’s picture

I didn't look in great detail at the code above, but for D6, by default it should be spitting out a class for your primary nav called "active-trail" if you're ever in a subsection of something that's in the main nav. So if I have Section1 in my Menu, and below that I have Subsection1, when I'm on the Subsection1 page, then "active-trail" will show up in the class definitions for Section1 in the menu.

This isn't much use for items that are *not* in your menu though. (Ex. an article page that is supposed to be in your section)

You might want to look at overriding some functions or spitting out the menu in a different way. In this post, the developer is using the links theme for his nav (that is, using theme('links'...) rather than menu_tree('primary-links')), and he overrides theme_links() with phptemplate_links().

Inside of that he's checking urls and using regular expressions to find matches, and then add classes accordingly. (ex. if I'm at /section1/subsection1/my_article, when I'm spitting out my menu, the menu item that has "/section1" as its path will have a new class added to it)

That's an ok solution, but it assumes that your subsections have urls that match up with parent urls. For 99% of the cases, that's probably fine, but if you have a subsection nav item that doesn't match up (ie. section is /section1 but the subsection under that is /blogs/user-name) then that code won't work. :/

It's a start though.

Good luck!

beasley’s picture

This is a solution that I used in D6 because I didn't know how else to do it, and didn't want to tackle the theme code. I just put the submenu link in both the primary links menu and the submenu.

Say you have a primary link called 'About us' and a custom section menu for 'About us'. In the section menu you have a link called 'Our mission'. I add the 'Our mission' page to both the primary links menu (as a subpage of 'About us') and to the 'About us' menu. Now when I click on 'Our mission' both the primary links and the 'About us' menu recognise it as their own. 'About us' highlights as well as 'Our mission' because they both have the 'active-trail' class. Of course, the primary links didn't expand. I had them in a simple horizontal menu with no drop-downs, and set a rule in Blocks for the submenus to appear in the appropriate sections.

I'm sure there must be neater ways of doing it, though.

stackpool’s picture

I did a similar workaround — using the Local Menu module as a quick fix. Rather than manually recreate separate menus, just have this module create them on the fly...

http://drupal.org/project/local_menu

You and your visitors might find it aesthetically pleasing to have hierarchical nodes working too.

http://drupal.org/project/nodehierarchy

This works great for most purposes, but there's just one minor issue — without hacking code I don't think you can make the active primary link a different colour from the rest of the primary menu links (although it will take text decoration, emboldening, borders, background colour, images etc etc). Or am I missing something obvious?

Actually — I notice that FF, Chrome and Safari don't display different colours for active/inactive primary menu links; but IE does. WTD!

beasley’s picture

— without hacking code I don't think you can make the active primary link a different colour from the rest of the primary menu links (although it will take text decoration, emboldening, borders, background colour, images etc etc).

Sounds like that might be a specificity issue with CSS. Have you tried making the style rule for the active primary link as specific (i.e. long-winded) as possible e.g.:
div#navbar div#primary ul.links li.active a {background-color: blue;}

That way it should trump any inherited style rules.

Wish I'd known about those modules!

stackpool’s picture

This is off-topic, but I stumbled upon this post again and thought I should just correct the poppycock I was talking about the active primary link. It's entirely editable by modifying the system-menus.css file: http://drupal.org/node/380098

Cheers —

sbydrupal’s picture

Hello Beasley,

I am trying to solve this problem for a while now.
I think your solution will be quite usefull for my case, where I will set the sub-menu blocks for exposed filter results, going down the sub-menu path quite deep.... it should be useful.

However, could not make your solution work. Here is what I created and not working:

- Created Link "A" and assigned to Primary Links.
- Created Link "B" and assigned to Primary Links as Sublink of "A".

- Created a custom menu, and created the same link "B" and assigned it to Custom Menu. Assigned Custom Menu to Block.

When clicking "B" in the Block, Primary link is not hightighted. Can you shed some light on what is wrong here..

Thansk much,

beasley’s picture

When you view the source for the link 'B' in Primary links does it have the 'active-trail' class? Just seeing if it's a CSS issue.

sbydrupal’s picture

Hi Beasley, I had forgotten to place the active-trail tag to css. Now, it is automatically working without any code addition/module addition. I am using Zen and D6. Thanks.