Ok I have sussed out a function to achieve this. I am at the very start of my journey with WordPress so I am not sure about the quality or efficiency of this code. But here it is:-
function get_active_menu_item_ids( $classes )
{
//set up defaults for menu retrieval
$dosmenudefaults = array( 'menu' => '', 'container' => 'div', 'container_class' => '', 'container_id' => '', 'menu_class' => 'menu', 'menu_id' => '',
'echo' => true, 'fallback_cb' => 'wp_page_menu', 'before' => '', 'after' => '', 'link_before' => '', 'link_after' => '', 'items_wrap' => '<ul id="%1$s" class="%2$s">%3$s</ul>',
'depth' => 0, 'walker' => '', 'theme_location' => '' );
$dosargs = wp_parse_args( $dosargs, $dosmenudefaults );
$dosargs = apply_filters( 'wp_nav_menu_args', $dosargs );
$dosargs = (object) $dosargs;
// Get the nav menu based on the requested menu
$dosmenu = wp_get_nav_menu_object( $dosargs->menu );
// Get the nav menu based on the theme_location
if ( ! $dosmenu && $dosargs->theme_location && ( $doslocations = get_nav_menu_locations() ) && isset( $doslocations[ $dosargs->theme_location ] ) )
$dosmenu = wp_get_nav_menu_object( $doslocations[ $dosargs->theme_location ] );
// Get the first menu that has items if we still can't find a menu
if ( ! $dosmenu && !$dosargs->theme_location ) {
$dosmenus = wp_get_nav_menus();
foreach ( $dosmenus as $dosmenu_maybe ) {
if ( $dosmenu_items = wp_get_nav_menu_items($dosmenu_maybe->term_id) ) {
$dosmenu = $dosmenu_maybe;
break;
}
}
}
// If the menu exists, get its items.
if ( $dosmenu && ! is_wp_error($dosmenu) && !isset($dosmenu_items) )
$dosmenu_items = wp_get_nav_menu_items( $dosmenu->term_id );
$dosmenu = $dosmenu_items;
// Get the $menu_item variables
_wp_menu_item_classes_by_context( $dosmenu );
//create empty parents array
$dosparents = array();
//Iterate through the menu items and get the active item and its parent items
foreach ($dosmenu as $dosmenuitem)
{
if ($dosmenuitem->current == '1')
{
$dosactivemenuids['current']= $dosmenuitem->ID;
}
if (($dosmenuitem->current_item_parent == '1')||($dosmenuitem->current_item_ancestor == '1'))
{
$dosparents[$dosmenuitem->menu_order] = $dosmenuitem->ID;
}
if(is_array($dosparents))
{
krsort($dosparents);
foreach ($dosparents as $key =>$value)
{
$dosactivemenuids['parents'][$key]= $value;
}
}
}
//return $dosactivemenuids;
if (is_array($dosactivemenuids['parents']))
{
foreach ( $dosactivemenuids['parents'] as $key=>$value)
{
$classes[] = 'menu-item-'.$value;
}
}
if ($dosactivemenuids['current'] != '')
{
$classes[] = 'menu-item-'.$dosactivemenuids['current'];
}
return $classes;
}
You add that to your templates 'functions.php' and also somewhere after the function add a filter to call it with:-
add_filter( 'body_class', 'get_active_menu_item_ids');
What this does?
What this does is get the active menu ids and adds them to the body classes in ascending order
Why would I need this?
Coming from a CMS background I am used to pages being defined by the menu. With this function the active menu item id and/or its parent item id is added to the body classes so you can add page wide styles based on the active menu item. So for example you may have a menu structure like this:-
->menu-item-1
->menu-item-2
->->menu-item-3
Using this function if you are viewing the page 'menu-item-3' the classes 'menu-item-2' and 'menu-item-3' are added to the body tag in that order. What this means is that you can have a css rule that targets body.menu-item-3 that can fall back to its parent items rule in body.menu-item-2 and ultimately to body if there are no styles for either. What I am using this for, for example, is to have a default background colour for the whole page (body) a background colour for the whole page when menu-item-2 is active (body.menu-item-2) and a different background colour for the page when menu-item-3 is active (body.menu-item-3).
Hope that helps someone ;)
body_class()
function that will generate and output some classes for the body for you. They may not match what's applied to the menu, but semantically I wouldn't put a class calledmenu-whatever
on the body.