Agregue la clase 'has_children' a la li principal al modificar Walker_Nav_Menu

22

Estoy escribiendo una clase de caminante personalizada para wp_nav_menu y quiero poder especificar si un li contiene un submenú. Entonces quiero que mi marcado sea:

<li class="has_children [other-wordpress-classes]">
    <a class="parent-link">Some item</a>
    <ul class="sub-menu">

Sé cómo agregar y eliminar las clases bien, simplemente no puedo encontrar nada que me diga si el elemento actual tiene elementos secundarios.

¿Algunas ideas?

Gracias por adelantado.

Patnz
fuente

Respuestas:

23

start_el()debería obtener esta información en su $argsparámetro, pero parece que WordPress solo completa esto si $argses una matriz , mientras que para los menús de navegación personalizados es un objeto. Esto se informa en un boleto de Trac . Pero no hay problema, puede completar esto usted mismo, si también anula el display_element()método en su andador personalizado (porque este es el lugar más fácil para acceder a la matriz de elementos secundarios):

class WPSE16818_Walker extends Walker_Nav_Menu
{
    function display_element( $element, &$children_elements, $max_depth, $depth=0, $args, &$output )
    {
        $id_field = $this->db_fields['id'];
        if ( is_object( $args[0] ) ) {
            $args[0]->has_children = ! empty( $children_elements[$element->$id_field] );
        }
        return parent::display_element( $element, $children_elements, $max_depth, $depth, $args, $output );
    }

    function start_el( &$output, $item, $depth, $args ) {
        if ( $args->has_children ) {
            // ...
        }
    }
Jan Fabry
fuente
Hola Jan, ¿puedes ayudarme con esta pregunta ? Probé tu código pero no pude hacerlo funcionar. ¿Me puede dar más código de muestra?
Giri
Consulte el ejemplo de implementación completa más abajo en esta página.
rjb
Muchas gracias @ Jan fabry ... me detuve con mi andador personalizado ... Atlast tu fragmento me ayudó.
Harish Chinju
7

Actualización: a partir de WordPress 3.7 (octubre de 2013), se han agregado clases CSS para indicar elementos de menú secundarios y páginas en menús temáticos; no es necesario usar un andador personalizado, ya que se ocupa en el núcleo de WordPress.

Las clases CSS se nombran menu-item-has-childreny page_item_has_children.


Para obtener una solución completa para cualquier persona que tenga prisa (crédito a la respuesta anterior de Jan Fabry), consulte la implementación completa a continuación.

Imprima la navegación en la plantilla de su tema:

wp_nav_menu( array(
    'theme_location' => 'navigation-primary',
    'container' => false,
    'container_class' => '',
    'container_id' => '',
    'menu_class' => '',
    'menu_id' => '',
    'walker' => new Selective_Walker(),
    'depth' => 2
    )
);

Luego, incluya lo siguiente en su tema functions.php:

class Selective_Walker extends Walker_Nav_Menu {
    function display_element( $element, &$children_elements, $max_depth, $depth=0, $args, &$output ) {
        $id_field = $this->db_fields['id'];

        if ( is_object( $args[0] ) ) {
            $args[0]->has_children = !empty( $children_elements[$element->$id_field] );
        }

        return parent::display_element( $element, $children_elements, $max_depth, $depth, $args, $output );
    }

    function start_el( &$output, $item, $depth, $args ) {
        if ( $args->has_children ) {
            $item->classes[] = 'has_children';
        }

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

El resultado HTML resultante será similar al siguiente:

<ul>
    <li><a href="#">Home</a></li>
    <li class="has_children"><a href="#">About</a>
        <ul class="sub-menu">
            <li><a href="#">Our Mission</a></li>
        </ul>
    </li>
    <li><a href="#">Services</a></li>
    <li class="has_children"><a href="#">Products</a>
        <ul class="sub-menu">
            <li><a href="#">Lorem Ipsum</a></li>
            <li><a href="#">Lorem Ipsum</a></li>                
        </ul>
    </li>
    <li><a href="#">Contact Us</a></li>
</ul>

Para obtener más información sobre el uso de la clase de caminante de WordPress, consulte Comprender la clase de caminante .

¡Disfrutar!

rjb
fuente
Error fatal: la referencia de tiempo de llamada se ha eliminado en D: \ www \ wordpress \ wp-content \ themes \ wpt_theme \ functions.php en la línea 44
Tahir Yasin
La línea # 44 es parent :: start_el (& $ output, $ item, $ depth, $ args);
Tahir Yasin
2

Esta función es exactamente lo que quieres tener. También le muestra una forma bastante efectiva de modificar los elementos del menú de navegación. Además, puede abrirlo para funciones más avanzadas (por ejemplo, tema secundario) a través del filtro de elementos:

/**
 * Classes for a navigation named "Topnav" in the nav location "top".
 * Shows examples on how to modify the current nav menu item
 * 
 * @param (object) $items
 * @param (object) $menu
 * @param (object) $args
 */
function wpse16818_nav_menu_items( $items, $menu, $args )
{
    # >>>> start editing

    // examples for possible targets
    $target['name'] = 'Topnav';
    // The targeted menu item/s
    $target['items'] = array( (int) 6 );

    # <<<< stop editing

    // filter for child themes: "config_nav_menu_topnav"
    $target = apply_filters( 'config_nav_menu_'.strtolower( $target['name'] ), $target );

    // Abort if we're not with the named menu
    if ( $menu->name !== $target['name'] ) 
        return;

    foreach ( $items as $item )
    {
        // Check what $item contains
        echo '<pre>'; print_r($item); echo '</pre>';

        // First real world example:
        $item->classes = 'span-4';

        // Second real world example:
        // Append this class if we are in one of the targeted items
        if ( in_array( (int) $item->menu_order, $target['items'] ) )
            $item->classes .= ' last';
    }

    return $items;
}
add_filter( 'wp_get_nav_menu_items', 'wpse16818_nav_menu_items', 10, 3 );

Y sí, en casi todos los casos no hay necesidad de un andador personalizado.

emperador
fuente
Gracias, necesito el andador por ahora, ¡pero lo veré la próxima vez!
patnz
1

si desea hacer desplegable, puede hacerlo solo con CSS. hacer una navegación personalizada en WP con niños, WordPress asigna automáticamente la clase .sub-menu al niño ul. Prueba este CSS

    nav li {position:relative;}
   .sub-menu {display:none; position:absolute; width:300px;}
    nav ul li:hover ul {display:block;}

Es posible que desee agregar un poco de jQuery para darle un poco de sabor, pero esto debería darle un menú desplegable que funcione.

alexndm
fuente
Gracias, es por un menú de árbol plegable multinivel en el que también estoy insertando elementos de control, ¡pero definitivamente es bueno hacer todo lo posible con CSS!
patnz
-1
if ( $this->has_children ) {
    $item_output .= 'has_children';
}
Yaroslav
fuente
3
Por favor, explique qué hace este código y cómo responde la pregunta.
cybmeta
Y publique el código en más contexto. Como es, la mayoría de las personas que visitan no tendrán idea de dónde tratar de pegar eso y se equivocarán.
s_ha_dum