Filtro wp_nav_menu ()

9

Intento dividir mi navegación en 3 barras de navegación individuales (nivel 1, nivel 2 y nivel 3 +). Tres porque están separados en el sitio y solo deberían aparecer según la página actual.

-0-------1--------2-------3+- level/depth
Home
 |
 |\___ Lobby
 |
 |\___ Projects
 |       |\___ Project A
 |       |       |\___ Review
 |       |       |\___ Comments
 |       |       \____ Download
 |       \____ Project B
 |               |\___ Review
 |               |\___ Comments
 |               \____ Download
 |\___ Blog
 |
 \____ About
         |\___ Legal
         \____ Contact

La primera barra de navegación que contiene el nivel 1 siempre está visible. La segunda barra de navegación (nivel 2) solo cuando estoy actualmente en la página principal correspondiente. Lo mismo ocurre con la tercera barra de navegación (nivel 3+, además porque esta barra de navegación también contendrá subpáginas y páginas de subsub ... del nivel 3).

En resumen: quiero mostrar todos los menús principales en sus barras de navegación y solo los secundarios directos de la página actual.

Lo que intenté:

function my_nav_menu( $args = array() )
{
    $echo = isset( $args['echo'] ) ? (bool)( $args['echo'] ) : true;
    $args['echo'] = false;

    add_filter( 'wp_get_nav_menu_items' , 'my_nav_menu_filter' , 666 , 3 );

    $menu = wp_nav_menu( $args );

    remove_filter( 'wp_nav_menu_objects' , 'my_nav_menu_filter' , 666 );

    if( $echo )
        echo $menu;
    else
        return $menu;
}

function my_nav_menu_filter( $items , $menu , $args )
{
    //var_dump( $args );

    $navLevel = isset( $args['navlevel'] ) ? (int)( $args['navlevel'] ) : 0;

    //echo 'navlevel = ' . $args['navlevel'] . ' | ' . $navLevel;

    if( $navLevel == 1 )
    {
        foreach( $items as $key => $item )
        {
            if( $item->menu_item_parent != 0 )
                unset( $items[$key] );
        }
    }
    else if( $navLevel == 2 )
    {
        foreach( $items as $key => $item )
        {
            if( $item->menu_item_parent != 0 )
            {
                $page = get_page( $item->menu_item_parent );

                if( $page->menu_item_parent == 0 )
                    continue;
            }

            unset( $items[$key] );
        }
    }
    else if( $navLevel == 3 )
    {
        foreach( $items as $key => $item )
        {
            if( $item->menu_item_parent != 0 )
            {
                $page = get_page( $item->menu_item_parent );

                if( $page->menu_item_parent != 0 )
                    continue;
            }

            unset( $items[$key] );
        }
    }
    else
    {
        //var_dump( $items );
    }

    return $items;
}

Llamando a esto en mi header.php: <?php my_nav_menu( array( 'echo' => false , 'navlevel' => 1 ) ); ?>

Sin embargo, $args se establece en los valores predeterminados y mi entrada personalizada navlevel no se muestra en el filtro.

¿Cómo puedo dividir mi barra de navegación como se describe? ¿Cómo configuro mi entrada personalizada $args ?

    
pregunta nonsensation 07.04.2014 - 20:26

2 respuestas

3

Creo que obtuve la respuesta:

function my_nav_menu( $args = array() )
{
    $echo = isset( $args['echo'] ) ? (bool)( $args['echo'] ) : true;

    $args['echo'] = false;

    add_filter( 'wp_nav_menu_objects' , 'my_filter_nav_menu' , 100 , 2 );

    $menu = wp_nav_menu( $args );

    remove_filter( 'wp_nav_menu_objects' , 'my_filter_nav_menu' , 100, 2 );

    if( $echo )
        echo $menu;
    else
        return $menu;
}

Esto hace el truco: me permite alterar los artículos y los argumentos personalizados todavía están disponibles. Accidentalmente enganché el filtro en wp_get_nav_menu_items en lugar de wp_nav_menu_objects . Todavía tengo problemas con el filtrado, sin embargo, estos son probablemente algunos errores lógicos ...

EDITAR: resolveré mi problema combinando el nivel 2 de la barra de navegación y el nivel 3+ de la barra de navegación en uno y separándolos con css

aquí está la parte actual de php:

function serthy_filter_nav_menu( $items , $args )
{
    $argArray = (array)( $args );

    if( isset( $argArray['toplevel'] ) )
    {
        foreach( $items as $key => $item )
        {
            if( $item->menu_item_parent != 0 )
                unset( $items[$key] );
        }

        return $items;
    }

    global $post;

    $arr = array();

    foreach( $items as $key => $item )
    {
        $parentIDs = get_post_ancestors( $item->ID );

        foreach( $parentIDs as $i => $parentID )
        {
            if( $parentID == $post->ID )
            {
                array_push( $arr , $item );

                break;
            }
        }
    }

    return $arr;
}
    
respondido por el nonsensation 08.04.2014 - 00:20
1

Me parece que usted podría manejar esto a través de CSS en el sentido de que podría ocultar las opciones del menú de nivel inferior de manera predeterminada, y luego elegir mostrar si tienen ciertas clases por encima de ellos.

En esta página del Códice , puede ver las clases del menú (y en su propia página). Entonces, para el "segundo nivel" que describiste, asumiendo que el menú de primer nivel es el nivel 1, no el 0.

ul > li > ul.sub-menu { display: none; }  /* Hide by default */
ul > li.current-menu-parent > ul.sub-menu { display: block; } /* Show menu */

Y luego algo similar para el siguiente nivel abajo:

ul > li > ul.sub-menu > li > ul.sub-menu{ display: none; }  /* Hide by default */
ul > li > ul.sub-menu > li.current-menu-parent > ul.sub-menu { display: block; }

Obviamente, reemplace "bloque" con "bloque en línea" o lo que sea que estén configurados en sus menús.

Es posible que tengas que jugar para encontrar la combinación correcta de clases, pero antes tuve buena suerte con este método. WP suelta un montón de clases allí, también podría usarlas.

    
respondido por el Amanda Giles 08.04.2014 - 01:23

Lea otras preguntas en las etiquetas