I added one context and Active menu for that context but It is not working

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

ceardach’s picture

Confirmed. I set my context to do two reactions: set the active menu item, and display a block. The block appears appropriately and the context devel block says I am in that context, however, the menu item I selected is not active.

ashiwebi’s picture

Can u give me some tutorial for this.

redben’s picture

Category: task » support

I have this problem too. It seems that context only works with primary and secondary links (have i missed something) AND the features menu if you have features installed.
Is this right ?

nwe_44’s picture

I also have this issue, I tried changing the module weight to various options, including the heaviest weight in the site, and still no joy.

Any ideas?

ceardach’s picture

Category: support » bug

Reassigning as a bug report because this is behaviour that should work.

ashiwebi’s picture

I created one menu under primary links and menu needs path then how we assign path for context?

redben’s picture

I think this is a theming/css class problem.
When i looked at the source the menu items i specified to be a active in the context actually have a class "active-trail" but not "active"

kyle_mathews’s picture

Component: User interface » Code

I can confirm the same problem. I've crated a context that is triggered on a view and on a node type. The active menu *is* set when viewing the view but is not set when viewing just one node.

Changing component to code as this seems like a coding problem, not an interface problem.

kyle_mathews’s picture

Update on my bug report. Why that the appropriate feature tab wasn't being set to active, it turned out, was I was printing the features menu in my theme. Context only sets links with the primary and secondary links menu to active. Once I set "primary-links" to use features, then links were set active appropriately.

schedal’s picture

On my end, I have a primary menu, I have selected the menu item I want to have the context active in, and it won't turn "ON" when I surf to the URL.

I don't know if this is an issue, but my primary links are all in the format:

page/%name

where page refers to a "panel" and %name is a name I give the menu which is an argument which is passed to the panel.

so I might have:

page/teachers

which calls up the panel named "page" and sends it the argument "teachers"

If I hardcode a path match to:

page/teachers it DOES work; but obviously this is less user friendly than using your mutli-select box.

Thanks for looking into this!!!

Best,

ceardach’s picture

Status: Active » Closed (won't fix)

Alright, I sat down to really try to solve this problem... and what it comes down to is that it really can't be fixed within the context module.

Context will only support adding the active-trail class to a menu link when a menu is rendered in the theme as either the primary or secondary links (see context_preprocess_page()). This is because, as far as I could tell after a few hours of investigation, there is no way to alter a menu link. At every level of the output of a menu link, there is no possible way to hook into it and add an additional class.

To compensate for this on my project, I'm adding a phptemplate_menu_item() function to my base theme's template.php file. It is a copy of theme_menu_item(), with an additional clause which will check to see if the link is part of the active paths for sites that use spaces or not. This should add the active-trail class in the majority of cases where the menu is rendered.

/**
 * Implementation of theme_menu_item().
 */
function phptemplate_menu_item($link, $has_children, $menu = '', $in_active_trail = FALSE, $extra_class = NULL) {
  $class = ($menu ? 'expanded' : ($has_children ? 'collapsed' : 'leaf'));
  if (!empty($extra_class)) {
    $class .= ' '. $extra_class;
  }
  if ($in_active_trail) {
    $class .= ' active-trail';
  } else {
    // Get the link's URL (sadly, this function doesn't include the link object)
    $url_pattern = '/<a\s[^>]*href=\"([^\"]*)\"[^>]*>.*<\/a>/siU';
    preg_match($url_pattern, $link, $matches);
    $link_path = substr_replace($matches[1], '', 0, 1); // remove first slash

    // Add in support for context's active-trail reaction
    $active_paths = context_active_values('menu');
    $space = spaces_get_space();
    $purl = $space->purl.'/';
    if (
      // Check against both the path, and path without PURL
      in_array($link_path, $active_paths) ||
      (isset($space->purl) && in_array(str_replace($purl, '', $link_path), $active_paths))
    ) {
      $class .= ' active-trail';
    }
  }
  return '<li class="'. $class .'">'. $link . $menu ."</li>\n";
}

Since it appears as though there is no way to do this outside of the theme layer, I'm marking this ticket as won't fix. People can hopefully use the above example to solve this problem instead.

redben’s picture

Another way of getting around this problem (if your use case allows it) is to have all your items as deep children of items on primary or secondary links then use menu_block to render the desired menu level on a different block. This is how i am doing it with my contexts

divbox’s picture

I'm not using spaces, so I made following change and I now get active-trail on the LI tag.

function MYTHEME_menu_item($link, $has_children, $menu = '', $in_active_trail = FALSE, $extra_class = NULL) {
  $class = ($menu ? 'expanded' : ($has_children ? 'collapsed' : 'leaf'));
  if (!empty($extra_class)) {
    $class .= ' '. $extra_class;
  }
  if ($in_active_trail) {
    $class .= ' active-trail';
  } else {
    // Get the link's URL (sadly, this function doesn't include the link object)
    $url_pattern = '/<a\s[^>]*href=\"([^\"]*)\"[^>]*>.*<\/a>/siU';
    preg_match($url_pattern, $link, $matches);
    $link_path = substr_replace($matches[1], '', 0, 1); // remove first slash

    // Add in support for context's active-trail reaction
    $active_paths = context_active_values('menu');
    if (in_array($link_path, $active_paths)) {
      $class .= ' active-trail';
    }
  }
  return '<li class="'. $class .'">'. $link . $menu ."</li>\n";
}

I had to add CSS to apply active to LI element. primary_menu had the class "active" set on the A tag

#block-menu-primary-links ul li.active-trail a,
#block-menu-primary-links ul li a.active {
 background:url(images/nav-hover.png) repeat-x;
 height:34px;
}
abdulFarooqui’s picture

