Zeigen Sie einen Teil des Menübaums mit wp_nav_menu () an.

109

Ich habe ein Menü in WP Admin definiert, das so aussieht:

Alt-Text

Ich möchte alle untergeordneten Links in der Seitenleiste anzeigen können, wenn ich mich auf einer übergeordneten Seite befinde. Wenn sich der Benutzer beispielsweise auf meiner Seite "Über uns" befindet, soll eine Liste der 4 grün hervorgehobenen Links in der Seitenleiste angezeigt werden.

Ich habe mir die Dokumentation zu wp_nav_menu () angesehen und es scheint keine eingebaute Möglichkeit zu geben, einen bestimmten Knoten eines bestimmten Menüs anzugeben, der als Ausgangspunkt beim Generieren der Links verwendet werden soll.

Ich habe eine Lösung für eine ähnliche Situation erstellt, die sich auf die Beziehungen stützte, die von den übergeordneten Seiten erstellt wurden, aber ich suche eine, die das Menüsystem speziell verwendet. Jede Hilfe wäre dankbar.

jessegavin
quelle
2
Sie möchten also das gesamte Menü als benutzerdefiniertes Menü verwalten, aber einen benutzerdefinierten Walker erstellen, der nur den aktiven Teilbaum erweitert. Wie dieser Code , aber wp_nav_menu anstelle von wp_list_pages erweitern? Ich habe kürzlich etwas Ähnliches gemacht und könnte den Code posten, wenn es das ist, wonach du suchst ...
goldenapples
1
@goldenapples, genau danach bin ich. Wenn es Ihnen nichts ausmacht, Ihren Code als Antwort zu veröffentlichen, wäre ich Ihnen sehr dankbar.
Jessegavin
1
Ich frage mich, dass solch eine offensichtliche nützliche Funktionalität es nicht schon baut. Das ist insgesamt sehr nützlich für jede Site, die "CMS" betreibt.
Hakre
Ich versuche das obige Problem oder ähnliches zu lösen. Als Alternative habe ich hier eine CSS-Lösung gefunden: stackoverflow.com/q/7640837/518169
hyperknot

Antworten:

75

Das war noch in meinen Gedanken, also habe ich es noch einmal überarbeitet und diese Lösung zusammengestellt, die nicht so sehr vom Kontext abhängt:

add_filter( 'wp_nav_menu_objects', 'submenu_limit', 10, 2 );

function submenu_limit( $items, $args ) {

    if ( empty( $args->submenu ) ) {
        return $items;
    }

    $ids       = wp_filter_object_list( $items, array( 'title' => $args->submenu ), 'and', 'ID' );
    $parent_id = array_pop( $ids );
    $children  = submenu_get_children_ids( $parent_id, $items );

    foreach ( $items as $key => $item ) {

        if ( ! in_array( $item->ID, $children ) ) {
            unset( $items[$key] );
        }
    }

    return $items;
}

function submenu_get_children_ids( $id, $items ) {

    $ids = wp_filter_object_list( $items, array( 'menu_item_parent' => $id ), 'and', 'ID' );

    foreach ( $ids as $id ) {

        $ids = array_merge( $ids, submenu_get_children_ids( $id, $items ) );
    }

    return $ids;
}

Verwendungszweck

$args = array(
    'theme_location' => 'slug-of-the-menu', // the one used on register_nav_menus
    'submenu' => 'About Us', // could be used __() for translations
);

wp_nav_menu( $args );
Rarst
quelle
Schöne Technik! Darf ich Sie diesbezüglich etwas fragen: Wie würden Sie den Inhalt dieser aufgelisteten Untermenüseiten in der Vorlage anzeigen?
daniel.tosaba
2
@ daniel.tosaba Sie müssen in der Walker_Nav_MenuKlasse Unterklassen oder Filter verwenden . Wie alle Menü-Sachen zu viel für einen Kommentar - neue Frage dazu stellen?
Rarst
3
Was für eine fantastische Antwort. Ich danke dir sehr. Dies sollte eigentlich eine Standardoption in WordPress sein.
dotty
3
Wirklich ordentlich. Wenn jemand daran interessiert ist, dasselbe zu tun, aber nach Seiten-ID, ändern Sie die wp_filter_object_listZeile zuwp_filter_object_list( $items, array( 'object_id' => $args->submenu ), 'and', 'ID' );
Ben
14

