wp_nav_menu: verifique si el elemento de la lista tiene hijos y agregue una clase al enlace de anclaje

4

Estoy tratando de agregar una clase para anclar los enlaces del elemento children en wp_nav_menu tanto para las páginas como para las publicaciones. ¿Hay alguna manera de modificar el menú del navegador y hacerlo?

Básicamente, mi andador personalizado se ve así:

class Main_Nav extends Walker_Nav_Menu {
        function start_lvl(&$output, $depth) {
            $indent = str_repeat("\t", $depth);
            $output .= "\n$indent<ul class=\"dropdown-menu\">\n";
        }
        function start_el(&$output, $item, $depth, $args) {

            if( $depth == 0) {
                    $output .= "<li class='menu'>";
            }               
            if( $depth == 1) {
                    $output .= "<li>";
            }
            $attributes  = '';
            ! empty( $item->attr_title ) and $attributes .= ' title="' . esc_attr( $item->attr_title ) .'"';
            ! empty( $item->target )and $attributes .= ' target="' . esc_attr( $item->target ) .'"';
            ! empty( $item->xfn )and $attributes .= ' rel="' . esc_attr( $item->xfn ) .'"';
            ! empty( $item->url )and $attributes .= ' href="' . esc_attr( $item->url ) .'"';

            $title = apply_filters( 'the_title', $item->title, $item->ID );

            if (/* THE MENU ELEMENT HAS CHILDREN */) {
                    $item_output = 
                    "<a $attributes class='menu'>"
                    . $title
                    . '</a> ';
            }

            else {
                    $item_output = 
                    "<a $attributes>"
                    . $title
                    . '</a> ';
            }

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

    }

}

Como ve, no sé cuál es la condición adecuada en lugar de /* THE ELEMENT HAS CHILDREN */ .

Gracias.

ACTUALIZAR

Gracias a Tamil, actualicé el código de la siguiente manera:

class Main_Nav extends Walker_Nav_Menu {
        function start_lvl(&$output, $depth) {
            $indent = str_repeat("\t", $depth);
            $output .= "\n$indent<ul class=\"dropdown-menu\">\n";
        }
        function start_el(&$output, $item, $depth, $args) {

            if( $depth == 0) {
                    $output .= "<li class='menu'>";
            }               
            if( $depth == 1) {
                    $output .= "<li>";
            }
            $attributes  = '';
            ! empty( $item->attr_title ) and $attributes .= ' title="' . esc_attr( $item->attr_title ) .'"';
            ! empty( $item->target )and $attributes .= ' target="' . esc_attr( $item->target ) .'"';
            ! empty( $item->xfn )and $attributes .= ' rel="' . esc_attr( $item->xfn ) .'"';
            ! empty( $item->url )and $attributes .= ' href="' . esc_attr( $item->url ) .'"';

            $title = apply_filters( 'the_title', $item->title, $item->ID );

            global $wpdb;
            $query = $wpdb->prepare("SELECT COUNT(*) FROM $wpdb->posts WHERE post_status ='publish' AND post_type='nav_menu_item' AND post_parent=%d", $item->ID);
            $child_count = $wpdb->get_var($query);

            if($child_count > 0) { /* THE MENU ELEMENT HAS CHILDREN */
                 $item_output = 
                    "<a $attributes class='menu'>"
                    . $title
                    . '</a> ';
            } else {
                    $item_output = 
                    "<a $attributes>"
                    . $title
                    . '</a> ';
            }

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

    }

}

Aunque no hay suerte :(

    
pregunta Sergey 23.12.2011 - 06:11

3 respuestas

3

Pude agregar una clase CSS "primaria" a la etiqueta de anclaje de los elementos del menú que tienen hijos siguiendo esta respuesta: Agregue la clase 'has_children' a li padre cuando modifique Walker_Nav_Menu

Aquí hay un ejemplo:

class Main_Nav extends Walker_Nav_Menu {
  /**
   * @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;
    $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, $args ) );
    $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        ) .'"' : '';

    // Check our custom has_children property.
    if ( $args->has_children ) {
      $attributes .= ' class="menu parent"';
    }

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

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

}
    
respondido por el Dave Romsey 22.01.2012 - 00:47
2

La otra forma es muy simple y puede ser útil para algunas personas

/**
* Custom Nav Classes
* https://v123.tw
*/
add_filter('nav_menu_css_class' , 'v123_nav_class' , 10 , 2 );
function v123_nav_class ($classes, $item) {
    if (in_array('menu-item-has-children', $classes) ){
        $classes[] = 'other-wordpress-classes';
    }
    return $classes;
}
    
respondido por el Ann 05.11.2017 - 20:40
0

Si los elementos utilizados son de la tabla {$wpdb->prefix}posts , entonces puede consultar las publicaciones con

  

post_parent = $ item- > ID y post_status = 'publish'

Si la consulta devuelve una publicación, tiene hijos y puede agregar la clase requerida.

Si es para páginas, se puede usar el código de la página siguiente.

enlace

Sin embargo, no parece haber una forma directa de encontrar si existe un hijo.

ACTUALIZACIÓN: Código agregado según su solicitud.

global $wpdb;
$query = $wpdb->prepare("SELECT COUNT(*) FROM $wpdb->posts WHERE post_status ='publish' AND post_type='nav_menu_item' AND post_parent=%d", $item->ID);
$child_count = $wpdb->get_var($query);
if($child_count > 0) { /* THE MENU ELEMENT HAS CHILDREN */
   .....
} else {
   .....
}
    
respondido por el tamilsweet 23.12.2011 - 07:59

Lea otras preguntas en las etiquetas