0

I'm trying to create a custom menu structure that will work with jquery push menu's. http://multi-level-push-menu.make.rs/

All is working fine with the 1st and 2nd level. If I try to add a third level to my menu, everthing goes weird. Obvoiusly this is due to the function only accounting for a second level.

But unfortunately my wordpress knowledge is limited and wont allow me to go any further.

    <?php 

function clean_custom_menu( $theme_location ) {
    if ( ($theme_location) && ($locations = get_nav_menu_locations()) && isset($locations[$theme_location]) ) {
        $menu = get_term( $locations[$theme_location], 'nav_menu' );
        $menu_items = wp_get_nav_menu_items($menu->term_id);

        $menu_list  = '<nav>' ."\n";
        $menu_list .= '<h2><i class="fa fa-reorder"></i>Navigation</h2>' ."\n";
        $menu_list .= '<ul class="main-nav">' ."\n";

        $count = 0;
        $submenu = false;

        foreach( $menu_items as $menu_item ) {
             //var_dump($menu_item);
            $link = $menu_item->url;
            $title = $menu_item->title;
            $classes = $menu_item->classes;
            $description = $menu_item->description;

            if ( !$menu_item->menu_item_parent ) {
                $parent_id = $menu_item->ID;

                $menu_list .= '<li class="item">' ."\n";
                if (!empty($description)) {
                    $menu_list .= '<a href="'.$link.'" class="title"><i class="fa fa-'.$description.'"></i>'.$title.'</a>' ."\n";
                    $menu_list .= '<h2><i class="fa fa-'.$description.'"></i>'.$title.'</h2>' ."\n";
                } else {
                    $menu_list .= '<a href="'.$link.'" class="title">'.$title.'</a>' ."\n";
                }
            }

            if ( $parent_id == $menu_item->menu_item_parent ) {

                if ( !$submenu ) {
                    $submenu = true;
                    $menu_list .= '<ul class="sub-menu">' ."\n";
                }

                $menu_list .= '<li class="item">' ."\n";
                if (!empty($description)) {
                    $menu_list .= '<a href="'.$link.'" class="title"><i class="fa fa-'.$description.'"></i>'.$title.'</a>' ."\n";
                    $menu_list .= '<h2><i class="fa fa-'.$description.'"></i>'.$title.'</h2>' ."\n";
                } else {
                    $menu_list .= '<a href="'.$link.'" class="title">'.$title.'</a>' ."\n";
                }
                $menu_list .= '</li>' ."\n";


                if ( $menu_items[ $count + 1 ]->menu_item_parent != $parent_id && $submenu ){
                    $menu_list .= '</ul>' ."\n";
                    $submenu = false;
                }

            }

            if ( $menu_items[ $count + 1 ]->menu_item_parent != $parent_id ) { 
                $menu_list .= '</li>' ."\n";      
                $submenu = false;
            }

            $count++;
        }

        $menu_list .= '</ul>' ."\n";
        $menu_list .= '</nav>' ."\n";

    } else {
        $menu_list = '<!-- no menu defined in location "'.$theme_location.'" -->';
    }
    echo $menu_list;
}
 ?>
  • Try searching for "custom nav menu walker" – Z. Zlatev Sep 29 '17 at 15:18
1

Seems that nobody has an answer to this question, so I followed @Zlatev advice and created a custom walker class...

Download the plugin from GIT and add it to your theme, add the custom walker below to a include() or directly into your functions.

<?php 
    /**
     * Required plugin
     * https://github.com/adgsm/multi-level-push-menu
     */
    class Push_Menu_Walker extends Walker_Nav_Menu {
        /**
         * Start the element output.
         *
         * @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. May be used for padding.
         * @param  array $args    Additional strings.
         * @return void
         */
        function start_el( &$output, $item, $depth = 5, $args = array(), $id = 0 ) {

            $output .= "<li>";

            $attributes  = '';
            $title = $item->title;
            $desc = $item->description;
            $classes = $item->classes;
                    /*["classes"] => array(8) {
                        [0]=> string(0) "" <-- THIS IS THE CUSTOM CLASS
                        [1]=> string(9) "menu-item" 
                        [2]=> string(24) "menu-item-type-post_type" 
                        [3]=> string(21) "menu-item-object-page" 
                        [4]=> string(17) "current-menu-item" 
                        [5]=> string(9) "page_item"
                        [6]=> string(12) "page-item-50"
                        [7]=> string(17) "current_page_item"
                    }*/
            $font_awesome_class = ' class="fa fa-'. $classes[0] . '"';

            ! empty( $item->url )
                and $attributes .= ' href="'   . esc_attr( $item->url        ) .'"';

            $title = apply_filters( 'the_title', $item->title, $item->ID );

            if (!empty ( $classes[0] )) : // If we have a custom class, add the H2 + icon
                    $item_output = $args->before
                        . "<a $attributes>"
                        .       $args->link_before
                        .       $title
                        . '</a> '
                        . '<h2>'
                        .       '<i ' . $font_awesome_class . '></i>'
                        .       $title
                        . '</h2>'
                        . $args->link_after
                        // . $description <-- Not needed for now...
                        . $args->after;
            else :
                    $item_output = $args->before
                        . "<a $attributes>"
                        . $args->link_before
                        . $title
                        . '</a> '
                        . $args->link_after
                        . $args->after;
            endif;

            // Since $output is called by reference we don't need to return anything.
            $output .= apply_filters(
                'walker_nav_menu_start_el',
                $item_output,
                $item,
                $depth,
                $args
            );
        }
    }
 ?>

Finally call the walker in your theme:

  1. Update the theme_location
  2. Remove the container by creating an empty argument
  3. Call the walker we've just created

<div id="push-nav"> <nav> <h2>Navigation <i class="fa fa-reorder"></i></h2> <?php wp_nav_menu( array( 'theme_location' => 'menu-3', 'container'=>'', 'walker' => new Push_Menu_Walker()) ); ?> </nav> </div><!-- /#page -->

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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