I created a block with PHP Code. Inside that block I called the function menu_set_active_item('node/xxx') ;, where xxx is the node-id of the node linked to the menu-item I wanted to be active. I place this block on the page (in left side bar), it may not print anything, but it seems to do the job.

Corrected: I noticed that calling the menu_set_active_item from the code of a block is not good. It also had some side-effects on active menu trail and bread crumbs, which I could not explain. So I abandoned this approach. In my specific case menutrails module worked.

ceardach’s picture

Just as an update, this is the updated version of the code snippet above so it works with context 3 and spaces 3:

/**
 * Implementation of theme_menu_item().
 */
function phptemplate_menu_item($link, $has_children, $menu = '', $in_active_trail = FALSE, $extra_class = NULL) {
  $class = ($menu ? 'expanded' : ($has_children ? 'collapsed' : 'leaf'));
  if (!empty($extra_class)) {
    $class .= ' '. $extra_class;
  }
  if ($in_active_trail) {
    $class .= ' active-trail';
  }
  else {
    // Get the link's URL (sadly, this function doesn't include the link object)
    $url_pattern = '/<a\s[^>]*href=\"([^\"]*)\"[^>]*>.*<\/a>/siU';
    preg_match($url_pattern, $link, $matches);
    $link_path = substr_replace($matches[1], '', 0, 1);

    // Add in support for context's active-trail reaction
    $contexts = context_get();
    $active_paths = array();
    foreach ($contexts['context'] as $context) {
      if (array_key_exists('menu', $context->reactions)) {
        $active_paths[$context->reactions['menu']] = $context->reactions['menu'];
      }
    }
    $space = spaces_get_space();
    $purl = $space->purl.'/';
    if (
      // Check against both the path, and path without PURL
      in_array($link_path, $active_paths) ||
      (isset($space->purl) && in_array(str_replace($purl, '', $link_path), $active_paths))
    ) {
      $class .= ' active-trail';
    }
  }
  return '<li class="'. $class .'">'. $link . $menu ."</li>\n";
}
capellic’s picture

@divbox, #13.

THANKS! This is exactly what I needed.

capellic’s picture

I had a little problem with divbox's code in #13. I often use a node with as the top page in a section which is represented in the menu. This page often has a view in it via the Inset View module. This node has a title of "News" and a path (node/1) and an alias (news). When selecting "News" in context for the active menu, the paththat appears ins node/1 instead of news which causes problems because the code in #13 is trying to match on the alias. To overcome that, I've added the following code:

foreach ($active_paths as $i => $active_path) {
	if (substr($active_path, 0, 5) == 'node/') {
		$active_paths[$i] = drupal_get_path_alias($active_path);
	}
} 

Here's the full function:

function MYTHEME_menu_item($link, $has_children, $menu = '', $in_active_trail = FALSE, $extra_class = NULL) {
  $class = ($menu ? 'expanded' : ($has_children ? 'collapsed' : 'leaf'));
  if (!empty($extra_class)) {
    $class .= ' '. $extra_class;
  }
  if ($in_active_trail) {
    $class .= ' active-trail';
  } else {
    // Get the link's URL (sadly, this function doesn't include the link object)
    $url_pattern = '/<a\s[^>]*href=\"([^\"]*)\"[^>]*>.*<\/a>/siU';
    preg_match($url_pattern, $link, $matches);
    $link_path = substr_replace($matches[1], '', 0, 1); // remove first slash

    // Add in support for context's active-trail reaction
    $active_paths = context_active_values('menu');
		foreach ($active_paths as $i => $active_path) {
			if (substr($active_path, 0, 5) == 'node/') {
				$active_paths[$i] = drupal_get_path_alias($active_path);
			}
		}
    if (in_array($link_path, $active_paths)) {
      $class .= ' active-trail';
    }
  }
  return '<li class="'. $class .'">'. $link . $menu ."</li>\n";
}
JThan’s picture

I get a error that function context_active_values(); doesn't exist. I searched all files coming with Context Module and did not find that function. So this code can not be added.

owntheweb’s picture

Here's my addition referencing the context 3 version that worked for me (with no spaces module used). Custom URL aliases were being used, so drupal_lookup_path() is added below. Let me know if it's discombobulated as I'm newish at this:

<?php
function acquia_prosper_menu_item($link, $has_children, $menu = '', $in_active_trail = FALSE, $extra_class = NULL) {
  
  $class = ($menu ? 'expanded' : ($has_children ? 'collapsed' : 'leaf'));
  if (!empty($extra_class)) {
    $class .= ' '. $extra_class;
  }
  if ($in_active_trail) {
    $class .= ' active-trail';
  } else {
    // Get the link's URL (sadly, this function doesn't include the link object)
    $url_pattern = '/<a\s[^>]*href=\"([^\"]*)\"[^>]*>.*<\/a>/siU';
    preg_match($url_pattern, $link, $matches);
    $link_path = substr_replace($matches[1], '', 0, 1); // remove first slash
	
	$contexts = context_get();
    if(!empty($contexts)) {
		$active_paths = array();
		foreach ($contexts['context'] as $context) {
		  if (array_key_exists('menu', $context->reactions)) {
			$active_paths[$context->reactions['menu']] = $context->reactions['menu'];
		  }
		}
		
		if (in_array(drupal_lookup_path('source', $link_path), $active_paths)) {
		  $class .= ' active-trail';
		}
	}
  }
  return '<li class="'. $class .'">'. $link . $menu ."</li>\n";
}
?>
ryan_courtnage’s picture

