Auto-expand parent menu item(s) for active menu item

jondblackburn - December 9, 2008 - 19:08
Project:JQuery menu
Version:6.x-2.3
Component:Miscellaneous
Category:support request
Priority:minor
Assigned:Unassigned
Status:needs review
Description

I just installed and tested jquery menu, and I like it lot.

My only problem is that it does not automatically expand the parent menu item(s) for page you are visiting.

It sure would be nice if it could do this - but I cannot seem to be able to figure out a way just using CSS.

Maybe, this could be a future feature request -OR- if someone has a patch or suggested method for adding this functionality.

I do know a bit of PHP, but I am not a hard-core coder.

#1

jondblackburn - December 10, 2008 - 21:25
Category:feature request» bug report

Looking through the code for the module (to see if it was themable) . . . I see that apparently, this functionality is supposed to be here already

// If the menu item is expanded or in the active trail and if has children add the "open" class.
    if (!empty($item['link']['expanded']) || (in_array($item['link']['link_path'], $url_array) && !empty($item['link']['has_children']))){
      $classes[] = 'open';
      $state = 'open';
    }

So, I am changing this to a bug report - though there is obviously the possibility that I am doing something wrong.

More Explanation - added 12/10/08

P.S. Please let me know if I am understanding the code above incorrectly, but it seems like any menu item(s) in the "active trail" should be open/expanded by default.

E.G. If you have ...

Menu Item 1
- SubMenuItem 1
- Page 1
- Page 2

And you are on Page 2

Then, Menu Item 1 and SubMenuItem1 should both have the "open" class - expanding both options when on that page.

Is this correct?

#2

Aaron Hawkins - December 17, 2008 - 23:40
Category:bug report» support request
Priority:normal» minor
Status:active» postponed (maintainer needs more info)

Where is the block you are using? Did you put in the primary links section? Some themes remove the active trail and menus placed in the primary links section almost always have them removed. Go to http://www.pixelclever.com/drupal-theme-conversion-psd-or-fireworks-files and look how the menu responds to the active trail. I use this module on at least 5 themes on separate host without the issue you mentioned, so until I see evidence to the contrary I consider this a theme issue.

#3

Rob T - December 24, 2008 - 22:49

I'm experiencing the same issue, no matter what theme I use. My main theme is based on Basic, but all the core Drupal 6.x themes yield the same result. My menu is a custom one. Many of the links point to spots that are views-like (versus actual nodes), so I am unsure if that has anything to do with anything.

In my custom menu-jquerymenu block, I'm not getting my menu's "li" tagged w/ "active-trail". Only the current page's "a" tag gets an "active".

In my primary links area, "active-trail" tagging seems to work fine.

UPDATE: When I use the jquerymenu block for a primary links block, it works as advertised, but only to a depth of 1. Further tiers still yield the closed parents.

Any suggestions or advice?

#4

Aaron Hawkins - December 30, 2008 - 18:36

Could you show me a link to a page that is having this happen so that I can take a look at the classes that are in place? Try it out on a standard theme such as Garland and tell me if it shows up still. If it does then there is something else besides a theming issue coming up. The module makes use of the active trail that is handed to it by the Drupal system on a per page basis, so if the active trail isn't there then there isn't much my module can do about it. Usually though this kind of thing is related to theme functions that override classes or strip them from the menu before displaying.

Really I can't do anything unless I see an example of this error in action since it is not happening on any of my sites.

#5

yhancik - January 14, 2009 - 15:51

I don't have any online example for now, but here's what I get with Garland, on a custom menu :

<ul class="menu jquerymenu" id="jquerymenu-">
<li class="parent closed"><span class="parent closed"></span><a href="/_work/yhnck/?q=node/5">Title1</a>
<ul><li class="active-trail"><a href="/_work/yhnck/?q=node/6" class="active">Item1</a></li></ul></li></ul>

clicking on Item1 closes the Title1 level

VS the administrative menu

<ul class="menu jquerymenu" id="jquerymenu-">
<li><a href="/_work/yhnck/?q=blog/1">My blog</a></li>
<li><a href="/_work/yhnck/?q=user/1">My account</a></li>
<li class="parent open active-trail"><span class="parent open active-trail"></span><a href="/_work/yhnck/?q=node/add">Create content</a>
<ul><li class="active-trail"><a href="/_work/yhnck/?q=node/add/blog" title="" class="active">Blog entry</a></li><li><a href="/_work/yhnck/?q=node/add/book" title="">Book page</a></li>
(...)

--

edit

Obviously, menu_get_active_trail() skips the parent node when clicking on a child.

thus, if the (working) administrative menus have this $url_array

array (
0 => '',
1 => 'node/add',
2 => 'node/add/story',
)

the custom menu returns

array (
0 => '',
1 => 'node/6',
)

when it should be

array (
0 => '',
1 => 'node/5',
2 => 'node/6',
)

Now let's figure out why...

