Ajout de première / dernière classes CSS aux menus

15

est-ce possible, sans piratage javascript? comme ça:

<ul class="my_menu">
  <li class="first"> ... </li>
  <li> ... </li>
  <li> ... </li>
  <li class"with_sub"> ... 
    <ul class="my_menu_sub">
      <li class="first"> ... </li>
      <li> ... </li>
      <li> ... </li>
      <li class="last"> ... </li>
    </ul>
  </li>
  <li> ... </li>
  <li> ... </li>
  <li class="last"> ... </li>
</ul>
Alex
la source
1
quel est le problème avec l'utilisation de javascript? est-ce une fonctionnalité de base à laquelle ils sont destinés? Ou pourrait-il être considéré comme une amélioration progressive?
Mild Fuzz

Réponses:

14

Une approche meilleure et plus simple:

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

add_filter('wp_nav_menu_objects', 'add_first_and_last');
Ismaelj
la source
1
Agréable et simple. Je l'aime!
Jonathan Wold
Je vois que ce code fonctionne pour les menus de navigation personnalisés (je l'ai vu fonctionner dans un widget de menu personnalisé), mais il ne fonctionne pas dans le même menu utilisé dans la barre de navigation principale (testé dans Twenty Eleven). Devrait-ce être? ou serait-ce un code différent? ou juste un filtre différent? Merci!
Evan Mattson
2
Cela fonctionnera pour un menu à un niveau, mais peut-être pas pour un menu plus complexe, car à ce stade, c'est un tableau avec tous les éléments, pas ceux de niveau supérieur.
Rarst
6

Voici un extrait approximatif qui prend en charge la modification de la sortie du menu et l'ajout de la première / dernière à la première et à la dernière classe (externe uln'est pas appliqué à ce stade, donc ne compte pas). Remarque - nécessite PHP5 pourstrripos()

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

Je suis un peu coincé avec la façon de le faire gérer les listes imbriquées, mais cela devrait au moins vous aider à démarrer.

Rarst
la source
6

Voici une fonction pour ajouter uniquement la première / dernière classe aux éléments de menu parent. Pour la plupart des styles CSS, c'est tout ce qui est nécessaire.

function nav_menu_add_classes( $items, $args ) {
    //Add first item class
    $items[1]->classes[] = 'menu-item-first';

    //Add last item class
    $i = count($items);
    while($items[$i]->menu_item_parent != 0 && $i > 0) {
        $i--;
    }
    $items[$i]->classes[] = 'menu-item-last';

    return $items;
}
add_filter( 'wp_nav_menu_objects', 'nav_menu_add_classes', 10, 2 );
Chaoix
la source
1
exactement ce que je cherchais. Merci. c'est un peu surprenant wp_nav_menu ne le fait pas automatiquement
yitwail
Je suis d'accord. Je pense qu'il y a eu une demande de fonctionnalité dans le bugtracker de Wordpress pendant un certain temps, mais rien n'en est sorti. Au moins, les filtres appropriés existent pour que nous puissions ajouter ces classes;).
Chaoix
1
Merci. Je cherchais le comptoir, qui pourrait être utilisé dans le menu walker. votre réponse le permet. Je viens d'ajouter $ item-> number = $ i; et je l'ai mis dans le déambulateur. Merci!!!
BasTaller
5

En savoir plus sur la nouvelle API Menus dans wordpress 3. Vous pouvez donner manuellement à n'importe quel élément sa propre classe. De plus, une fois maîtrisé, cela rend les menus très agréables à modifier.

Doux Fuzz
la source
2
Ce serait la voie à suivre, simplement afficher l'écran du menu de navigation dans l'admin et ajouter une classe aux premier et dernier éléments. Bien sûr, si l'utilisateur déplace ces éléments de menu, les classes devront être réaffectées, mais cela me semble être la réponse la plus valide / la meilleure (car il n'y a pas de codage impliqué).
t31os
5

Si vous avez des menus imbriqués