@Kyle_mathews (#9) Thanks for figuring this out and posting. I was seeing this problem with a custom menu I'd created. Setting it to be the "Source for the primary links" in the menu settings made Context/Active Menu work for me.

my-family’s picture

The same problem as #18 (context_active_values() is undefined, fatal error), please could anybody suggest what to do? Thanks

thomjjames’s picture

Here's a little snippet I used to set the active menu trails using context with the nice_menus module:

In template.php:

function THEMENAME_nice_menus_build($menu, $depth = -1, $trail = NULL) {
  $output = '';
  $active_paths = array();
	
  //reaction to context module active menus
  if (module_exists('context')) {
    if ($contexts = context_active_contexts()) {
      foreach ($contexts as $context) {
        if ($context->reactions['menu']) {
          $active_paths[] = $context->reactions['menu'];
        }
      }
    }
  } 
	
  // Prepare to count the links so we can mark first, last, odd and even.
  $index = 0;
  $count = 0;
  foreach ($menu as $menu_count) {
    if ($menu_count['link']['hidden'] == 0) {
      $count++;
    }
  }
  // Get to building the menu.
  foreach ($menu as $menu_item) {
    $mlid = $menu_item['link']['mlid'];
    // Check to see if it is a visible menu item.
    if ($menu_item['link']['hidden'] == 0) {
      // Check our count and build first, last, odd/even classes.
      $index++;
      $first_class = $index == 1 ? ' menu-item-first ' : '';
      $oddeven_class = $index % 2 == 0 ? ' menu-item-even ' : ' menu-item-odd ';
      $last_class = $index == $count ? ' menu-item-last ' : '';
      // Build class name based on menu path
      // e.g. to give each menu item individual style.
      // Strip funny symbols.
      $clean_path = str_replace(array('http://', 'www', '<', '>', '&', '=', '?', ':', '.'), '', $menu_item['link']['href']);
      // Convert slashes to dashes.
      $clean_path = str_replace('/', '-', $clean_path);
      $class = 'menu-path-'. $clean_path;
      if ($trail && in_array($mlid, $trail)) {
        $class .= ' active-trail';
      }
	
     //context active menu reaction
     if (!empty($active_paths) && in_array($menu_item['link']['link_path'], $active_paths)) {
        $menu_item['link']['in_active_trail'] = true;
        $menu_item['link']['localized_options']['attributes']['class'] .= ' active';
        $class .= ' active-trail';
     }
			
      // If it has children build a nice little tree under it.
      if ((!empty($menu_item['link']['has_children'])) && (!empty($menu_item['below'])) && $depth != 0) {
        // Keep passing children into the function 'til we get them all.
        $children = theme('nice_menus_build', $menu_item['below'], $depth, $trail);
        // Set the class to parent only of children are displayed.
        $parent_class = $children ? 'menuparent ' : '';
        $output .= '<li class="menu-' . $mlid . ' ' . $parent_class . $class . $first_class . $oddeven_class . $last_class .'">'. theme('menu_item_link', $menu_item['link']);
        // Check our depth parameters.
        if ($menu_item['link']['depth'] <= $depth || $depth == -1) {
          // Build the child UL only if children are displayed for the user.
          if ($children) {
            $output .= '<ul>';
            $output .= $children;
            $output .= "</ul>\n";
          }
        }
        $output .= "</li>\n";
      }
      else {
        $output .= '<li class="menu-' . $mlid . ' ' . $class . $first_class . $oddeven_class . $last_class .'">'. theme('menu_item_link', $menu_item['link']) .'</li>'."\n";
      }
    }
  }
  return $output;
}

Thought it might be useful to someone else.

Cheers
Tom

artwork’s picture

This not work for me (I'm using nice menu 6.x-1.3 and rename already changed THEMENAME_nice_menus_build to THEMENAME_nice_menu_build). Is this compatible with my version ?

artwork’s picture

Problem solved

For nice menu version 6.x-1.3

changed

  if (module_exists('context')) {
    if ($contexts = context_active_contexts()) {
      foreach ($contexts as $context) {
        if ($context->reactions['menu']) {
          $active_paths[] = $context->reactions['menu'];
        }
      }
    }
  } 

to

  if (module_exists('context')) {
    if ($contexts = context_active_contexts()) {
      foreach ($contexts as $context) {
        if ($context->menu) {
          $active_paths[] = $context->menu'];
        }
      }
    }
  } 

or

just use $active_paths = context_active_values('menu');

Don't sure if this will cause a problem, just my work around.

joep.hendrix’s picture

#22 works nice, thanks!

chrisfromredfin’s picture

#24 didn't exactly work for me (the code is syntactically incorrect, to begin with). Here's the whole theme function that DID work for me, based on the example above and the theme code from nice_menus 1.3.

<?php
/**
 * Helper function that builds the nested lists of a nice menu.
 *
 * @param $menu
 *   Menu array from which to build the nested lists.
 */
function THEMENAME_nice_menu_build($menu) {
  $output = '';
  $active_paths = array();
   
  //reaction to context module active menus
  if (module_exists('context')) {
    if ($contexts = context_active_contexts()) {
      foreach ($contexts as $context) {
        if ($context->reactions['menu']) {
          $active_paths[] = $context->reactions['menu'];
        }
      }
    }
  } 

  foreach ($menu as $menu_item) {
    $mlid = $menu_item['link']['mlid'];
    // Check to see if it is a visible menu item.
    if ($menu_item['link']['hidden'] == 0) {
      // Build class name based on menu path
      // e.g. to give each menu item individual style.
      // Strip funny symbols.
      $clean_path = str_replace(array('http://', '<', '>', '&', '=', '?', ':'), '', $menu_item['link']['href']);
      // Convert slashes to dashes.
      $clean_path = str_replace('/', '-', $clean_path);
      $path_class = 'menu-path-'. $clean_path;
      // If it has children build a nice little tree under it.
      
     //context active menu reaction
     if (!empty($active_paths) && in_array($menu_item['link']['link_path'], $active_paths)) {
        $menu_item['link']['in_active_trail'] = true;
        $menu_item['link']['localized_options']['attributes']['class'] .= ' active';
        $class .= ' active-trail';
     }
      
      if ((!empty($menu_item['link']['has_children'])) && (!empty($menu_item['below']))) {
        // Keep passing children into the function 'til we get them all.
        $children = theme('nice_menu_build', $menu_item['below']);
        // Set the class to parent only of children are displayed.
        $parent_class = $children ? 'menuparent ' : '';
        $output .= '<li id="menu-'. $mlid .'" class="'. $parent_class . $path_class . $class .'">'. theme('menu_item_link', $menu_item['link']);
        // Build the child UL only if children are displayed for the user.
        if ($children) {
          $output .= '<ul>';
          $output .= $children;
          $output .= "</ul>\n";
        }
        $output .= "</li>\n";
      }
      else {
        $output .= '<li id="menu-'. $mlid .'" class="'. $path_class .'">'. theme('menu_item_link', $menu_item['link']) .'</li>'."\n";
      }
    }
  }
  return $output;
}
?>

As usual, this belongs in your theme's template.php file (rename THEMENAME to your theme's name), and flush caches.

Macronomicus’s picture

Yea this still doesnt work optimally even in the latest 3.x branch.
The better option is to use http://drupal.org/project/menutrails it works out of the box and is pretty awesome IMO.

dervishmoose’s picture

@owntheweb #19 Your fix works, thanks!

ONE thing to note, drupal_lookup_path( can not look up the special string <front>. This means you can not use context to set a menu item active that uses <front> as the path.

Note: this does not solve for if the path is a URL address

A better solution should be improvised for the long term.

Here is the update that I am using to support special string <front>:

function yourthemename_menu_item($link, $has_children, $menu = '', $in_active_trail = FALSE, $extra_class = NULL) {

  $class = ($menu ? 'expanded' : ($has_children ? 'collapsed' : 'leaf'));
  if (!empty($extra_class)) {
    $class .= ' '. $extra_class;
  }
  if ($in_active_trail) {
    $class .= ' active-trail';
  } else {
    // Get the link's URL (sadly, this function doesn't include the link object)
    $url_pattern = '/<a\s[^>]*href=\"([^\"]*)\"[^>]*>.*<\/a>/siU';
    preg_match($url_pattern, $link, $matches);
    $link_path = substr_replace($matches[1], '', 0, 1); // remove first slash
   
    $contexts = context_get();
    if(!empty($contexts)) {
        $active_paths = array();
        foreach ($contexts['context'] as $context) {
          if (array_key_exists('menu', $context->reactions)) {
            $active_paths[$context->reactions['menu']] = $context->reactions['menu'];
          }
        }
        if (in_array(drupal_lookup_path('source', $link_path), $active_paths) or (in_array('<front>', $active_paths) and  $link_path =='')) {
          $class .= ' active-trail';
        }
    }
  }
  return '<li class="'. $class .'">'. $link . $menu ."</li>\n";
} 
EdinburghRob’s picture

Thanks this worked for me, but I had to add some code to handle my base path and also cases where the active menu was a path from a view and didn't have an alias. Maybe this will save somebody some time.

<?php
function yourthemename_menu_item($link, $has_children, $menu = '', $in_active_trail = FALSE, $extra_class = NULL) {

  $class = ($menu ? 'expanded' : ($has_children ? 'collapsed' : 'leaf'));
  if (!empty($extra_class)) {
    $class .= ' '. $extra_class;
  }
  if ($in_active_trail) {
    $class .= ' active-trail';
  } else {
    // Get the link's URL (sadly, this function doesn't include the link object)
    $url_pattern = '/<a\s[^>]*href=\"([^\"]*)\"[^>]*>.*<\/a>/siU';
    preg_match($url_pattern, $link, $matches);
    $link_path = substr_replace($matches[1], '', 0, 1); // remove first slash
  
    $contexts = context_get();
    if(!empty($contexts)) {
        $active_paths = array();
        foreach ($contexts['context'] as $context) {
          if (array_key_exists('menu', $context->reactions)) {
            $active_paths[$context->reactions['menu']] = $context->reactions['menu'];
          }
        }
        
        $link_path = str_replace(base_path(), '', '/'.$link_path);
        if (in_array(drupal_lookup_path('source', $link_path), $active_paths) or (in_array('<front>', $active_paths) and  $link_path =='') or in_array($link_path, $active_paths)) {
          $class .= ' active-trail';
        }
    }
  }

  return '<li class="'. $class .'">'. $link . $menu ."</li>\n";
} 
?>
Alice Heaton’s picture

Hello,

If you don't need the class applied to the 'LI' element (eg. you have flat menus), then a more elegant solution (which applies the class to the 'A' element) is to use theme_menu_item_link instead. This way you don't need to have a regular expression on the path.

Implement theme_menu_item_link in your template.php as such :

function YOURTHEME_menu_item_link($link) {
  if (empty($link['localized_options'])) {
    $link['localized_options'] = array();
  }

  // Check if we match a context rule
  $contexts = context_active_contexts();
  foreach($contexts as $context) {
    if (isset($context->reactions['menu'])
        && $context->reactions['menu'] == $link['href']) {
      $link['localized_options']['attributes']['class'] .= ' active_trail';
    }
  }

  return l($link['title'], $link['href'], $link['localized_options']);
}

This works great for me, but I haven't checked special cases such as <front>, etc. so you might need to improve it for these.

For people who use a Zen subtheme, note that Zen already overrides menu_item_link ; so you should copy the extra code back into this function (only a few lines).

noussh’s picture

#22 worked for me. Thanks

vegardjo’s picture

Thanks Anselm, didn't get the other examples to work, possibly because this was in an og / spaces group, and there might be some conflict with Purl, but #30 works like a charm in this setup too!

hedac’s picture

I couldn't use any of the above codes... but I am using active-trail instead of active in the css and it works.

naero’s picture

This still isn't fixed and none of the code above works for me either. Has there been any progress on this?

joeysantiago’s picture

Using D7 i had to add this code to my basic template.php file:

function basic_menu_link(array $variables) {
  $contexts = context_active_contexts();
  if($contexts){
    foreach($contexts as $context){
       if($variables['element']['#href']==$context->reactions['menu']){
        $variables['element']['#attributes']['class'][]="active-trail";
       }
    }
  }
  $element = $variables['element'];
  $sub_menu = '';

  if ($element['#below']) {
    $sub_menu = drupal_render($element['#below']);
  }
  $output = l($element['#title'], $element['#href'], $element['#localized_options']);
  // Adding a class depending on the TITLE of the link (not constant)
  $element['#attributes']['class'][] = mattia_id_safe($element['#title']);
  // Adding a class depending on the ID of the link (constant)
  $element['#attributes']['class'][] = 'mid-' . $element['#original_link']['mlid'];
  return '<li' . drupal_attributes($element['#attributes']) . '>' . $output . $sub_menu . "</li>\n";
}

It looks like working. Actually i would have preferred to override a theme function like the ones that appear in $variables array at ['#theme'] element... but couldn't find the right function name, probably?

Well, any help appreciated, thanks

grndlvl’s picture

Here is #35 in a more generic form that works with drupal 7 out of the box.

<?php
function YOURTHEME_menu_link(array $variables) {
  if($contexts = context_active_contexts()){
    foreach($contexts as $context){
      if((isset($context->reactions['menu']))){
        if ($variables['element']['#href'] == $context->reactions['menu']) {
          $variables['element']['#localized_options']['attributes']['class'][] = "active";
        }   
      }   
    }   
  }
  $element = $variables['element'];
  $sub_menu = ''; 

  if ($element['#below']) {
    $sub_menu = drupal_render($element['#below']);
  }
  $output = l($element['#title'], $element['#href'], $element['#localized_options']);
  return '<li' . drupal_attributes($element['#attributes']) . '>' . $output . $sub_menu . "</li>\n";
}
?>
grndlvl’s picture

Status: Active » Closed (won't fix)

Although, I think this now can be fixed in the module with hook_preprocess_menu_link() in d7.

Unless there is something that is already there for that I will go ahead and create a patch for d7.

grndlvl’s picture

Version: 6.x-2.0-beta7 » 7.x-3.x-dev
Status: Closed (won't fix) » Active

whoops forgot

grndlvl’s picture

Status: Closed (won't fix) » Active
FileSize
1.01 KB

Patch to allow this to happen in d7.(basically same code from #36 inside of hook_preprocess_menu_link())

May write tests later.

grndlvl’s picture

Status: Active » Needs review
grndlvl’s picture

/me being lazy... :) this is the right one now

rjbrown99’s picture

FWIW, I'm using #22 and it works well, except for the scenario where you have parent/child menus. In that case, the child menu has its active trail set and the class marked as active, but the parent is never set as part of the active trail.

Here's what I did to fix it. This is a short snippet that would go into #22. Instead of this section of the original code:

     //context active menu reaction
     if (!empty($active_paths) && in_array($menu_item['link']['link_path'], $active_paths)) {
        $menu_item['link']['in_active_trail'] = true;
        $menu_item['link']['localized_options']['attributes']['class'] .= ' active';
        $class .= ' active-trail';
     }

I changed it to this:

      // Context Active Trail handling
      // This first stanza searches the menu's children to see if any of them are in the context active trail.
      // If so, we add the active trail class but not the 'active' class, so the menu appears to be expanded.
      if ((!empty($menu_item['link']['has_children'])) && (!empty($menu_item['below'])) && $depth != 0) {
        foreach ($menu_item['below'] as $below => $item) {
          if (!empty($active_paths) && in_array($item['link']['link_path'], $active_paths)) {
            $menu_item['link']['in_active_trail'] = true;
            $class .= ' active-trail';
          }
        }
      }

      // This handles the actual active menu item. It is unaware of any parents so this will set the active
      // class regardless of what level the menu appears.
      if (!empty($active_paths) && in_array($menu_item['link']['link_path'], $active_paths)) {
        $menu_item['link']['in_active_trail'] = true;
        $menu_item['link']['localized_options']['attributes']['class'] .= ' active';
        $class .= ' active-trail';
      }
othermachines’s picture

#22 (thomjjames) worked splendidly-- thanks!

benleivian’s picture

Thanks! That did the trick.

bradjones1’s picture

Status: Needs review » Reviewed & tested by the community

To help move this along: I required a patch to context in order to have menu path reactions affect menus in blocks. #41 appears to be the most succinct method of fixing this particular problem. The patch applied cleanly and works for me against 7.x-3.x-dev.

Patching this module for this narrow issue appears to be a more elegant solution than recommending work-arounds in theme templates.

I'm going to be bold and mark this RTBC - does a maintainer have a perspective on this?

rjbrown99’s picture

Does #41 handle the parent/child menu issue described in #42? If not I'd say this is needs work.

bradjones1’s picture

@rjbrown99: This ticket dates back to 2009 and was originally tagged to the 6.x version. I think the advent of hook_preprocess_HOOK in D7 may now 2 years later address the issue raised, even if it doesn't backport directly to 6.x versions of context.

#42 refers back to #22 which is a theme function suggestion, not a patch to context. Perhaps this thread should be honed in to D7 and if there's a backport or other solution needed for D6, that can be handled separately. Thoughts?

febbraro’s picture

Status: Reviewed & tested by the community » Fixed

Committed the patch in #41. Could use more testing to know if it fixes #42, in my limited testing the path to the root of the menu was labeled as active. In any case this fixes part of the issue so I figured i would get it in (I'll be rolling a new release tomorrow I think) If it does not fix #42, then we can reopen this.

http://drupalcode.org/project/context.git/commit/289025b

arnemaine’s picture

Version: 7.x-3.x-dev » 6.x-3.0

Does the current 6x-3.0 version of Context have a patch to correct this issue?

grndlvl’s picture

Due to the restrictions of Drupal < 7 the module cannot fix this issue. You would have to use one of the fixes above.

othermachines’s picture

Status: Fixed » Active

I was hopeful, but in special circumstances it appears that the preprocessor (context_preprocess_menu_link) is reached before context has time to execute active contexts.

In my case, I've got a menu inside a panel pane. I'm using page_manager (ctools).

What's going on, as best as I can figure:

It appears that when ctools_context_handler_render_handler('panels_panel_context_render') is called from page_manager_node_view_page(), the page is being built on this line:

$info = $function($handler, $contexts, $args); ---> Checking active contexts... what? Nothing?

... which occurs before this line:

drupal_alter('ctools_render', ...) ---> Let's go set active contexts! (via context_ctools_render_alter)

Is this even fixable in this module or should I hassle someone else? I've been trying to come up with even a sloppy workaround but either I'm too tired or it's particularly sticky.

Running context 7.x-3.0-beta2 with ctools 7.x-1.0-rc1 with page_manager and panels 7.x-3.0-alpha3.

othermachines’s picture

Following up on #51:

Not sure if this is the most ideal workaround, but I came up with a 7.x patch that adds a preprocess_panels_pane() function to precede context_preprocess_menu_link(). Before I attach it, since the previous patch has been committed, I'm wondering if a new issue might be in order for this?

In context.module:

/**
 * Preprocessor for theme('panels_pane'). 
 *
 * We're intercepting to ensure node conditions are registered before menus 
 * inside panel panes are rendered; menu_link preprocessor below finishes 
 * the job.  A static variable is used since this only needs to happen
 * once. See issue http://drupal.org/node/586396#comment-5025310.
 */
function context_preprocess_panels_pane(&$variables) {
  static $set;
  foreach ($variables['display']->context as $context) {
    if (!$set) {
      if (in_array('node', $context->type) && !empty($context->data)) {
        context_node_condition($context->data, 'view');
        $set = TRUE;
        break;
      }
    }
  }
}

I'm not 100% sure this should only be triggered once (thus the static variable). Some insight on this would be awesome.

This can also be added to sites/all/themes/mytheme/template.php. I have both since I'm using a couple of non-standard conditions. Mine is below. (Notice the line context_node_condition($context->data, 'view'); is absent; you'll need it if you're only changing template.php.)

function mytheme_preprocess_panels_pane(&$variables) {
  static $set;
  // A workaround for issue http://drupal.org/node/586396#comment-5025310
  foreach ($variables['display']->context as $k => $c) {
    if (!$set) {
      if (in_array('node', $c->type) && !empty($c->data)) {
        // context_og condition.
        context_og_context_page_reaction();
        // context_og condition.
        $group = og_context();
        $plugin = context_get_plugin('condition', 'context_og_condition_group_type');
        if ($plugin) {
          $plugin->execute($group);
        }
        $set = TRUE;
        break;
      }
    }
  }
}

Cheers-

timcosgrove’s picture

#41 assumes that the menu link is actually displaying when the context is active. If the context tries to activate a menu link that is nested and unexpanded this patch will not help.

Subscribing.

abdelatifs’s picture

Hi guys,
Does anyone figured this by now without using any snippets ?
For some reasons I get white screen of death whenever I put any of those snippets in my template.php file.
Thanks for your help guys.

othermachines’s picture

@abdekatifs: Update to context 7.x-3.0-beta2.

castawaybcn’s picture

I know this is an old issue, but I am getting the same wsods as @abdelatifs, did you find a solution to this?
My bad, actually the solution in #30 worked like a charm for 6.x, thanks so much!

majorbenks’s picture

As far as I see: this problem exists also in 7.x beta 5. Or did I missed something?

tom92’s picture

It does not work in 7.x and none of the template work arounds are working at my site..

tom92’s picture

Version: 6.x-3.0 » 7.x-3.0-beta6
illmatix’s picture

Which is the last patch that was suggested for Drupal 7.x?

Arnion’s picture

I hope this helps. You have to update the context after applying the patch.

mErilainen’s picture

Status: Closed (duplicate) » Needs work

Patch seems to work, but also broke the active menu item condition which I have used in another context. All the menu items are still selected, but won't activate the context. Using a path condition works, but the site is multilingual, so it's easier to select the main menu items than write several lines of path selectors.

sagannotcarl’s picture

Status: Active » Closed (duplicate)

Seems to me like this is a duplicate of #835090: Context Reaction: Set menu trail (unless I'm missing something about the differences).

anou’s picture

Status: Needs work » Closed (duplicate)

Didn't read every comment (sorry) but I must say that for D6 context will not "active-trail" the menu item if it is configured via views menu option.

not flagrant... I talked to fast... can't make it work...

So I finally made it work with the help of #13 and the help of this post. Here's the final code for D6.28 and Context 6.x-3.1 :
(Everything goes in template.php)

<?php 
/**
* Implementation of theme_menu_item().
*/
function phptemplate_menu_item($link, $has_children, $menu = '', $in_active_trail = FALSE, $extra_class = NULL) {
  static $zebra = FALSE;
  $zebra = !$zebra;
  $class = ($menu ? 'expanded' : ($has_children ? 'collapsed' : 'leaf'));
  if (!empty($extra_class)) {
    $class .= ' ' . $extra_class;
  }
  if ($in_active_trail) {
    $class .= ' active-trail';
  } else {
    // Get the link's URL (sadly, this function doesn't include the link object)
    $url_pattern = '/<a\s[^>]*href=\"([^\"]*)\"[^>]*>.*<\/a>/siU';
    preg_match($url_pattern, $link, $matches);
    $link_path = substr_replace($matches[1], '', 0, 1); // remove first slash
    
    $active_paths = _menu_block_context_active_values('menu');

    // Check against the path
    if (in_array($link_path, $active_paths)) {
      $class .= ' active-trail';
    }
  }

  if ($zebra) {
    $class .= ' even';
  }
  else {
    $class .= ' odd';
  }
  return '<li class="' . $class . '">' . $link . $menu . "</li>\n";
}

function _menu_block_context_active_values($context_name) {
  $contexts = context_get();
  $active_paths = array();

  // If there aren't any contexts available, then there aren't any
  // context-defined active paths.
  if (!is_array($contexts['context'])) {
    return $active_paths;
  }

  foreach ($contexts['context'] as $context) {
    if (array_key_exists($context_name, $context->reactions)) {
      $active_paths[$context->reactions[$context_name]] = $context->reactions[$context_name];
    }
  }
 
  return $active_paths;
} 
?>

I must say that I really got used to D7 and working in D6 is harder then before :-)

Karsa’s picture

I created a patch for this bug, please see #835090: Context Reaction: Set menu trail

malapeiro’s picture

hi, dont know how to code, but i solve this issue with menu position module (https://drupal.org/project/menu_position) instead of context module. it works for me!