I think megamenu is a very nice module and has a feature!

After looking at multiple issues in theme_megamenu_menu_tree() I decided to refactor the function, so it's now much easier to fix bugs or make enhancements without 3 levels of cut&paste (or even 4 levels - 886652)

By the way my implementation (together with _megamenu_get_menu_tree() change http://drupal.org/node/1198976#comment-4669450) makes number of menu levels unlimited.

I tried to include fixes for the following issues, please review.

#1198976: Warning: Invalid argument supplied for foreach() in i18nmenu_localize_tree() (line 114 of sites/all/m
#886652: Can I add an extra degree of depth/nesting to the megamenu?
#1078694: Mega menu doesn't allow query strings in menu paths
#1170472: let "nolink" be handled by "special menu items" module in order to allow compatibility with "menu_attributes" module
#1195348: megamenu omits link parameters
#1172776: Make MEGA only one menu item?
#865892: Menu items that are not links
#799280: Ability to inject custom css classes into each level of the menu - menu attributes compatibility

I couldn't include also the patch http://drupal.org/files/issues/0001-fix-1170472-use-theme_menu_link-to-r... as it's a bit too much for me ;) If @axel.rutz could have a look at my change and apply his patch?

I'm not setup for creating patches (yet), so I attach the file.

Comments

alexbk66-’s picture

And just in case, here's the function:


function theme_megamenu_menu_tree($menu_name) {

  $menutree = _megamenu_get_menu_tree($menu_name);

  if (function_exists('i18nmenu_localize_tree')) {
    i18nmenu_localize_tree($menutree);
  }

  return theme_megamenu_menu_tree_helper($menu_name, $menutree, 1);
}

And a couple of helper functions:


function theme_megamenu_menu_tree_helper($menu_name, $item, $level) {
  $ul_classes = array('', 'megamenu-menu', 'megamenu-bin', 'megamenu-items');
  $li_classes = array('', 'megamenu-parent', 'megamenu-slot', 'megamenu-item', 'megamenu-subitem');
  $h_classes = array('',  'h2', 'h3', 'h4', 'h5');
  
  $minimize_html = TRUE;
  
  $position = 0;
  $leaf_count = count($item);
  
  foreach ($item as $leaf) {
  
    // Nested call
    if ($leaf['below']) {
      $items_list = theme_megamenu_menu_tree_helper($menu_name, $leaf['below'], $level + 1);
    }
    else {
      $items_list = NULL;
    }

    $position++;
    // are we active / active-trail ?
    $active = _megamenu_active_classes($leaf);
    
    $mlid = $leaf['link']['mlid'];
    $link_options['attributes'] = array('class' => $active/* . ' menu-' . $mlid*/); // No need for mlid in class

    // http://drupal.org/node/799280
    if(is_array($leaf['link']['options']['attributes'])) {
      $link_options['attributes'] = array_merge($link_options['attributes'], $leaf['link']['options']['attributes']);
    }
    
    // http://drupal.org/node/1078694
    // do we have a query string
    if(isset($leaf['link']['options']['query'])){
      $link_options['query'] = $leaf['link']['options']['query'];
    }
    
    // This <li> content
    // TEMP - TODO: if no children - change 'hx' to 'leaf'
    $menu_title = _megamenu_get_translated_menu_title($menu_name, $mlid);
    
    // Create $data to add to $leaf_item
    $data = '<';
    // Opening header tag
    $data .= $h_classes[$level];
    $data .= ' class="' . $li_classes[$level] . '-title';
    // http://drupal.org/node/1170472
    if ($leaf['link']['router_path'] == 'nolink') {
      $data .= ' nolink">' . $menu_title;
    }
    else {
      $data .= '">' . l($menu_title, $leaf['link']['href'], $link_options);
    }
    // Closing header tag
    if (isset($items_list)) {
      $data .= '</' . $h_classes[$level] . '>';
    }
    
    $data .= $items_list;

    $leaf_item = array();
    
    if($minimize_html == FALSE) {
      $leaf_item['id'] = 'megamenu-mlid-' . $mlid;
      $leaf_item['class'] = $li_classes[$level] . '-' . _megamenu_count_attributes($position, $leaf_count);
    }
    
    $leaf_item['data'] = $data;
    $leaf_item['class'] .= ' ' . $li_classes[$level] . $active;
    // http://drupal.org/node/1172776#comment-4674980
    $leaf_item['class'] .= isset($items_list) ? ' has-children' : ' no-children';
    $leaf_items[] = $leaf_item;
  } // END leaf iteration
  
  // Build leaf list
  $list_options = array( 'class' => $ul_classes[$level] . ' ' . _megamenu_menu_attribute_by_level($menu_name, $level) );
  if ($level == 1) {
      $list_options['id'] = 'megamenu-' . $menu_name;
  }
  $items_list = theme('item_list', $leaf_items, NULL, 'ul', $list_options);
  return _megamenu_strip_list_wrapper($items_list);
}

