Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

(just got reccommended to post this over here from stack overflow...)

I am just starting with Wordpress (defecting from Joomla)- having a bit of difficulty getting started.

One thing I am trying to do is make a custom plugin that allows the user to add custom backgrounds to the site, based on the active menu item.

So what I am trying to do is get the active menu id (like 'menu-item-xx' that is added to the nav li's) and active parent menu id so I can add these to the body classes.

Is this something I can get from anything built into Wordpress or is this something I will need to make a custom for?

Any pointers most welcome...

UPDATE

I have solved this now with a custom function that you can find below

share|improve this question
    
If there's an active menu item, then there's probably an active page or post that you can check for to add a class. There's also the 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 called menu-whatever on the body. –  helenhousandi Nov 9 '11 at 2:25
    
I understand about what you are saying about semantics. I have added a function below that does actually get what I need which is the actual menu item id. There is nothing to stop the class being added to be active-menu-item-xx or whatever if someone wants to change it to that. The point is that the actual class reflects the active menu item. This is the actual answer to my question I believe, so please vote it up if you agree ;) –  David O'Sullivan Nov 10 '11 at 19:32
add comment

4 Answers

From my comment earlier: Use the body_class() function in your header.php file or wherever your body tag is, e.g. <body <?php body_class(); ?>>. This will give you an output with a bunch of classes on the body that you can then use in your CSS. For example, <body class="page page-id-114 page-parent page-template-default logged-in admin-bar">. You can also use the body_class filter to add more classes. If you want to add the slug, for instance, you would global $post and then use $post->post_name.

share|improve this answer
    
Thanks for your help there. I already have the body_class() function in efeect actually... Thing is I need to attach styles specifically to the menu, because my clients want to have a background based on which menu section of the site the user is viewing. I appreciate that I could style based on 'categories' etc but from a UX pov for the user to add an image to a menu item is what they want to be able to do... –  David O'Sullivan Nov 9 '11 at 10:44
    
So... your original question is backward or not the real question? You're asking how they can add an image to a menu item? –  helenhousandi Nov 9 '11 at 15:10
    
Hey Helen, no what I'm after is a way to get the active menu item id and add it to the list of body classes. I have got the ability to add an image to a menu item, I just want that image to show as a background to the whole page. Thats why I need to give the body a class that relates to the active menu item ;) I think I am nearly there now, I'll post a solution when I am done... –  David O'Sullivan Nov 10 '11 at 12:25
add comment

I have tried getting the Page slug but it seems to be empty in wp_head but you can get the page id and assign it to the body class like so:

add_action('wp_head', 'bodyclassReplacer');
function bodyclassReplacer() {

    global $wp_query;
    $thePostID = $wp_query->post->ID;
    echo str_replace('<body>', '<body class="page'. $thePostID .'">', '<body>');
}

.
After you got a class you can assign a background using css like this:

body.page6 {
    background:url("images/background6.png") no-repeat;
}

.
ps. it was fun finding the solution :) - hope this helps,
cheers, Sagive

. As for Dynamic Menu Highlighting- here is a code that would do that:

add_filter( 'nav_menu_css_class', 'additional_active_item_classes', 10, 2 );

function additional_active_item_classes($classes = array(), $menu_item = false){

    if(in_array('current-menu-item', $menu_item->classes)){
        $classes[] = 'active';
    }

    return $classes;
}
share|improve this answer
    
I'll have another look at that, but I think I have already tried it. i think that gives you the page ID but not the active menu item id which is what I am after- I'll double check though- thanks for your advice though! –  David O'Sullivan Nov 9 '11 at 10:48
    
i can give you a simple script to do that.. CHeck out the added info to my answer.. –  Sagive SEO Nov 9 '11 at 13:52
    
Thanks again Sagive, not quite what I am after still though. That second code for 'Dynamic Menu Highlighting' adds 'active' to the active menu item itself, what I am after is the ability to add the id of the active menuitem (and/or its parent) to the list of body classes so that if a menuitem with the id 'menu-item-49' is active then 'menu-item-49' is added to the body classes and if 'menu-item-49' is not a 'top level' menu item its parent menu item id is added as well. –  David O'Sullivan Nov 9 '11 at 14:34
    
This way I can modify the 'Custom Menu Images' plugin so that the added images are actually 'Page Body Backgrounds'. I know there is a 'Page Background' option in appearance, but I want to give the user the option of being able to change these on a per-menu-item basis... That plugin generates a css that targets a menu item li by its menu id, so if I can add that menu item id to the page then I can modify the outputted css so that the image is actually a page background rather than a menu item image –  David O'Sullivan Nov 9 '11 at 14:37
add comment

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 ;)

share|improve this answer
add comment

Ok my last shot was a while ago now and I was a bit of a novice- I look at that now and its embarassing! I really did not get Wordpress then!

This is what you need...

function ics_get_active_menu_item_ids(){
$menus = wp_get_nav_menus();
$menu_menu_items = array();
$current_menu_items = array();
$current_menu_items['parents'] = array();
$current_menu_items['ancestors'] = array();
foreach($menus as $menu)
    {
    $menu_menu_items[] = wp_get_nav_menu_items($menu->term_id);
    }
foreach ($menu_menu_items as $menu_items)
    {
    foreach($menu_items as $menu_item)
        {
        if ($menu_item->current == 1)
            {
            $current_menu_items['current'] = $menu_item->ID;
            }
        if ($menu_item->current_item_parent == 1)
            {
            $current_menu_items['parents'][] = $menu_item->ID;
            }
        if ($menu_item->current_item_ancestor == 1)
            {
            $current_menu_items['ancestors'][] = $menu_item->ID;
            }
        }
    }
    $current_menu_items['parents'] = array_values(array_unique($current_menu_items['parents']));
    $current_menu_items['ancestors'] = array_values(array_unique($current_menu_items['ancestors']));
return  $current_menu_items;
}

returns the current item id along with parents and ancestors ;)

share|improve this answer
    
You also need to add a filter to wp_get_nav_menu_items that calls:- _wp_menu_item_classes_by_context( $menuItems ); for the above to work –  David O'Sullivan Jun 7 '12 at 17:33
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.