@goldenapples: Deine Walker-Klasse funktioniert nicht. Aber die Idee ist wirklich gut. Ich habe einen Walker basierend auf Ihrer Idee erstellt:

class Selective_Walker extends Walker_Nav_Menu
{
    function walk( $elements, $max_depth) {

        $args = array_slice(func_get_args(), 2);
        $output = '';

        if ($max_depth < -1) //invalid parameter
            return $output;

        if (empty($elements)) //nothing to walk
            return $output;

        $id_field = $this->db_fields['id'];
        $parent_field = $this->db_fields['parent'];

        // flat display
        if ( -1 == $max_depth ) {
            $empty_array = array();
            foreach ( $elements as $e )
                $this->display_element( $e, $empty_array, 1, 0, $args, $output );
            return $output;
        }

        /*
         * need to display in hierarchical order
         * separate elements into two buckets: top level and children elements
         * children_elements is two dimensional array, eg.
         * children_elements[10][] contains all sub-elements whose parent is 10.
         */
        $top_level_elements = array();
        $children_elements  = array();
        foreach ( $elements as $e) {
            if ( 0 == $e->$parent_field )
                $top_level_elements[] = $e;
            else
                $children_elements[ $e->$parent_field ][] = $e;
        }

        /*
         * when none of the elements is top level
         * assume the first one must be root of the sub elements
         */
        if ( empty($top_level_elements) ) {

            $first = array_slice( $elements, 0, 1 );
            $root = $first[0];

            $top_level_elements = array();
            $children_elements  = array();
            foreach ( $elements as $e) {
                if ( $root->$parent_field == $e->$parent_field )
                    $top_level_elements[] = $e;
                else
                    $children_elements[ $e->$parent_field ][] = $e;
            }
        }

        $current_element_markers = array( 'current-menu-item', 'current-menu-parent', 'current-menu-ancestor' );  //added by continent7
        foreach ( $top_level_elements as $e ){  //changed by continent7
            // descend only on current tree
            $descend_test = array_intersect( $current_element_markers, $e->classes );
            if ( !empty( $descend_test ) ) 
                $this->display_element( $e, $children_elements, 2, 0, $args, $output );
        }

        /*
         * if we are displaying all levels, and remaining children_elements is not empty,
         * then we got orphans, which should be displayed regardless
         */
         /* removed by continent7
        if ( ( $max_depth == 0 ) && count( $children_elements ) > 0 ) {
            $empty_array = array();
            foreach ( $children_elements as $orphans )
                foreach( $orphans as $op )
                    $this->display_element( $op, $empty_array, 1, 0, $args, $output );
         }
        */
         return $output;
    }
}

Jetzt können Sie verwenden:

<?php wp_nav_menu( 
   array(
       'theme_location'=>'test', 
       'walker'=>new Selective_Walker() ) 
   ); ?>

Die Ausgabe ist eine Liste mit dem aktuellen Stammelement und seinen untergeordneten Elementen (nicht ihren untergeordneten Elementen). Def: Root element: = Das oberste Menüelement, das der aktuellen Seite entspricht oder übergeordnet zu einer aktuellen Seite oder übergeordnet zu einer übergeordneten Seite ist ...

Dies beantwortet die ursprüngliche Frage aber fast nicht genau, da es sich immer noch um das Element der obersten Ebene handelt. Dies ist in Ordnung für mich, da ich das Element der obersten Ebene als Überschrift der Seitenleiste verwenden möchte. Wenn Sie dies beseitigen möchten, müssen Sie möglicherweise display_element überschreiben oder einen HTML-Parser verwenden.

