Il navigatore personalizzato visualizza la voce di menu corrente figlio o fratelli su nessun figlio


14

Ho pasticciato / cercato per ore e ancora non riesco a farlo funzionare, quindi finalmente mi arrendo e chiedo aiuto.

Sto cercando di scrivere un walker personalizzato che mostri solo le pagine correnti figli, o se non ci sono figli mostrano le pagine fratelli.

Ad esempio, prendi la seguente struttura di menu:

  • 1.0
    • 1.2.0
      • 1.3.0
      • 1.3.1
      • 1.3.2
    • 1.2.1
    • 1.2.2
  • 2.0

Supponiamo che io sia nella pagina corrente 1.2.0. In questa pagina voglio mostrare i suoi figli (1.3.0, 1.3.1, 1.3.2)

tuttavia, se sono sulla pagina 1.2.2, poiché non ha figli, dovrebbe mostrare i suoi fratelli di livello attuale, quindi dovrebbe mostrarmi (1.2.0, 1.2.1, 1.2.2).


4
Sposta la tua soluzione in una risposta in modo che sia più chiara per gli altri e le domande non perseguitano il sito come senza risposta.
Rarst

Cosa ha detto @Rarst! Mi ero quasi perso che avresti trovato una soluzione.
Chris Krycho,

Risposta Necro. Ho fatto più o meno la stessa domanda su SO circa 2 anni fa con un'ottima risposta. stackoverflow.com/questions/5826609/…
Stoosh,

Sposta la risposta all'interno della domanda per separare la risposta. OP: Per favore, segui qui.
Kaiser

Risposte:


4

Questo è il walker che ho usato per visualizzare solo i figli della voce di menu corrente. O le voci del menu fratelli se non ha figli propri.

Ci sono commenti in tutta la classe che spiegano ogni sezione

<?php

class SH_Child_Only_Walker extends Walker_Nav_Menu {

private $ID;
private $depth;
private $classes = array();
private $child_count = 0;
private $have_current = false;


// Don't start the top level
function start_lvl(&$output, $depth=0, $args=array()) {

    if( 0 == $depth || $this->depth != $depth )
        return;

    parent::start_lvl($output, $depth,$args);
}

// Don't end the top level
function end_lvl(&$output, $depth=0, $args=array()) {
    if( 0 == $depth || $this->depth != $depth )
        return;

    parent::end_lvl($output, $depth,$args);
}

// Don't print top-level elements
function start_el(&$output, $item, $depth=0, $args=array()) {

    $is_current = in_array('current-menu-item', $this->classes);

    if( 0 == $depth || ! $is_current )
        return;

    parent::start_el($output, $item, $depth, $args);
}

function end_el(&$output, $item, $depth=0, $args=array()) {
    if( 0 == $depth )
        return;

    parent::end_el($output, $item, $depth, $args);
}

// Only follow down one branch
function display_element( $element, &$children_elements, $max_depth, $depth=0, $args, &$output ) {

    // Check if element is in the current tree to display
    $current_element_markers = array( 'current-menu-item', 'current-menu-parent', 'current-menu-ancestor' );
    $this->classes = array_intersect( $current_element_markers, $element->classes );

    // If element has a 'current' class, it is an ancestor of the current element
    $ancestor_of_current = !empty($this->classes);

    // check if the element is the actual page element we are on.
    $is_current = in_array('current-menu-item', $this->classes);

    // if it is the current element
    if($is_current) {

        // set the count / ID / and depth to use in the other functions.
        $this->child_count = ( isset($children_elements[$element->ID]) ) ? count($children_elements[$element->ID]) : 0;
        $this->ID = $element->ID;
        $this->depth = $depth;
        $this->have_current = true;

        if($this->child_count > 0) {

            // if there are children loop through them and display the kids.
            foreach( $children_elements[$element->ID] as $child ) {
                parent::display_element( $child, $children_elements, $max_depth, $depth, $args, $output );
            }

        } else {
            // no children so loop through kids of parent item.
            foreach( $children_elements[$element->menu_item_parent] as $child ) {
                parent::display_element( $child, $children_elements, $max_depth, $depth, $args, $output );
            }

        }
    }

    // if depth is zero and not in current tree go to the next element
    if ( 0 == $depth && !$ancestor_of_current)
        return;

    // if we aren't on the current element proceed as normal
    if(! $this->have_current )
        parent::display_element( $element, $children_elements, $max_depth, $depth, $args, $output );
}
}

Collegalo come faresti con qualsiasi altro walker personalizzato su un wp_nav_menu

<?php
wp_nav_menu( array(
    'menu' => 'primary-menu'
    ,'container' => 'nav'
    ,'container_class' => 'subpages'
    ,'depth' => 0
    ,'walker' => new SH_Child_Only_Walker()
 ));
?>

Voglio sottolineare il commento di @ Stoosh che punta qui. stackoverflow.com/questions/5826609/… poiché questa è un'altra buona soluzione
jchamb

0

Ho avuto un'esperienza simile. Potresti pensare di spostare la logica delle pagine fuori dal walker. Fondamentalmente, compilare la gerarchia di pagina corrente come oggetto. Quindi utilizzare il parametro 'exclude' nella funzione wp_nav_menu. Ora le pagine escluse dipenderebbero se la pagina corrente ha dei figli. Se nessun bambino mostra fratelli; se i bambini && quei bambini sono la fine della linea mostrano fratelli e figli; se esistono figli && e nipoti escludere fratelli e mostrare figli e nipoti.


Qual è questo excludeparametro a cui ti riferisci? Sto guardando la documentazione e non vedo alcun riferimento ad essa.
Chris Krycho,

1
Mi scuso per essermi sbagliato. Hai ragione sul fatto che non esiste un parametro 'exclude'. Intendevo usare la funzione "wp_list_pages".
Steve Fischer,

Molto bene, senza preoccupazioni. Ero solo curioso di sapere se c'era qualcosa di non documentato, ma nel back-end: l'ho visto accadere prima. Grazie per averlo chiarito! Non avevo pensato di utilizzare wp_list_pages()in questo contesto, quindi è un'idea interessante.
Chris Krycho,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.