'm currently integrating Foundation 5's accordion and WordPress via a walker class. The original was made by AWshout here: https://gist.github.com/awshout/5375157
The side menu on the left is an accordion thing which is working fine until you add a third level of child page. I currently have a Walker class (not sure if you’re familiar with them but they allow WordPress menus to be styled better.)
class Section_Nav_Walker extends Walker_Nav_Menu {
/**
* @see Walker_Nav_Menu::start_lvl()
*
* @param string $output Passed by reference. Used to append additional content.
* @param int $depth Depth of page. Used for padding.
*/
function start_lvl( &$output, $depth = 0, $args = array() ) {
$output .= '<div class="content" data-section-content><ul class="side-nav">';
}
/**
* @see Walker::end_lvl()
*
* @param string $output Passed by reference. Used to append additional content.
* @param int $depth Depth of page. Used for padding.
*/
function end_lvl( &$output, $depth = 0, $args = array() ) {
// close .side-nav .content and .section
$output .= '</ul></div></div>';
}
/**
* @see Walker_Nav_Menu::start_el()
*
* @param string $output Passed by reference. Used to append additional content.
* @param object $item Menu item data object.
* @param int $depth Depth of menu item. Used for padding.
* @param object $args
*/
function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) {
$class_names = $value = '';
$classes = empty( $item->classes ) ? array() : (array) $item->classes;
$classes[] = 'menu-item-' . $item->ID;
$classes[] = ( $depth == 0 ) ? 'title' : '';
$classes[] = ( $args->has_children ) ? 'has-dropdown' : '';
$classes[] = ( in_array('current-menu-item', $classes) && !in_array('active', $classes) ) ? 'active' : '';
$class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item, $args ) );
$class_names = $class_names ? ' class="' . esc_attr( $class_names ) . '"' : '';
$id = apply_filters( 'nav_menu_item_id', 'menu-item-'. $item->ID, $item, $args );
$id = $id ? ' id="' . esc_attr( $id ) . '"' : '';
// create sections
$section_class = ( $depth == 0 && in_array('active', $classes) ) ? 'section active' : 'section';
$section_class = ( $depth <= 1 && in_array('active', $classes) ) ? 'section active' : 'section';
// $section_class = 'section';
$output .= ( $depth == 0 ) ? '<div class="' . $section_class . '">' : '';
// if top level use p.title else use li in dropdown
$output .= ( $depth == 0 ) ? '<p data-section-title' . $id . $value . $class_names .'>' : '<li' . $id . $value . $class_names .'>';
$attributes = !empty( $item->attr_title ) ? ' title="' . esc_attr( $item->attr_title ) . '"' : '';
$attributes .= !empty( $item->target ) ? ' target="' . esc_attr( $item->target ) . '"' : '';
$attributes .= !empty( $item->xfn ) ? ' rel="' . esc_attr( $item->xfn ) . '"' : '';
// if top level and has dropdown do not use url
if ( $depth == 0 && $args->has_children ) {
$attributes .= ' href="#"';
}
// else use url
elseif ( !empty( $item->url ) ) {
$attributes .= ' href="' . esc_attr( $item->url ) . '"';
}
$item_output = $args->before;
$item_output .= '<a'. $attributes .'>';
$item_output .= $args->link_before . apply_filters( 'the_title', $item->title, $item->ID ) . $args->link_after;
$item_output .= '</a>';
$item_output .= $args->after;
// close .section if there is no dropdown
$item_output .= ( $depth == 0 && !$args->has_children ) ? '</div>' : '';
$output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
}
/**
* @see Walker::end_el()
*
* @param string $output Passed by reference. Used to append additional content.
* @param object $item Page data object. Not used.
* @param int $depth Depth of page. Not Used.
*/
function end_el( &$output, $item, $depth = 0, $args = array() ) {
if ( $depth > 0 ) {
$output .= "</li>";
}
}
/**
* Traverse elements to create list from elements.
*
* Display one element if the element doesn't have any children otherwise,
* display the element and its children. Will only traverse up to the max
* depth and no ignore elements under that depth.
*
* This method shouldn't be called directly, use the walk() method instead.
*
* @see Walker::start_el()
* @since 2.5.0
*
* @param object $element Data object
* @param array $children_elements List of elements to continue traversing.
* @param int $max_depth Max depth to traverse.
* @param int $depth Depth of current element.
* @param array $args
* @param string $output Passed by reference. Used to append additional content.
* @return null Null on failure with no changes to parameters.
*/
function display_element( $element, &$children_elements, $max_depth, $depth, $args, &$output ) {
if ( !$element ) {
return;
}
$id_field = $this->db_fields['id'];
//display this element
if ( is_object( $args[0] ) ) {
$args[0]->has_children = ! empty( $children_elements[$element->$id_field] );
}
parent::display_element($element, $children_elements, $max_depth, $depth, $args, $output);
}
}
The problem is that there’s something in that file that can’t work out how to cope with more than one set of grandchildren in a list and that’s when the menu breaks. What I need ideally is something that can cope with a menu like this:
- Parent
- Child
- Grandchild
- Child
- Grandchild
- Child
Any ideas what I might need to change in that file? Have tried a bunch of stuff but every time I just end up reformatting bits – I think that I need to add something that navigates back up a level before closing the list.
I’d really appreciate a hand, Marc