views:

46

answers:

2

is it possible to add some kind of class like 'arrow' or a span inside the menus that have submenus (in Wordpress)? it seems that you can do this is using javascript, but I want to know if there's a PHP solution...

in WP 3.0, I saw that active menus have the "parent" or "ancestor" classes on them, but this is only for active menu, and I need it for inactive ones as well

+1  A: 

I don't know of any native WordPress support for it, but you could easily do it using some jQuery.

<script type="text/javascript">
$("#menu-id ul li:has(ul)").addClass("parent");
</script>
Luke
thanks, I knew that. I was wondering if there's a way to do this with PHP.The problem with the js method is that you get a small "flicker" during the page load, if the menu items have a variable width
Alex
So you're asking for a way to modify the HTML that WP is generating as it generates it, then? There's no built-in support for that or way you can just customise your templates?
Rup
well you can get the entire menu output (a string) and modify it before it gets echoed, but I don't know what I could change there...the menu template is here: http://core.trac.wordpress.org/browser/trunk/wp-includes/nav-menu-template.php
Alex
I have something a bit like this on my WordPress blog. It makes use of an xml to array function and finds out which li items have submenus, then adds a class to them and converts it back to xml. The source of the functions are here: http://mysrc.blogspot.com/2007/02/php-xml-to-array-and-backwards.html
Luke
+2  A: 

This functionality really should be in WordPress core!
Anyway, I had a look at the menu template source you sent in a comment on the other answer, and have found a (rather hacky) way to add a class on menu items with children. It basically subclasses the default walker to extend its default behaviour. It's probably best if you put it in your theme's functions.php. Here's the code:

<?php
class Arrow_Walker_Nav_Menu extends Walker_Nav_Menu {
    function display_element($element, &$children_elements, $max_depth, $depth=0, $args, &$output) {
        $id_field = $this->db_fields['id'];
        if (!empty($children_elements[$element->$id_field])) { 
            $element->classes[] = 'arrow'; //enter any classname you like here!
        }
        Walker_Nav_Menu::display_element($element, $children_elements, $max_depth, $depth, $args, $output);
    }
}
?>

To call it, you'll need to add the walker argument when you call wp_nav_menu() in your theme, like so:

<?php 
wp_nav_menu(array('walker' => new Arrow_Walker_Nav_Menu, [other arguments...]))
?>

Hope that works for you! I've only tested it superficially, but it seems to work. Let me know if there are any edge cases where adding the class fails.

Donald Harvey
holy crap it works! thank you :D
Alex
there is ony situation where it fails: when there's a callback function specified in the arguments (fallback_cb), ie. when you don't have a custom menu created, wp_nav_menu will retrieve menu items from the wp_page_menu() function, which uses a different Walker I think
Alex
Yes - the walker used by wp_page_menu doesn't allow the addition of classes quite so easily. I'll have a look and see if I can think of a workaround over the next couple of days and will edit my answer if I find anything.
Donald Harvey