Davidn
quelle
12

Hi @jessegavin :

Navigationsmenüs werden in einer Kombination aus benutzerdefinierten Beitragstypen und benutzerdefinierten Taxonomien gespeichert. Jedes Menü wird als ein Begriff (dh "About Menu" , gefunden in wp_terms) einer benutzerdefinierten Taxonomie (dh nav_menugefunden in wp_term_taxonomy.) Gespeichert .

Jeder Nav-Menüpunkt wird als Beitrag von post_type=='nav_menu_item'(dh "Über die Firma" , gefunden in wp_posts) mit seinen Attributen als Beitrags-Meta (in wp_postmeta) gespeichert, wobei das meta_keyPräfix verwendet wird, _menu_item_*wo _menu_item_menu_item_parentdie ID des übergeordneten Nav-Menüpunkt-Beitrags Ihres Menüpunkts ist.

Die Beziehung zwischen Menüs und Menüelementen ist in gespeichert, wp_term_relationshipswobei sie object_idsich auf das $post->IDfür das Navigationsmenüelement und $term_relationships->term_taxonomy_idauf das in wp_term_taxonomyund gemeinsam definierte Menü bezieht wp_terms.

Ich bin mir ziemlich sicher , dass es möglich wäre , haken beide 'wp_update_nav_menu'und 'wp_update_nav_menu_item'aktuelle Menüs in erstellen wp_termsund einen parallelen Satz von Beziehungen in wp_term_taxonomyund wp_term_relationshipswo jeden Nav Menüpunkt, der auch Unter Nav Menüpunkte hat wird es eigenes Nav - Menü.

Sie sollten auch einen Hook 'wp_get_nav_menus' (den ich aufgrund einer ähnlichen Arbeit, die ich vor einigen Monaten durchgeführt habe, zu WP 3.0 hinzugefügt habe) verwenden, um sicherzustellen, dass Ihre generierten Navigationsmenüs nicht für den Benutzer im Administrator zur Manipulation angezeigt werden, andernfalls würde sehr schnell aus der Synchronisation geraten und du hättest einen Daten-Albtraum auf der Hand.

Klingt nach einem unterhaltsamen und nützlichen Projekt, aber es ist ein bisschen mehr Code und Testen, als ich es mir leisten kann, zum gegenwärtigen Zeitpunkt in Angriff zu nehmen, da alles, was Daten synchronisiert, zum PITA wird, wenn es darum geht, alle Fehler auszubügeln (und weil Zahlende Kunden fordern mich auf, die Dinge zu erledigen. :) Aber mit den obigen Informationen bewaffnet, bin ich ein ziemlich motivierter WordPress-Plug-in-Entwickler, der sie codieren könnte, wenn er wollte.

Natürlich stellen Sie jetzt fest, dass Sie, wenn Sie es codieren, verpflichtet sind, es hierher zurückzusenden, damit wir alle von Ihrer Größe profitieren können! :-)

MikeSchinkel
quelle
Ich bin nicht sicher, ob ich dem folge, was du sagst. Ich suche nach einer schreibgeschützten Lösung zum Anzeigen von "Untermenüs", die sich auf die aktuelle Seite beziehen, auf der sich ein Benutzer befindet. Sprechen wir über das Gleiche? - Ich weiß Ihre tiefere Erklärung zum Datenbankschema zu schätzen.
Jessegavin
@jessegavin - Ja, wenn Sie anrufen möchten, müssen wp_nav_menu()Sie die Menüs klonen, da sie wp_nav_menu()eng mit der Menüstruktur verbunden sind . Die andere Möglichkeit besteht darin, den wp_nav_menu()Code zu kopieren und die Änderungen vorzunehmen, die für die Anzeige als Untermenü erforderlich sind.
MikeSchinkel
10

Dies ist eine Walker-Erweiterung, die das tun sollte, wonach Sie suchen:

class Selective_Walker extends Walker_Nav_Menu
{

