Ajouter une classe .last au dernier li de chaque ul.sous-menu

4

J'ai vu beaucoup de code sur la façon d'ajouter une classe first et last à un menu WordPress, mais dans mon cas, j'aimerais ajouter une classe last au dernier li du sous-menu -menu que WP génère. Voici ce que je voudrais réaliser sous sa forme la plus 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>

Et voici ce que j'ai actuellement, qui ajoute la première et la dernière classe aux seuls éléments du menu parent. Cela pourrait-il être adapté?

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

Je voudrais rester avec php pour cela et ne pas utiliser ni :last-child (je veux que ça marche dans ie7 & 8;) ou jQuery.

    
posée Andrew 14.04.2012 - 12:11

3 réponses

4

Mettez les informations suivantes dans votre 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 );
    }
}

Utilisation

Si vous utilisez wp_nav_menu et que vous souhaitez ajouter la "dernière" classe, spécifiez le randonneur ci-dessus:

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

theme_location et depth peuvent être ce que vous voulez, la partie importante est l'attribut walker .

Remarques secondaires

Ce code peut être amélioré - éventuellement en dé-définissant chaque élément du tableau $children_elements[$parent_id] lorsqu’il est appelé et en vérifiant quand il s’agit du dernier élément (c’est-à-dire quand il ne contient qu’un seul élément). Je pense que wp_list_filter conviendrait ici. Cela pourrait ne pas améliorer l'efficacité, mais pourrait être plus simple.

De plus, vous pouvez coder en dur les champs parent et id. Je ne l’ai pas encore fait pour la portabilité. La classe suivante pourrait être en mesure d’étendre l’une quelconque des extensions fournies de la classe Walker (listes de pages, listes de catégories, etc.).

    
réponse donnée Stephen Harris 14.04.2012 - 13:32
3

Le jQuery ressemblerait à quelque chose comme ceci;

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

} );

Mais comme pour le PHP, jetez un oeil à cette réponse de Rarst ICI et voyez si cela vous aide du tout.

MISE À JOUR

La solution "Rart" à partir du lien ci-dessus fonctionne-t-elle réellement et l'extrait de code est;

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 sortie m'a donné quelque chose comme ça;

<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>

Ce qui signifie que vous pourrez ensuite styliser votre élément ul ul li via les sélecteurs CSS.

    
réponse donnée userabuser 14.04.2012 - 12:24
2

quelque chose à considérer: bien que IE7 et IE8 ne supportent pas le dernier-enfant, ils soutiennent le premier-enfant. donc, selon le type de CSS à appliquer différemment au dernier élément, vous pouvez l’inverser.

De même, FWIW, votre thème utilise déjà jQuery dans d’autres zones par défaut (section de commentaires, par exemple), ce qui en ferait une option plus rapide et plus propre.

    
réponse donnée Norcross 14.04.2012 - 15:01

Lire d'autres questions sur les étiquettes