Вопрос

I'm looking for a way to wrap a menu's top-level link and sub-menus into a custom div. I found this code that almost does the trick:

class Sub_Wrapper extends Walker_Nav_Menu {
    function start_lvl(&$output, $depth = 0, $args = array()) {
        $indent = str_repeat("\t", $depth);
        $output .= "\n$indent<div class=\"sub-menu-wrapper\"><ul class=\"sub-menu\">\n";
    }
    function end_lvl(&$output, $depth = 0, $args = array()) {
        $indent = str_repeat("\t", $depth);
        $output .= "$indent</ul></div>\n";
    }
}

This outputs the following:

<ul>
    <li>
        <a href="#"></a>
        <div class="sub-menu-wrapper">
            <ul class="sub-menu"></ul>
        </div>
    </li>
</ul>

Though I'd need the 'a href..' to be inside the wrapper as well, like this:

<ul>
    <li>
        <div class="sub-menu-wrapper">
            <a href="#"></a>
            <ul class="sub-menu"></ul>
        </div>
    </li>
</ul>

Any suggestions? Trying to do it via the walker class and avoid jQuery's .wrap().

Это было полезно?

Решение

This would do it:

class My_Walker_Nav_Menu extends Walker_Nav_Menu {
    private $_before = null;

    public function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) {
        // Backup the original "before", if any.
        if ( null === $this->_before ) {
            $this->_before = $args->before;
        }
        // Now add the wrapper div, if applicable.
        if ( 0 == $depth ) {
            $args->before = '<div class="sub-menu-wrapper">' . $this->_before;
        } else {
            $args->before = $this->_before;
        }

        // Then let the parent walker does the output generation.
        parent::start_el( $output, $item, $depth, $args, $id );
    }

    public function end_el( &$output, $item, $depth = 0, $args = array() ) {
        // Close the wrapper div, if applicable.
        if ( 0 == $depth ) {
            $output .= '</div><!-- .sub-menu-wrapper -->';
        }
        $output .= "</li>\n";
    }
}

I.e. Extend the start_el() and end_el() methods/functions instead of start_lvl() and end_lvl(). Also, the wrapper will only be added if the menu item has children (or submenu(s)).

Sample usage:

wp_nav_menu( [
    'walker' => new My_Walker_Nav_Menu(),
    // ... other args.
] );
Лицензировано под: CC-BY-SA с атрибуция
Не связан с wordpress.stackexchange
scroll top