    function walk( $elements, $max_depth) {

        $args = array_slice(func_get_args(), 2);
        $output = '';

        if ($max_depth < -1) //invalid parameter
            return $output;

        if (empty($elements)) //nothing to walk
            return $output;

        $id_field = $this->db_fields['id'];
        $parent_field = $this->db_fields['parent'];

        // flat display
        if ( -1 == $max_depth ) {
            $empty_array = array();
            foreach ( $elements as $e )
                $this->display_element( $e, $empty_array, 1, 0, $args, $output );
            return $output;
        }

        /*
         * need to display in hierarchical order
         * separate elements into two buckets: top level and children elements
         * children_elements is two dimensional array, eg.
         * children_elements[10][] contains all sub-elements whose parent is 10.
         */
        $top_level_elements = array();
        $children_elements  = array();
        foreach ( $elements as $e) {
            if ( 0 == $e->$parent_field )
                $top_level_elements[] = $e;
            else
                $children_elements[ $e->$parent_field ][] = $e;
        }

        /*
         * when none of the elements is top level
         * assume the first one must be root of the sub elements
         */
        if ( empty($top_level_elements) ) {

            $first = array_slice( $elements, 0, 1 );
            $root = $first[0];

            $top_level_elements = array();
            $children_elements  = array();
            foreach ( $elements as $e) {
                if ( $root->$parent_field == $e->$parent_field )
                    $top_level_elements[] = $e;
                else
                    $children_elements[ $e->$parent_field ][] = $e;
            }
        }

        $current_element_markers = array( 'current-menu-item', 'current-menu-parent', 'current-menu-ancestor' );

        foreach ( $top_level_elements as $e ) {

            // descend only on current tree
            $descend_test = array_intersect( $current_element_markers, $e->classes );
            if ( empty( $descend_test ) )  unset ( $children_elements );

            $this->display_element( $e, $children_elements, $max_depth, 0, $args, $output );
        }

        /*
         * if we are displaying all levels, and remaining children_elements is not empty,
         * then we got orphans, which should be displayed regardless
         */
        if ( ( $max_depth == 0 ) && count( $children_elements ) > 0 ) {
            $empty_array = array();
            foreach ( $children_elements as $orphans )
                foreach( $orphans as $op )
                    $this->display_element( $op, $empty_array, 1, 0, $args, $output );
         }

         return $output;
    }

}

Basierend auf dem Code von mfields, auf den ich bereits in meinem Kommentar verwiesen habe. Es wird lediglich beim Durchlaufen des Menüs überprüft, ob das aktuelle Element (1) das aktuelle Menüelement oder (2) ein Vorgänger des aktuellen Menüelements ist, und der untergeordnete Baum wird nur dann erweitert, wenn eine dieser Bedingungen erfüllt ist . Ich hoffe, das funktioniert für Sie.

Um es zu benutzen, fügen Sie einfach ein "walker" Argument hinzu, wenn Sie das Menü aufrufen, dh:

<?php wp_nav_menu( 
   array(
       'theme_location'=>'test', 
       'walker'=>new Selective_Walker() ) 
   ); ?>
goldenapples
quelle
Oh ... Ich habe Ihre Frage gerade noch einmal gelesen und festgestellt, dass ich sie zuerst missverstanden hatte. Dieser Walker zeigt alle anderen Menüelemente der obersten Ebene an, erweitert sie jedoch nicht. Das war nicht genau das, was du machen wolltest. Dieser Code kann jedoch beliebig geändert werden. Schauen Sie sich einfach die Schleife durch $top_level_elementsund fügen Sie Ihren eigenen Test hinzu, bevor Sie anrufen $this->display_element.
Goldenapples
Ist es möglich, mit dieser Klasse die Tiefe der aktuellen Unterseite anzuzeigen? Das heißt .. Wenn ich eine Tiefe von drei oder mehr Ebenen habe, werden die dritte und die folgenden Ebenen für die aktuelle (Unter-) Seite angezeigt? Im Moment wird nur A> B und nicht> C
angezeigt
@Zolomon - Ich bin mir nicht sicher, ob ich deine Frage verstehe. Dies sollte den gesamten Baum unter jedem Menüpunkt mit den Klassen 'aktueller-Menüpunkt', 'aktueller-Menüpunkt' oder 'aktueller-Menüvorfahr' erweitern. Wenn ich es teste, werden alle Ebenen der Unterseiten im Menü angezeigt. Was suchst du zu tun?
Goldenapples
Vielleicht möchten Sie einen depthParameter an den Aufruf übergeben wp_nav_menu, falls Ihr Thema die Standardeinstellung 0 überschreitet (alle Ebenen anzeigen)?
Goldenapples
8

