O Navegador personalizado exibe o item do menu atual filhos ou irmãos sem filhos

14

Eu tenho andado brincando / procurando por horas e ainda não consigo fazer isso funcionar, então finalmente estou cedendo e pedindo ajuda.

Estou tentando escrever um andador personalizado que mostre apenas os filhos das páginas atuais ou se não houver filhos exibindo os irmãos das páginas.

Por exemplo, considere a seguinte árvore de menus:

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

Vamos supor que eu esteja na página atual 1.2.0. Nesta página, quero exibir os filhos (1.3.0, 1.3.1, 1.3.2)

no entanto, se eu estiver na página 1.2.2, uma vez que não possui filhos, ele deve exibir seus irmãos no nível atual e mostrar-me (1.2.0, 1.2.1, 1.2.2).

jchamb
fonte
4
Mova sua solução para uma resposta para que fique mais claro para outras pessoas e as perguntas não assombrem o site como sem resposta.
Rarst
O que @Rarst disse! Eu quase senti falta de que você tivesse uma solução.
precisa saber é o seguinte
Resposta necro. Eu fiz mais ou menos a mesma pergunta sobre o SO há cerca de 2 anos, com uma resposta muito boa. stackoverflow.com/questions/5826609/…
Stoosh
Resposta movida dentro da pergunta para separar a resposta. OP: Por favor, siga até lá.
Kaiser #

Respostas:

4

Este é o andador que eu costumava exibir apenas os filhos do item de menu atual. Ou os itens de menu irmãos, se não tiver filhos.

Há comentários em toda a classe explicando cada seção

<?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 );
}
}

Anexe-o como faria com qualquer outro andador personalizado em um wp_nav_menu

<?php
wp_nav_menu( array(
    'menu' => 'primary-menu'
    ,'container' => 'nav'
    ,'container_class' => 'subpages'
    ,'depth' => 0
    ,'walker' => new SH_Child_Only_Walker()
 ));
?>
jchamb
fonte
Quero salientar o comentário de @ Stoosh apontando aqui. stackoverflow.com/questions/5826609/... como esta é outra boa solução
jchamb
0

Eu tive uma experiência parecida. Você pode pensar em mover a lógica das páginas para fora do andador. Basicamente, compile a hierarquia da página atual como um objeto. Em seguida, use o parâmetro 'exclude' na função wp_nav_menu. Agora, as páginas excluídas dependerão se a página atual tiver filhos. Se nenhum filho mostra irmãos; se filhos e essas crianças são o fim da linha, mostre irmãos e filhos; se existirem filhos e netos, exclua irmãos e mostre filhos e netos.

Steve Fischer
fonte
Qual é esse excludeparâmetro ao qual você se refere? Estou olhando a documentação e não vejo nenhuma referência a ela.
precisa saber é o seguinte
1
Peço desculpas por ter me enganado. Você está certo de que não há parâmetro 'excluir'. Eu pretendia usar a função "wp_list_pages".
22613 Steve Fischer
Muito bom, e não se preocupe. Fiquei curioso para saber se havia algo sem documentos, mas no final - já vi isso acontecer antes. Obrigado por esclarecê-lo! Eu não tinha pensado em usar wp_list_pages()nesse contexto, então essa é uma ideia interessante.
precisa saber é o seguinte