- I have a content type on my site called "Articles".
- I created a view that lists the nodes of this content type. It's path is "/articles"
- For that view, I created a menu item in my main menu, "Articles".
- I used the pathauto module for all my nodes of this content type to have the path
articles/[node:title]
My question is, I want the menu item to remain highlighted if the user is viewing a single article node, or if the user is viewing the view.
I solved the issue by using theme_menu_link()
function in my template.php file for my theme (code below). Being new to the Drupal API, is there a better way to do it?
What I did:
function mytheme_menu_link(array $variables) {
//Some variables, we're using
$element = $variables['element'];
$sub_menu = '';
//#href is an element inside the item
$the_path = drupal_lookup_path('alias', $element['#href']) ?: $element['#href'];
//Compare the path to the actual URI (using sub-function), and if they match, then add a new CSS class
//either: 'uri-active' or 'uri-active-trail'
switch(mytheme__menu_detect_uri($the_path)) {
case 1: $element['#attributes']['class'][] = 'path-active'; break;
case -1: $element['#attributes']['class'][] = 'path-active-trail'; break;
}
//If there are sub-menu items under this, render those too
if ($element['#below']) {
$sub_menu = drupal_render($element['#below']);
}
//Return the output
$output = l($element['#title'], $element['#href'], $element['#localized_options']);
return '<li' . drupal_attributes($element['#attributes']) . '>' . $output . $sub_menu . "</li>\n";
}
/**
* Detect if a given path matches the current URI, as detected
* from reading the current_path() alias from Drupal
*
* @param string $path_to_check The path to check
* @param string $check_against The path to check against (leave blank for current path)
* @reutrn int 1 = Matches, 0 = No Match, -1 = In Active Path
*/
function mytheme__menu_detect_uri($menu_item_path, $actual_path = NULL)
{
if (is_null($actual_path))
$actual_path = drupal_lookup_path('alias', current_path()) ?: current_path();
//Compare em
if (strcasecmp($menu_item_path, $actual_path) == 0)
return 1;
elseif (strlen($actual_path) > strlen($menu_item_path) && strcasecmp(substr($actual_path, 0, strlen($menu_item_path)), $menu_item_path) == 0)
return -1;
else
return 0;
}