Update: Ich habe daraus ein Plugin gemacht. Hier herunterladen .


Ich musste das selbst lösen und schließlich einen Filter für die Ergebnisse der Menüsuche schreiben. Sie können es wp_nav_menuwie gewohnt verwenden, aber basierend auf dem Titel des übergeordneten Elements einen Unterabschnitt des Menüs auswählen. Fügen Sie submenudem Menü einen Parameter wie folgt hinzu:

wp_nav_menu(array(
  'menu' => 'header',
  'submenu' => 'About Us',
));

Sie können sogar mehrere Ebenen tief gehen, indem Sie Schrägstriche einfügen:

wp_nav_menu(array(
  'menu' => 'header',
  'submenu' => 'About Us/Board of Directors'
));

Oder wenn Sie mit einem Array bevorzugen:

wp_nav_menu(array(
  'menu' => 'header',
  'submenu' => array('About Us', 'Board of Directors')
));

Es wird eine Slug-Version des Titels verwendet, mit der Groß- und Kleinschreibung und Zeichensetzung vermieden werden können.

Marcus Downing
quelle
Ist es möglich das Untermenü über id zu erreichen? Ich meine Seiten-ID oder Post-ID.
Digerkam
split () ist veraltet, $loc = split( "/", $loc );im Plugin ersetzen durch$loc = preg_split( "~/~", $loc );
Floris
Ich würde auch vorschlagen, $ submenu optional zu machen. So können Sie bei Bedarf immer noch das gesamte Menü abrufen. Fügen Sie dies dem Filter oben hinzu: `if (! Isset ($ args-> submenu)) {return $ items; } `
Floris
8

Ich habe die folgende Klasse für mich zusammengestellt. Es wird das übergeordnete Navigationselement der aktuellen Seite gefunden, oder Sie können ihm eine Ziel-ID für das oberste Navigationselement im Walker-Konstruktor zuweisen.

class Walker_SubNav_Menu extends Walker_Nav_Menu {
    var $target_id = false;

    function __construct($target_id = false) {
        $this->target_id = $target_id;
    }

    function walk($items, $depth) {
        $args = array_slice(func_get_args(), 2);
        $args = $args[0];
        $parent_field = $this->db_fields['parent'];
        $target_id = $this->target_id;
        $filtered_items = array();

        // if the parent is not set, set it based on the post
        if (!$target_id) {
            global $post;
            foreach ($items as $item) {
                if ($item->object_id == $post->ID) {
                    $target_id = $item->ID;
                }
            }
        }

        // if there isn't a parent, do a regular menu
        if (!$target_id) return parent::walk($items, $depth, $args);

        // get the top nav item
        $target_id = $this->top_level_id($items, $target_id);

        // only include items under the parent
        foreach ($items as $item) {
            if (!$item->$parent_field) continue;

            $item_id = $this->top_level_id($items, $item->ID);

            if ($item_id == $target_id) {
                $filtered_items[] = $item;
            }
        }

        return parent::walk($filtered_items, $depth, $args);
    }