function add_first_and_last($items) {
    // first class on parent most level
    $items[1]->classes[] = 'first';
    // separate parents and children
    $parents = $children = array();
    foreach($items as $k => $item){
        if($item->menu_item_parent == '0'){
            $parents[] = $k;
        } else {
            $children[$item->menu_item_parent] = $k;
        }
    }
    // last class on parent most level
    $last = end(array_keys($parents));
    foreach ($parents as $k => $parent) {
        if ($k == $last) {
            $items[$parent]->classes[] = 'last';
        }
    }
    // last class on children levels
    foreach($children as $child){
        $items[$child]->classes[] = 'last';
    }
    // first class on children levels
    $r_items = array_reverse($items, true);
    foreach($r_items as $k => $item){
        if($item->menu_item_parent !== '0'){
            $children[$item->menu_item_parent] = $k;
        }
    }
    foreach($children as $child){
        $items[$child]->classes[] = 'first';
    }
    return $items;
}
add_filter('wp_nav_menu_objects', 'add_first_and_last');

J'aime la simplicité de la réponse d'Ismaelj, mais il doit y en avoir plus si vous voulez des classes de sous-menu.

brent
la source
2

Si vous n'avez pas besoin de support pour IE8 ou inférieur, n'oubliez pas que vous pouvez également utiliser du CSS pur:

.my_menu > :first-child,
.my_menu > :last-child {
    /* some styles */
}

La prise en charge du navigateur jQuery est encore meilleure, mais il semble que vous essayez d'éviter cela.

mrwweb
la source
J'utilise cela, parce que le dernier enfant est maintenant pris en charge par IE 9 aussi, et je ne me soucie plus tellement de 8, 7 ..
Alex
2

Voici un meilleur code pour ajouter les première et dernière classes d'élément de menu qui inclut la prise en charge des sous-menus imbriqués.

add_filter( 'wp_nav_menu_objects', 'tgm_filter_menu_class', 10, 2 );
/**
 * Filters the first and last nav menu objects in your menus
 * to add custom classes.
 *
 * This also supports nested menus.
 *
 * @since 1.0.0
 *
 * @param array $objects An array of nav menu objects
 * @param object $args Nav menu object args
 * @return object $objects Amended array of nav menu objects with new class
 */
function tgm_filter_menu_class( $objects, $args ) {

    // Add first/last classes to nested menu items
    $ids        = array();
    $parent_ids = array();
    $top_ids    = array();
    foreach ( $objects as $i => $object ) {
        // If there is no menu item parent, store the ID and skip over the object
        if ( 0 == $object->menu_item_parent ) {
            $top_ids[$i] = $object;
            continue;
        }

        // Add first item class to nested menus
        if ( ! in_array( $object->menu_item_parent, $ids ) ) {
            $objects[$i]->classes[] = 'first-menu-item';
            $ids[]          = $object->menu_item_parent;
        }

        // If we have just added the first menu item class, skip over adding the ID
        if ( in_array( 'first-menu-item', $object->classes ) )
            continue;

        // Store the menu parent IDs in an array
        $parent_ids[$i] = $object->menu_item_parent;
    }

    // Remove any duplicate values and pull out the last menu item
    $sanitized_parent_ids = array_unique( array_reverse( $parent_ids, true ) );

    // Loop through the IDs and add the last menu item class to the appropriate objects
    foreach ( $sanitized_parent_ids as $i => $id )
        $objects[$i]->classes[] = 'last-menu-item';

    // Finish it off by adding classes to the top level menu items
    $objects[1]->classes[] = 'first-menu-item'; // We can be assured 1 will be the first item in the menu :-)
    $objects[end( array_keys( $top_ids ) )]->classes[] = 'last-menu-item';

    // Return the menu objects
    return $objects;

}

Vous pouvez trouver l'essentiel ici et le tutoriel associé ici .

Thomas
la source
0

Que diriez-vous:

 ul li:last-child{
     // do something with the last li
 }

et peut-être quelques http://selectivizr.com/

un m
la source
Ce serait le premier style <li>de chaque liste non ordonnée sur le site, pas seulement dans le menu. Elle est également substantiellement identique à cette réponse wordpress.stackexchange.com/a/63128/9844
mrwweb
Désolé, pseudo code.
le
0

CSS pur, fonctionne pour moi. Cela fonctionnera également avec les sous-menus

ul.nav>li:last-of-type a
Dan Green-Leipciger
la source
uniquement dans IE9 et plus, ce qui l'exclut pour à peu près tout ce que je fais :)
Milo