function _megamenu_menu_attribute_by_level($menu_name, $level) {
// TODO: cache
  switch ($level) {
    case '3':
      /* TODO: temp value, should be attached to twig level in admin interface. */
      return ' ' . _megamenu_get_slot_attributes_by_name($menu_name); 
      
    case '2':
      /* TODO: temp value, should be attached to branch level in admin interface */
      return ' megamenu-slots-' . _megamenu_get_slot_orientation_by_name($menu_name); 
      
    case '1':
      $skin = _megamenu_get_skin_by_name($menu_name);
      $menu_orientation = _megamenu_get_menu_orientation_by_name($menu_name);
      return ' ' . $menu_orientation . ' megamenu-skin-' . $skin;
  }
}
alexbk66-’s picture

I added $minimize_html = TRUE; as my taxonomy menu has 500 items, so by removing unused classes and attributes I reduce the html size significantly. I am going to make it configurable, but for now it should be changed to FALSE.

alexbk66-’s picture

StatusFileSize
new6.05 KB

And I move here my refactored _megamenu_get_menu_tree() from #1198976: Warning: Invalid argument supplied for foreach() in i18nmenu_localize_tree() (line 114 of sites/all/m

function _megamenu_get_menu_tree($menuname) {
  $menutree = menu_tree_all_data($menuname);
  $menutree_page = menu_tree_page_data($menuname); // Contains active trail
 
  _megamenu_get_menu_tree_helper($menutree, $menutree_page, 1);
  
  return $menutree;
}
/*
 * On top level $item = $menutree, $page_item = $menutree_page
 */
function _megamenu_get_menu_tree_helper(&$item, $page_item, $level = 1) {
  foreach ($item as $tier_key => $tier_item) {
    if ($page_item[$tier_key]['link']['in_active_trail']) {
      $item[$tier_key]['link']['in_active_trail'] = TRUE;
    }
    
    if ($tier_item['link']['hidden'] == 1 || empty($tier_item['link']['link_title'])) {
      unset($item[$tier_key]);
    }
    else {
      if ($tier_item['below']) {
        if ($level < 4) {
          _megamenu_get_menu_tree_helper($item[$tier_key]['below'], $page_item[$tier_key]['below'], $level + 1);
        }
        else {
          dsm($item[$tier_key]['below'], 'Removing');
          unset($item[$tier_key]['below']);
          $item[$tier_key]['below'] = FALSE;
        }
      }
    }
  }
}
alexbk66-’s picture

And I think that with the new theme_megamenu_menu_tree() implementation _megamenu_get_menu_tree() is no longer necessary, the check for active menu item can be easily moved to theme_megamenu_menu_tree_helper() or _megamenu_active_classes().

If maintainers of the module are interested in my changes, I can do this one also.

Anonymous’s picture

Thanks for your hard work on this. Eric or I will try to review this soon.

Anonymous’s picture

Status: Active » Needs review
alexbk66-’s picture

StatusFileSize
new10.2 KB
new16.56 KB

