Agregue una clase .last al último li en cada ul.sub-menu

4

He visto muchos códigos sobre cómo agregar una clase first y last a un menú de WordPress, pero en mi instancia me gustaría agregar una clase last a la última li en el sub -menu que genera WP. Esto es lo que me gustaría lograr en su forma más simple.

<ul>
    <li>Menu item one</li>
    <li class="has-sub-menu">Menu item two
        <ul class="sub-menu">
            <li>Sub menu item one</li>
            <li>Sub menu item two</li>
            <li class="last">Sub menu item three</li>
        </ul>
    </li>
    <li>Menu item three</li>
</ul>

Y aquí está lo que tengo actualmente, que agrega las clases primera y última solo a los elementos del menú principal. ¿Podría ser adaptado?

function add_first_and_last($items) {
    $items[1]->classes[] = 'first';
    $items[count($items)]->classes[] = 'last';
    return $items;
}

add_filter('wp_nav_menu_objects', 'add_first_and_last');

Me gustaría seguir con php para esto y no usar :last-child (quiero que funcione en ie7 & 8) o jQuery.

    
pregunta Andrew 14.04.2012 - 12:11

3 respuestas

4

Ponga lo siguiente en su functions.php

class SH_Last_Walker extends Walker_Nav_Menu{

   function display_element( $element, &$children_elements, $max_depth, $depth=0, $args, &$output ) {

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

       //If the current element has children, add class 'sub-menu'
       if( isset($children_elements[$element->$id_field]) ) { 
            $classes = empty( $element->classes ) ? array() : (array) $element->classes;
            $classes[] = 'has-sub-menu';
            $element->classes =$classes;
       }
        // We don't want to do anything at the 'top level'.
        if( 0 == $depth )
            return parent::display_element( $element, $children_elements, $max_depth, $depth, $args, $output );

        //Get the siblings of the current element
        $parent_id_field = $this->db_fields['parent'];      
        $parent_id = $element->$parent_id_field;
        $siblings = $children_elements[ $parent_id ] ;

        //No Siblings?? 
        if( ! is_array($siblings) )
            return parent::display_element( $element, $children_elements, $max_depth, $depth, $args, $output );

        //Get the 'last' of the siblings.
        $last_child = array_pop($siblings);
        $id_field = $this->db_fields['id'];

            //If current element is the last of the siblings, add class 'last'
        if( $element->$id_field == $last_child->$id_field ){
            $classes = empty( $element->classes ) ? array() : (array) $element->classes;
            $classes[] = 'last';
            $element->classes =$classes;
        }

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

Uso

Cuando use wp_nav_menu y desee que se agregue la clase 'última', especifique el caminante arriba:

wp_nav_menu( array('theme_location'=>'primary','walker' => new SH_Last_Walker(),'depth' => 0) ); 

theme_location y depth pueden ser lo que quieras, la parte importante es el atributo walker .

Observaciones laterales

Este código se puede mejorar, potencialmente eliminando la configuración de cada elemento de la matriz $children_elements[$parent_id] cuando se le llama y verificando cuándo es el último elemento (es decir, cuando contiene solo un elemento). Creo que wp_list_filter sería adecuado aquí. Esto podría no mejorar la eficiencia, pero podría ser más ordenado.

Además, puede codificar los campos principal y de identificación. No lo he hecho para la portabilidad. La siguiente clase podría extender cualquiera de las extensiones proporcionadas de la Clase Walker (listas de páginas, listas de categorías, etc.).

    
respondido por el Stephen Harris 14.04.2012 - 13:32
3

La jQuery se vería así:

jQuery(document).ready( function($) {
    $('.sub-menu > li:last-child').addClass('last-item');

} );

Pero en cuanto a PHP, lea esta respuesta proporcionada por Rarst AQUÍ y vea si esto le ayuda en algo.

ACTUALIZACIÓN

La solución

Rart 'del enlace anterior funciona de hecho y el fragmento de código es:

add_filter( 'wp_nav_menu_items', 'first_last_class' );

function first_last_class( $items ) {

    $first = strpos( $items, 'class=' );

    if( false !== $first )
         $items = substr_replace( $items, 'first ', $first+7, 0 );

    $last = strripos( $items, 'class=');

    if( false !== $last )
         $items = substr_replace( $items, 'last ', $last+7, 0 );

    return $items;
}

La salida me dio algo como esto;

<ul>
    <li class="first">Menu item one</li>
    <li>Menu item two
        <ul class="sub-menu">
            <li class="first">Sub menu item one</li>
            <li>Sub menu item two</li>
            <li class="last">Sub menu item three</li>
        </ul>
    </li>
    <li class="last">Menu item three</li>
</ul>

Lo que significa que puedes aplicar un estilo a tu elemento ul ul li mediante los selectores de CSS con éxito.

    
respondido por el userabuser 14.04.2012 - 12:24
2

algo a considerar: mientras que IE7 e IE8 no son compatibles con el último hijo, sí lo son para el primer hijo. por lo tanto, dependiendo de qué CSS necesite aplicar de manera diferente al último elemento, podría revertirlo.

también, FWIW, su tema ya está usando jQuery en otras áreas de forma predeterminada (sección de comentarios, por ejemplo), por lo que sería una opción más rápida y limpia.

    
respondido por el Norcross 14.04.2012 - 15:01

Lea otras preguntas en las etiquetas