description

This snippet allows you to highlight your primary links as being active when a node related to the primary link is being viewed.

usage

For use in your page.tpl.php or custom page-type.tpl.php file. The snippet automatically tags an "active" primary link as <li class="selected"> so you can change your style.css class for your primary links to display an alternate colour/image etc. for active primary links.

step 1 of 2

Using a text editor like notepad.exe, replace the existing primary links snippet in your page.tpl.php file by copying and pasting the following snippet.


<?php if (count($primary_links)) : ?> 
    <ul class="primary">
         <?php foreach ($primary_links as $link): ?> 
             <?php preg_match("/<a\s*.*?href\s*=\s*['\"]([^\"'>]*).*?> (.*?)<\/a>/i", $link, $matches); ?>
             <?php if (('/'.drupal_get_path_alias('node/'.$node->nid))==$matches[1]): /* if $node exists */ ?> 
                <li class="selected"> <?php print $link?> </li>
             <?php elseif ('/'.arg(0)==$matches[1]): /* else try to use arg */ ?> 
                <li class="selected"> <?php print $link?> </li>
             <?php elseif ((drupal_get_path_alias('node/'.$node->nid)=='node/') && (arg(0)=='node') && ($matches[1]=='/')): /* else if home */ ?> 
                <li class="selected"> <?php print $link?> </li>
             <?php else: ?> 
                <li> <?php print $link?> </li>
             <?php endif; ?> 
         <?php endforeach; ?> 
    </ul>
<?php endif; ?> 

notes

  • This code might not do what you expect for psuedo nodes that are part of a module as it currently only uses arg(0).

Comments

DynV’s picture

For Drupal 5.x there's a much simpler solution ! Use the module Menu Trails at http://drupal.org/project/menutrails

mattman’s picture

Maybe some drupal ninja can tell me I'm out of my mind, but it seems that simply testing against the REQUEST_URI (that's what request_uri() ultimately returns - on Apache) is a pretty benign way to add an "active" css class to links you pass in.

I wrote this function to tag primary or secondary links with an "active" class. I wasn't worried about other menu items so I didn't feel the need for something like menutrails (seemed like overkill).

The following is in template.php (phptemplate themeing)

function mythemename_activelink($links) {
  if (module_exists('path')) {
    // $alias = drupal_get_path_alias($_GET['q']); // This hits the db via ultimate drupal_lookup_path()
    $alias = explode('/', request_uri()); // Might as well save a db hit
    $alias = $alias[1];
    foreach ($links as $key => $link) {
      if ($link['href'] == $alias) {
        $links[$key]['attributes']['class'] = 'active';
      }
      return $links;
    }
  }
}

Then in your theme file (e.g. page.tpl.php)

print theme('links', mythemename_activelink($primary_links));

Are there any reasons I shouldn't be taking this approach?

themselves’s picture

Your code is slightly wrong. The snippet for Drupal 5 template.php should be:

function mythemename_activelink($links) {
  if (module_exists('path')) {
    // $alias = drupal_get_path_alias($_GET['q']); // This hits the db via ultimate drupal_lookup_path()
    $alias = explode('/', request_uri()); // Might as well save a db hit
    $alias = $alias[1];
    foreach ($links as $key => $link) {
      if ($link['href'] == $alias) {
        $links[$key]['attributes']['class'] = 'active';
      }
    }
    return $links;
  }
}

Other than that, it's exactly what I was looking for. Thanks for this! No idea if it'll work in D6 btw.

vijayan08’s picture

thanks for your post got exactly what i am expecting

olio’s picture

Hi,
I also searched for a way to link the page view of a specific node type to a primary menu item of my choice. Here's a simple solution for custom (module generated) nodes. Another way is the (already mentioned) menutrails module.

Background: Drupal's standard behaviour to link all kind of nodes to the parent menu item 'home'. I needed a way to assign the view page of a node to a specific primary menu item, depending on the node's type. Why? The primary menu item should stay active/ highlighted while I jump to the page view of a node that is related to this primary menu item.

For example, if you have a nodelist of a certain node type on the path 'workspace/nodelist-of-this-nodetype' and you click on a node in this list, one expect to stay in this menu trail (e.g. 'workspace/nodelist-of-this-nodetype/node-id'). Unfortunately, you will find yourself on the path 'node' and the primary menu item won't be highlighted as active.

At least for 'handmade'/ custom node types (defined by your own module), what I was searching for can easily be accomplished with the function menu_set_location()!
To do this, have a look at: http://api.drupal.org/api/function/hook_view/5
and http://api.drupal.org/api/function/menu_set_location/5

In the implementation of hook_view() of your node module, define the breadcrumb, then call menu_set_active_item() with this breadcrumb. Voilà! The trail will be "spliced in" to the existing site navigation at the point defined by the breadcrumb trail and the parent primary menu item will be set active.

Here is an example, with an primary menu item ('events/') and a nodelist of 'course' node types.

/**
 * Implementation of hook_view() in the module 'course' that defines a node type 'course'.
 */
function course_view($node, $teaser = FALSE, $page = FALSE) {
   if ($page) {
	// Associate the node_view with this menu path (to display the parent menu item as active).
	$breadcrumb = array();
	$breadcrumb[] = array('path' => 'events', 'title' => t('Events'));
	$breadcrumb[] = array('path' => 'events/course', 'title' => t('Course'));
	$breadcrumb[] = array('path' => 'node/'. $node->nid);
	menu_set_location($breadcrumb);
   }

You can do the same (for other primary menu items) with other node types, so that for each of your custom node types a specific primary menu item will be set to active (=highlighted).