I've split up the theme_megamenu_menu_tree_helper() function in smaller functions - I tried to implement #1172776: Make MEGA only one menu item?, but don't have time anymore.

I've got some hacky code there (commented with //HACK) which actually does work, but it's not nice. So if the items at second level don't have children - they are displayed as level 3 items, in single slot. Image attached.

I guess it's simpler to do that in _megamenu_get_menu_tree_helper() instead - if list of items doesn't have children - insert an extra level (single 'nolink' line) and move the list to this line children. Then the hack can be removed from theme_megamenu_menu_tree_helper().

And the file attached.

alexbk66-’s picture

Hi there, how is review going? I think that original code is a bit too messy and before doing any fixes/enhancements it should be refactored. I spent already some time cleaning the code - using nested call instead of having 3 or 4 FOREACH levels. Would be nice if this code could be used.

Anonymous’s picture

Thanks for your hard work on this. If you don't mind taking a few extra steps it will make things much easier for us. First, download the coder module. Coder will assist you in cleaning up the code and ensuring it conforms with Drupal conventions. Second, please submit your modifications as a patch.

If you need help with making patches, let me know.

tami.allen’s picture

Would love to see the patch file for this. I need Main Menu items as placeholders. I'm using D7 with a subtheme of Marinelli and I'm unable to get to work even after applying the patch in http://drupal.org/node/1170472. I have installed/enabled the 7.x-1.x dev version of Mega Menu and Special Menu Items 7.x-1.0. When editing a menu item, the description says to use "nolink" but every time I try I get this error: "The path "nolink" is either invalid or you do not have access to it."

Is it possible for me to pull the nolink function from your .txt file (lines 238-253?)? If so, where do I paste it?

dipole’s picture

Hi,

I would like to know if it's possible to add a class for parent items that do not have children in version 7. would appreciate any help.

Thanks in advance!

bomarmonk’s picture

This looks like a great patch. Can someone run this through the coder module and submit it as a regular patch file? If I get a chance, maybe I'll give it a go!

sittard’s picture

#3 works for me but you need to remove the following:
dsm($item[$tier_key]['below'], 'Removing');

The dsm function requires Devel.

alexbk66-’s picture

Yeah, this was just for debugging in case taxonomy has more than 3 levels

alexbk66-’s picture

StatusFileSize
new6.05 KB
new10.53 KB

I'm really sorry I didn't make a patch, I have to start learning patching. As my changes (refactoring) are pretty significant, I attached my version of two files, hope this helps to make this beautiful module even better!

I added .txt as drupal doesn't allow .module or .inc extensions.

alexbk66-’s picture

Version: 6.x-2.x-dev » 6.x-2.0-beta2
StatusFileSize
new16.15 KB

I finally learned how to create patches, well, not completely, see http://drupal.org/node/1054616#comment-5725064, help appreciated.

Here's the patch against 6.x-2.0-beta2 (I hope)

Anonymous’s picture

Priority: Normal » Critical
Anonymous’s picture

Assigned: Unassigned »
Issue tags: +multifix
greggmarshall’s picture

Status: Needs review » Reviewed & tested by the community

Once I got past a problem applying the patch, the code that resulted worked perfectly!

Thank you for this.

alexbk66-’s picture

My pleasure @greggmarshall, it's my first Drupal patch :)

oktay’s picture

Any word on if & when this will be incorporated into the official code?

Anonymous’s picture

I haven't had time to give it a spin. Alexbk66, would you also take a stab at rolling the patch against the dev branch?

halloffame’s picture

The patch only applied partially against 6.x-2.0-beta2. So decided to manually applied it but after doing so I can't still find the functionality/fixes I was expecting as mentioned in the original post.

Can anybody else please test the patch and report back?

ram4nd’s picture

Assigned: » Unassigned
Issue summary: View changes
Status: Reviewed & tested by the community » Fixed
Issue tags: -multifix

Looks like this has been committed long time ago.

Status: Fixed » Closed (fixed)

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