Walker Nav Menu alteration (with div)

I am working on a custom menu system using the Walker_Nav_Menu function. I have nearly got it working but i cant get through a few barriers which i hope someone can assist on.

What am i trying to achieve?:

Read More
<nav id="menu">
    <ul>
        <li><a href="/">Home</a></li>
        <li><a href="/about-us">About Us</a></li>
        <li>
            <span>Second Layer</span>
            <div>
                <ul>
                    <li><a href="/second-layer/second-layer/">Second Layer</a></li>
                    <li><a href="/second-layer/blah-blah/">blah blah</a></li>
                </ul>
            </div>
        </li>
    </ul>
</nav>

What is it currently doing?:

<nav id="menu">
    <ul>
        <li><a href="/">Home</a></li>
        <li><a href="/about-us">About Us</a></li>
        <li><a href="/second-layer/second-layer/">Second Layer</a>
        <span></span>
            <div>
                <ul>
                    <li><a href="/second-layer/blah-blah/">blah blah</a></li>
                </ul>
            </div>
        </li>
    </ul>
</nav>

I am trying to get the menu so if menu item has child items, it places it within a span and add that menu item as the first item under.

Here is what i have done with the Walker_nav_menu

class Excerpt_Walker extends Walker_Nav_Menu
{
      function start_el(&$output, $item, $depth, $args)
      {
           global $wp_query;
           $indent = ( $depth ) ? str_repeat( "t", $depth ) : '';

           $class_names = $value = '';

           $classes = empty( $item->classes ) ? array() : (array) $item->classes;

           $class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item ) );
           $class_names = ' class="'. esc_attr( $class_names ) . '"';

           $output .= $indent . '<li>';

           $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        ) .'"' : '';
           $attributes .= ! empty( $item->url )        ? ' href="'   . esc_attr( $item->url        ) .'"' : '';


           if($depth == 0)
           {
            $item_output = $args->before;
            $item_output .= '<a'. $attributes .'>';
            $item_output .= $args->link_before .apply_filters( 'the_title', $item->title, $item->ID );
            $item_output .= $description.$args->link_after;
            $item_output .= '</a>';
            $item_output .= $args->after;

            $output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );

           }else if($depth == 1){

            $item_output .= $args->before;
            $item_output .= '<a'. $attributes .'>';
            $item_output .= $args->link_before .apply_filters( 'the_title', $item->title, $item->ID );
            $item_output .= $description.$args->link_after;
            $item_output .= '</a>';
            $item_output .= $args->after;

            $output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );

           }

        }

        function start_lvl(&$output, $depth) {
            $indent = str_repeat("t", $depth);
            $output .= "n$indent" . $item_output = "<span>" . $args->link_before .apply_filters( 'the_title', $item->title, $item->ID ) . "</span>" . "<div><ul>n";
        }


}

Related posts

Leave a Reply

1 comment

  1. Try this code. you’ll notice I have the span tag wrapped around the menu description copy. Feel free to remove that call and put whatever you need in there.

    in you header.php file call the new walker menu like

    <?php
          if (has_nav_menu('primary_navigation')) :
            wp_nav_menu(array('theme_location' => 'primary_navigation','items_wrap' => '<ul id="%1$s" class="%2$s">%3$s</ul>', 'menu_class' => 'nav'));
          endif;
        ?>
    

    //place in functions.php

        class Roots_Nav_Walker extends Walker_Nav_Menu {
      function check_current($classes) {
        return preg_match('/(current[-_])|active|dropdown/', $classes);
      }
    
      function start_lvl(&$output, $depth = 0, $args = array()) {
        $output .= "n<span>Span here</span><div class='down'><ul class="dropdown-menu">n";
      }
    
      function start_el(&$output, $item, $depth = 0, $args = array(), $id = 0) {
    
        parent::start_el($item_html, $item, $depth, $args);
    
        if ($item->is_dropdown && ($depth === 0)) {
    
    
    
          $item_html = str_replace('<a', '<a class="dropdown-toggle" data-toggle="dropdown" data-target="#"', $item_html);
          $item_html = str_replace('</a>', '</a>', $item_html);
    
        }
        elseif (stristr($item_html, 'li class="divider')) {
          $item_html = preg_replace('/<a[^>]*>.*?</a>/iU', '', $item_html);
        }
        elseif (stristr($item_html, 'li class="nav-header')) {
          $item_html = preg_replace('/<a[^>]*>(.*)</a>/iU', '$1', $item_html);
        }
    
        $item_html = apply_filters('roots_wp_nav_menu_item', $item_html);
    
    
        $output .= $item_html;
    
         }
    
      function display_element($element, &$children_elements, $max_depth, $depth = 0, $args, &$output) {
        $element->is_dropdown = ((!empty($children_elements[$element->ID]) && (($depth + 1) < $max_depth || ($max_depth === 0))));
    
        if ($element->is_dropdown) {
          if ($depth === 0) {
            $element->classes[] = 'dropdown';
          } elseif ($depth === 1) {
            $element->classes[] = 'dropdown-submenu';
          }
        }
    
        parent::display_element($element, $children_elements, $max_depth, $depth, $args, $output);
      }
    }
    
    /** remove container */
    function nav_menu_args($args = '') {
      $nav_menu_args['container'] = false;
    
      if (!$args['items_wrap']) {
        $nav_menu_args['items_wrap'] = '<ul class="%2$s">%3$s</ul>';
      }
    
      if (current_theme_supports('bootstrap-top-navbar')) {
        $nav_menu_args['depth'] = 3;
      }
    
      if (!$args['walker']) {
        $nav_menu_args['walker'] = new Roots_Nav_Walker();
      }
    
      return array_merge($args, $nav_menu_args);
    }
    add_filter('wp_nav_menu_args', 'nav_menu_args');