Could it be some kind of incompatibility with another module ? (since I'm using Garland, here)

#6

miiimooo - January 20, 2009 - 18:47

It's a problem with the activemenu. If the menu you're using isn't drupal's active menu it will set the trail according to the one that is active ('navigation' by default).
For instance if you put this:

<?php
function jqmenu_trail_creator() {
   
menu_set_active_menu_name("name of your menu that jquery menu wraps around");
?>

then it work correctly.

Is there a better way of doing this though?

#7

miiimooo - January 20, 2009 - 18:51

Didn't take long and I found how to do it properly. Here's the code for the function - it only differs on three lines:

<?php
function jquerymenu_block($op = 'list', $delta = 0, $edit = array()) {
 
$result = db_query("SELECT mid, menu_name FROM {jquerymenus}");
 
$enabledmenus = array();
  while (
$enabled = db_fetch_object($result)) {
   
$enabledmenus[] = $enabled->menu_name;
  }
  switch (
$op) {
    case
'list':
     
$x = 0;
      foreach (
$enabledmenus as $name) {
       
$title = db_result(db_query("SELECT title FROM {menu_custom} WHERE menu_name = '%s'", $name));
       
$blocks[$x]['info'] = $title .' - Jquerymenu';
       
$blocks[$x]['cache'] = BLOCK_NO_CACHE;
       
$x++;
      }
    return
$blocks;

    case
'view':
     
$d = 0;
      global
$user;
//       $trail = jqmenu_trail_creator();
     
$old_activemenu = menu_get_active_menu_name();
      foreach (
$enabledmenus as $menuname) {
        if (
$delta == $d) {
          if (
$menuname == 'navigation' && !empty($user->uid)) {
           
$title = $user->name;
          }
          else {
           
$title = db_result(db_query("SELECT title FROM {menu_custom} WHERE menu_name = '%s'", $menuname));
          }
         
menu_set_active_menu_name($menuname);
         
$trail = jqmenu_trail_creator();
         
$block['subject'] = $title;
         
$menutree = menu_tree_all_data($menuname);
         
$block['content'] = theme('menu_creation_by_array', $menutree, $trail, $menuname);

        }
       
$d++;
      }
     
menu_set_active_menu_name($old_activemenu);
  }
 
//end switch ($op)
 
return $block;
}
?>

#8

honucreative - January 23, 2009 - 09:16

That worked for me. Thanks.

#9

Aaron Hawkins - February 6, 2009 - 19:39

I think there is a module compatibility issue going on here. Some other module or theme function is overriding the active trail. Perhaps this is a reasonable safeguard to insure that it doesn't happen, however I think it would be good to know why this is happening only on a few installations before committing it.

#10

Aaron Hawkins - February 6, 2009 - 19:45
Status:postponed (maintainer needs more info)» patch (to be ported)

#11

Aaron Hawkins - February 7, 2009 - 11:55
Status:patch (to be ported)» fixed

Committed in 2.1.

#12

System Message - February 21, 2009 - 12:00
Status:fixed» closed

Automatically closed -- issue fixed for 2 weeks with no activity.

#13

jaykali - April 16, 2009 - 15:22
Version:6.x-1.5» 6.x-2.3
Status:closed» needs review

The problem with this fix above is that I don't think it works with menus that go deeper than just 1 level. If the jquery menu goes a couple menus deep what happens is that the inner most menu has the class "open" but the parent menus have the class "closed" and so what results is that the menu is closed, which looks like a bug.

Possible fix: I modified recursive_link_creator() in v 6.x-2.3, line 189 to add another condition to look up the $item['link']['href'] in the $url_array using a regular expression to see if $item['link']['href'] is in the same path, if so it makes it open as well. This might not be the cleanest solution, maybe someone else can clean it up, but my initial tests look like it works. If it does, will someone please make a patch and commit? Thanks! -J

// If the menu item is expanded or in the active trail and if has children add the "open" class.
    if (!empty($item['link']['expanded']) || ((in_array($item['link']['href'], $url_array) || ($_GET['q'] == $item['link']['href'])) && !empty($item['link']['has_children']) && !empty($nextlevel))) {
      $classes[] = 'open';
      $state = 'open';
    }////// BEGIN NEW CHANGE ///////////////////
    else {
    /**
    * Go through each url and see if the current url is in the path (meaning it's a parent, if so make it open as well)
    */
    foreach ($url_array as $url) {
    $needle = str_replace('/', '\/', $item['link']['href']);
   
    if (preg_match("/^$needle/", $url)) {
$classes[] = 'open';
      $state = 'open';
      break;   
    }
    }
   
    if ($state != 'open' && !empty($item['below']) && !empty($nextlevel)) {
      $classes[] = 'closed';
    }
    }/////// END NEW CHANGE /////////////////

#14

duckzland - May 19, 2009 - 08:12

// If the menu item is expanded or in the active trail and if has children add the "open" class.
    if (!empty($item['link']['expanded']) || ((in_array($item['link']['href'], $url_array) || ($_GET['q'] == $item['link']['href'])) && !empty($item['link']['has_children']) && !empty($nextlevel))) {
      $classes[] = 'open';
      $state = 'open';
    }////// BEGIN NEW CHANGE ///////////////////
    else {
    /**
    * Go through each url and see if the current url is in the path (meaning it's a parent, if so make it open as well)
    */
    foreach ($url_array as $url) {
    $needle = str_replace('/', '\/', $item['link']['href']);
  
    if (preg_match("/^$needle/", $url)) {
$classes[] = 'open';
      $state = 'open';
      break;  
    }
    }
  
    if ($state != 'open' && !empty($item['below']) && !empty($nextlevel)) {
      $classes[] = 'closed';
    }
    }/////// END NEW CHANGE /////////////////

not working in acquia marina.

 
 

Drupal is a registered trademark of Dries Buytaert.