    // gets the top level ID for an item ID
    function top_level_id($items, $item_id) {
        $parent_field = $this->db_fields['parent'];

        $parents = array();
        foreach ($items as $item) {
            if ($item->$parent_field) {
                $parents[$item->ID] = $item->$parent_field;
            }
        }

        // find the top level item
        while (array_key_exists($item_id, $parents)) {
            $item_id = $parents[$item_id];
        }

        return $item_id;
    }
}

Navigationsanruf:

wp_nav_menu(array(
    'theme_location' => 'main_menu',
    'walker' => new Walker_SubNav_Menu(22), // with ID
));
Matt
quelle
4

@davidn @hakre Hi, ich habe eine hässliche Lösung ohne HTML-Parser oder übergeordnetes display_element.

 class Selective_Walker extends Walker_Nav_Menu
    {
        function walk( $elements, $max_depth) {

            $args = array_slice(func_get_args(), 2);
            $output = '';

            if ($max_depth < -1) //invalid parameter
                return $output;

            if (empty($elements)) //nothing to walk
                return $output;

            $id_field = $this->db_fields['id'];
            $parent_field = $this->db_fields['parent'];

            // flat display
            if ( -1 == $max_depth ) {
                $empty_array = array();
                foreach ( $elements as $e )
                    $this->display_element( $e, $empty_array, 1, 0, $args, $output );
                return $output;
            }

            /*
             * need to display in hierarchical order
             * separate elements into two buckets: top level and children elements
             * children_elements is two dimensional array, eg.
             * children_elements[10][] contains all sub-elements whose parent is 10.
             */
            $top_level_elements = array();
            $children_elements  = array();
            foreach ( $elements as $e) {
                if ( 0 == $e->$parent_field )
                    $top_level_elements[] = $e;
                else
                    $children_elements[ $e->$parent_field ][] = $e;
            }

            /*
             * when none of the elements is top level
             * assume the first one must be root of the sub elements
             */
            if ( empty($top_level_elements) ) {

                $first = array_slice( $elements, 0, 1 );
                $root = $first[0];

                $top_level_elements = array();
                $children_elements  = array();
                foreach ( $elements as $e) {
                    if ( $root->$parent_field == $e->$parent_field )
                        $top_level_elements[] = $e;
                    else
                        $children_elements[ $e->$parent_field ][] = $e;
                }
            }

            $current_element_markers = array( 'current-menu-item', 'current-menu-parent', 'current-menu-ancestor' );  //added by continent7
            foreach ( $top_level_elements as $e ){  //changed by continent7
                // descend only on current tree
                $descend_test = array_intersect( $current_element_markers, $e->classes );
                if ( !empty( $descend_test ) ) 
                    $this->display_element( $e, $children_elements, 2, 0, $args, $output );
            }

            /*
             * if we are displaying all levels, and remaining children_elements is not empty,
             * then we got orphans, which should be displayed regardless
             */
             /* removed by continent7
            if ( ( $max_depth == 0 ) && count( $children_elements ) > 0 ) {
                $empty_array = array();
                foreach ( $children_elements as $orphans )
                    foreach( $orphans as $op )
                        $this->display_element( $op, $empty_array, 1, 0, $args, $output );
             }
            */

/*added by alpguneysel  */
                $pos = strpos($output, '<a');
            $pos2 = strpos($output, 'a>');
            $topper= substr($output, 0, $pos).substr($output, $pos2+2);
            $pos3 = strpos($topper, '>');
            $lasst=substr($topper, $pos3+1);
            $submenu= substr($lasst, 0, -6);

        return $submenu;
        }
    }
Alp Güneysel
quelle
Nachdem ich sie alle ausprobiert hatte, war Alps Lösung die einzige, die für mich funktioniert hat. Allerdings ein Problem damit. Es zeigt nur die Kinder der ersten Ebene, aber nicht die Kinder der dritten oder vierten Ebene. Ich habe seit Tagen versucht, es dazu zu bringen. Weiß jemand, wie man seine Lösung als solche modifiziert? PS. Ich kann keine Kommentare hinzufügen und muss dies als Antwort tun.
Cchiera
3

Die Ausgabe des Navigationsmenüs enthält viele Klassen für das aktuelle Element, den aktuellen Element-Vorfahren usw. In einigen Situationen konnte ich das tun, was Sie wollen, indem ich die gesamte Ausgabe des Navigationsbaums zuließ und sie dann mit CSS reduzierte nur untergeordnete Elemente der aktuellen Seite usw.


quelle
3

Ich habe einen modifizierten Walker gemacht, der helfen soll! Nicht perfekt - es bleiben ein paar leere Elemente übrig, aber es macht den Trick. Die Modifikation sind im Grunde diese $ current_branch Bits. Hoffe es hilft jemandem!

class Kanec_Walker_Nav_Menu extends Walker {
/**
 * @see Walker::$tree_type
 * @since 3.0.0
 * @var string
 */
var $tree_type = array( 'post_type', 'taxonomy', 'custom' );

/**
 * @see Walker::$db_fields
 * @since 3.0.0
 * @todo Decouple this.
 * @var array
 */
var $db_fields = array( 'parent' => 'menu_item_parent', 'id' => 'db_id' );

/**
 * @see Walker::start_lvl()
 * @since 3.0.0
 *
 * @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) {
    $indent = str_repeat("\t", $depth);
    $output .= "\n$indent<ul class=\"sub-menu\">\n";
}

/**
 * @see Walker::end_lvl()
 * @since 3.0.0
 *
 * @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) {
    global $current_branch;
    if ($depth == 0) $current_branch = false;
    $indent = str_repeat("\t", $depth);
    $output .= "$indent</ul>\n";
}

/**
 * @see Walker::start_el()
 * @since 3.0.0
 *
 * @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 int $current_page Menu item ID.
 * @param object $args
 */
function start_el(&$output, $item, $depth, $args) {
    global $wp_query;
    global $current_branch;

    // Is this menu item in the current branch?
    if(in_array('current-menu-ancestor',$item->classes) ||
    in_array('current-menu-parent',$item->classes) ||
    in_array('current-menu-item',$item->classes)) {
        $current_branch = true; 
    }

    if($current_branch && $depth > 0) {
        $indent = ( $depth ) ? str_repeat( "\t", $depth ) : '';

        $class_names = $value = '';

        $classes = empty( $item->classes ) ? array() : (array) $item->classes;
        $classes[] = 'menu-item-' . $item->ID;

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

        $id = apply_filters( 'nav_menu_item_id', 'menu-item-'. $item->ID, $item, $args );
        $id = strlen( $id ) ? ' id="' . esc_attr( $id ) . '"' : '';

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

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

}

/**
 * @see Walker::end_el()
 * @since 3.0.0
 *
 * @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) {
    global $current_branch;
    if($current_branch && $depth > 0) $output .= "</li>\n";
    if($depth == 0) $current_branch = 0;
}

}


quelle
3

Schau dir den Code in meinem Plugin an oder benutze ihn für deinen Zweck;)

Dieses Plugin fügt ein erweitertes Widget "Navigationsmenü" hinzu. Es bietet viele Optionen, mit denen die Ausgabe des benutzerdefinierten Menüs über das Widget angepasst werden kann.

Features sind:

  • Benutzerdefinierte Hierarchie - "Nur verwandte Unterelemente" oder "Nur streng verwandte Unterelemente".
  • Starttiefe und maximales Niveau für die Anzeige + Flachbildschirm.
  • Zeigt alle Menüpunkte an, die mit dem ausgewählten beginnen.
  • Nur direkten Pfad zum aktuellen Element oder nur untergeordnete Elemente des
    ausgewählten Elements anzeigen (Option zum Einbeziehen des übergeordneten Elements).
  • Benutzerdefinierte Klasse für einen Widgetblock.
  • Und fast alle Parameter für die Funktion wp_nav_menu.

http://wordpress.org/extend/plugins/advanced-menu-widget/

Ján Bočínec
quelle