This took me a while to find.
We can't use
THEME_menu_link() because it has no count and no context
THEME_menu_tree() because the child items are already rendered into HTML
THEME_preprocess_menu_tree() also only has the rendered children available
There didn't seem to be any drupal_alter I could intercept between when the menu array was built menu_tree_output() and when it was sent for rendering (eg menu_block_view()
Eventually I found that I could get at the raw list of links early enough with THEME_preprocess_menu_block_wrapper() and insert the appropriate attributes into the render array there.
/**
* Preprocesses menus being rendered in blocks to add zebra-striping classes to
* each menu item.
*
* Desired output has odd/even classes like:
*
* <ul class="menu">
* <li class="first leaf has-children menu-mlid-346 even"><a href="/racing">Racing</a></li>
* <li class="leaf menu-mlid-347 odd"><a href="/recreational">Recreational</a></li>
* <li class="leaf menu-mlid-348 even"><a href="/get-sailing">Get into Sailing</a></li>
* <li class="last leaf menu-mlid-349 odd"><a href="/clubs">Clubs</a></li>
* </ul>
*/
function THEME_preprocess_menu_block_wrapper(&$variables, $hook) {
$zebra = 0;
foreach (element_children($variables['content']) as $mlid){
$variables['content'][$mlid]['#attributes']['class'][] = ($zebra % 2) ? 'even' : 'odd';
$zebra++;
}
}
Comments
The even/odd classes are
The even/odd classes are backwards in this code.
($zebra % 2) ? 'odd' : 'even'
Should be:
($zebra % 2) ? 'even' : 'odd'
Fixed code block, for convenience:
UPDATE: fixed original code above.
Don't think it's made clear
Don't think it's made clear here, but to do this you need to be using the menu_block module for your menus!
Also, it doesn't take into account sub-menus - here's my take: