Plantilla de WordPress - Cómo agregar clase a la etiqueta li si existe submenú

16 feb 2015, 13:38:33
Vistas: 18.3K
Votos: 0

Por ejemplo, quiero crear este menú:

<div class="menu_wrap">
 <ul class="nav sf-menu">
  <li class="sub-menu"><a href="">Menú Principal 1</a>
    <ul>
        <li><a href=""><span>-</span>Submenú 1</a></li>
        <li><a href=""><span>-</span>Submenú 2</a></li>
    </ul>
  </li>
  <li class="sub-menu"><a href="">Menú Principal 2</a>
    <ul>
        <li><a href=""><span>-</span>Submenú 1</a></li>
        <li><a href=""><span>-</span>Submenú 2</a></li>
    </ul>
  </li>
  <li><a href="">Menú Principal 3 sin submenú</a></li>
</ul>

Cómo agregar class="sub-menu" en la etiqueta li(s) que tengan submenú:

<li class="sub-menu"><a href="">Menú Principal 1</a>

Si no existe submenú, mostrar li sin class="sub-menu":

<li><a href="">Menú Principal 3 sin submenú</a></li>

Tengo este código en functions.php:

// Agrega menús
    add_theme_support( 'menus' );
    register_nav_menus(
            array(
                'mainmenu' => 'El Menú Principal'
            )
        );
    function dtuts_main_nav() {
        // muestra el menú de wp3 si está disponible
        wp_nav_menu(array(
            'theme_location'  => 'mainmenu',
            'menu'            => 'mainmenu',
            'container'       => 'div',
            'container_class' => 'menu_wrap',
            'menu_class'      => 'nav sf-menu',
            'echo'            => true,
            'items_wrap'      => '<ul class="%2$s">%3$s</ul>',
            'depth'           => 1,
            'walker'          => new themeslug_walker_nav_menu
        ));
    }

No puedo escribir la clase themeslug_walker_nav_menu, por favor ayuda.

1
Comentarios

Puedes usar jQuery (javascript).

Mayeenul Islam Mayeenul Islam
16 feb 2015 13:43:05
Todas las respuestas a la pregunta 1
4

Este es el código que estoy usando, es un nav walker personalizado para BootStrap pero podrías adaptarlo fácilmente al tuyo propio. Por cierto, podrías copiar y pegar mi nav walker y asegúrate de cambiar esta línea:

$class_names .= ' dropdown';

a

$class_names .= ' sub-menu';

Espero que esto ayude.

/**
 * Custom Bootstrap Nav Walker
 */

class macho_bootstrap_walker extends Walker_Nav_Menu
{

/**
 * @see Walker::start_lvl()
 * @since 3.0.0
 *
 * @param string $output Pasado por referencia. Usado para añadir contenido adicional.
 * @param int $depth Profundidad de la página. Usado para padding.
 */
public function start_lvl(&$output, $depth = 0, $args = array())
{
    $indent = str_repeat("\t", $depth);
    $output .= "\n$indent<ul role=\"menu\" class=\" dropdown-menu\">\n";
}

/**
 * @see Walker::start_el()
 * @since 3.0.0
 *
 * @param string $output Pasado por referencia. Usado para añadir contenido adicional.
 * @param object $item Objeto de datos del elemento del menú.
 * @param int $depth Profundidad del elemento del menú. Usado para padding.
 * @param int $current_page ID del elemento del menú.
 * @param object $args
 */
public function start_el(&$output, $item, $depth = 0, $args = array(), $id = 0)
{
    $indent = ($depth) ? str_repeat("\t", $depth) : '';

    /**
     * Divisores, Encabezados o Deshabilitados
     * =============================
     * Determina si el elemento es un Divisor, Encabezado, Deshabilitado o un
     * elemento de menú regular. Para prevenir errores usamos la función strcasecmp() para hacer una
     * comparación que no distinga entre mayúsculas y minúsculas. La función strcasecmp() devuelve
     * un 0 si las cadenas son iguales.
     */
    if (strcasecmp($item->attr_title, 'divider') == 0 && $depth === 1) {
        $output .= $indent . '<li role="presentation" class="divider">';
    } else if (strcasecmp($item->title, 'divider') == 0 && $depth === 1) {
        $output .= $indent . '<li role="presentation" class="divider">';
    } else if (strcasecmp($item->attr_title, 'dropdown-header') == 0 && $depth === 1) {
        $output .= $indent . '<li role="presentation" class="dropdown-header">' . esc_attr($item->title);
    } else if (strcasecmp($item->attr_title, 'disabled') == 0) {
        $output .= $indent . '<li role="presentation" class="disabled"><a href="#">' . esc_attr($item->title) . '</a>';
    } else {

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

        if ($args->has_children)
            $class_names .= ' dropdown';

        if (in_array('current-menu-item', $classes))
            $class_names .= ' active';

        $class_names = $class_names ? ' class="' . esc_attr($class_names) . '"' : '';

        $id = apply_filters('nav_menu_item_id', 'menu-item-' . $item->ID, $item, $args);
        $id = $id ? ' id="' . esc_attr($id) . '"' : '';

        $output .= $indent . '<li' . $id . $value . $class_names . '>';

        $atts = array();
        $atts['title'] = !empty($item->title) ? $item->title : '';
        $atts['target'] = !empty($item->target) ? $item->target : '';
        $atts['rel'] = !empty($item->xfn) ? $item->xfn : '';


        $atts['custom'] = !empty($item->custom) ? $item->custom : '';

        // Si el elemento tiene hijos, añade atributos al enlace.
        if ($args->has_children && $depth === 0) {
            $atts['href'] = '#';
            $atts['data-toggle'] = 'dropdown';
            $atts['class'] = 'dropdown-toggle';
            $atts['aria-haspopup'] = 'true';
        } else {
            $atts['href'] = !empty($item->url) ? $item->url : '';
        }

        $atts = apply_filters('nav_menu_link_attributes', $atts, $item, $args);


        $attributes = '';
        foreach ($atts as $attr => $value) {


            if (!empty($value)) {
                $value = ('href' === $attr) ? esc_url($value) : esc_attr($value);
                $attributes .= ' ' . $attr . '="' . $value . '"';
            }
        }

        $item_output = $args->before;

        /*
         * Glyphicons
         * ===========
         * Como el elemento del menú NO es un Divisor o Encabezado, verificamos
         * si hay un valor en la propiedad attr_title. Si la propiedad attr_title
         * NO es nula, la aplicamos como el nombre de clase para el glyphicon.
         */
        if (!empty($item->attr_title))
            $item_output .= '<a' . $attributes . '><span class="glyphicon ' . esc_attr($item->attr_title) . '"></span>&nbsp;';
        else
            $item_output .= '<a' . $attributes . '>';


        $item_output .= $args->link_before . apply_filters('the_title', $item->title, $item->ID) . $args->link_after;
        $item_output .= ($args->has_children && 0 === $depth) ? ' <span class="caret"></span></a>' : '</a>';
        $item_output .= $args->after;

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

/**
 * Recorre elementos para crear una lista a partir de ellos.
 *
 * Muestra un elemento si el elemento no tiene hijos, de lo contrario,
 * muestra el elemento y sus hijos. Solo recorrerá hasta la profundidad máxima
 * y no ignorará elementos por debajo de esa profundidad.
 *
 * Este método no debería llamarse directamente, usa el método walk() en su lugar.
 *
 * @see Walker::start_el()
 * @since 2.5.0
 *
 * @param object $element Objeto de datos
 * @param array $children_elements Lista de elementos para continuar recorriendo.
 * @param int $max_depth Profundidad máxima para recorrer.
 * @param int $depth Profundidad del elemento actual.
 * @param array $args
 * @param string $output Pasado por referencia. Usado para añadir contenido adicional.
 * @return null Nulo en caso de fallo sin cambios en los parámetros.
 */
public function display_element($element, &$children_elements, $max_depth, $depth, $args, &$output)
{
    if (!$element)
        return;

    $id_field = $this->db_fields['id'];

    // Muestra este elemento.
    if (is_object($args[0]))
        $args[0]->has_children = !empty($children_elements[$element->$id_field]);

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

/**
 * Fallback del Menú
 * =============
 * Si esta función se asigna a la variable fallback_cb de wp_nav_menu
 * y no se ha asignado un menú a la ubicación del tema en el administrador de menús
 * de WordPress, la función no mostrará nada a un usuario no logueado,
 * y añadirá un enlace al administrador de menús de WordPress si está logueado como administrador.
 *
 * @param array $args Pasado desde la función wp_nav_menu.
 *
 */
public static function fallback($args)
{
    if (current_user_can('manage_options')) {

        extract($args);

        $fb_output = null;

        if ($container) {
            $fb_output = '<' . $container;

            if ($container_id)
                $fb_output .= ' id="' . $container_id . '"';

            if ($container_class)
                $fb_output .= ' class="' . $container_class . '"';

            $fb_output .= '>';
        }

        $fb_output .= '<ul';

        if ($menu_id)
            $fb_output .= ' id="' . $menu_id . '"';

        if ($menu_class)
            $fb_output .= ' class="' . $menu_class . '"';

        $fb_output .= '>';
        $fb_output .= '<li><a href="' . admin_url('nav-menus.php') . '">Añadir un menú</a></li>';
        $fb_output .= '</ul>';

        if ($container)
            $fb_output .= '</' . $container . '>';

        echo $fb_output;
    }
}
}
16 feb 2015 13:47:21
Comentarios

Aquí va tu voto positivo.

kaiser kaiser
16 feb 2015 14:05:18

El código de TanQ.It funciona, pero quiero deshabilitar otras clases. Este código muestra varias otras clases para la etiqueta ul y li, etc. Solo quiero que muestre class="sub-menu" para la etiqueta li. ¿Cómo puedo hacerlo?

Shahin Ataei Shahin Ataei
16 feb 2015 19:56:52

Modifica el código anterior para que se ajuste a tus necesidades. Esto era solo un punto de partida.

cristian.raiber cristian.raiber
16 feb 2015 20:15:15

gracias. que sea verdadero y funcione. Solo tengo un problema. Quiero agregar un prefijo de caracter como "-". Si el elemento es hijo, que muestre "<span>-</span>" antes del elemento del submenú para la sangría. ¿Cómo puedo hacerlo?

Shahin Ataei Shahin Ataei
17 feb 2015 14:12:16