Hinzufügen der ersten / letzten CSS-Klassen zu Menüs

15

ist das möglich, ohne Javascript-Hacks? so was:

<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
quelle
1
Was ist los mit Javascript? Ist es die Kernfunktionalität, für die sie sind? Oder könnte es als eine fortschreitende Verbesserung angesehen werden?
Mild Fuzz

Antworten:

14

Ein besserer und einfacherer Ansatz:

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
quelle
1
Schön und einfach. Ich mag das!
Jonathan Wold
Ich sehe, dass dieser Code für benutzerdefinierte Navigationsmenüs funktioniert (ich habe gesehen, dass er in einem benutzerdefinierten Menü-Widget funktioniert), aber er funktioniert nicht in demselben Menü, das in der primären Navigationsleiste verwendet wird (getestet in Twenty Eleven). Sollte es sein? oder wäre das ein anderer code? oder nur ein anderer filter? Vielen Dank!
Evan Mattson
2
Dies funktioniert für ein Menü auf einer Ebene, jedoch möglicherweise nicht für ein komplexeres Menü, da es zu diesem Zeitpunkt ein Array mit allen Elementen und nicht mit den Elementen auf der obersten Ebene enthält.
Rarst
6

Hier ist ein grober Ausschnitt, der sich darum kümmert, die Menüausgabe zu ändern und die erste / letzte zur ersten und letzten Klasse hinzuzufügen (die äußere Klasse ulwird zu diesem Zeitpunkt nicht angewendet, zählt also nicht). Hinweis - benötigt PHP5 fürstrripos()

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

Ich bin ein bisschen festgefahren, wie es mit verschachtelten Listen umgehen soll, aber es sollte Ihnen zumindest den Einstieg erleichtern.

Rarst
quelle
6

Hier ist eine Funktion, mit der nur die erste / letzte Klasse zu den übergeordneten Menüelementen hinzugefügt wird. Für die meisten CSS-Stile ist dies alles, was erforderlich ist.

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
quelle
1
genau das, wonach ich gesucht habe. Vielen Dank. es ist überraschend, dass wp_nav_menu dies nicht automatisch
tut
Genau. Ich glaube, es gab für eine Weile eine Feature-Anfrage im Wordpress-Bugtracker, aber es wurde nichts daraus. Zumindest die richtigen Filter sind vorhanden, damit wir diese Klassen hinzufügen können;).
Chaoix
1
Vielen Dank. War auf der Suche nach der Theke, die im Menü Walker verwendet werden konnte. Ihre Antwort erlaubt dies. Gerade $ item-> number = $ i hinzugefügt; und habe es in der Gehhilfe. Vielen Dank!!!
BasTaller
5

Weitere Informationen zur neuen Menü-API in WordPress 3. Sie können jedem Element manuell eine eigene Klasse zuweisen. Einmal gemeistert, macht es das Bearbeiten von Menüs zum Vergnügen.

Milder Flaum
quelle
2
Dies ist der richtige Weg. Rufen Sie einfach das Navigationsmenü im Administrator auf und fügen Sie eine Klasse zum ersten und letzten Element hinzu. Wenn der Benutzer diese Menüelemente verschiebt, müssen die Klassen natürlich neu zugewiesen werden, aber dies ist meiner Meinung nach die gültigste / beste Antwort (da keine Codierung beteiligt ist).
t31os
5

Wenn Sie verschachtelte Menüs haben

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

Ich mag die Einfachheit von Ismaeljs Antwort, aber es muss mehr geben, wenn Sie Untermenüklassen wollen.

brent
quelle
2

Wenn Sie keine Unterstützung für IE8 oder niedriger benötigen, vergessen Sie nicht, dass Sie auch reines CSS verwenden können:

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

Die Unterstützung von jQuery-Browsern ist noch besser, aber es hört sich so an, als würden Sie versuchen, dies zu vermeiden.

mrwweb
quelle
Ich benutze das, weil last-child jetzt auch vom IE 9 unterstützt wird und es mir nicht mehr so ​​wichtig ist, zB 8, 7 ..
Alex
2

Hier ist ein besserer Code zum Hinzufügen der ersten und letzten Menüelementklassen, der die Unterstützung für verschachtelte Untermenüs enthält.

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;

}

Sie können den Kern finden hier und das zugehörige Tutorial hier .

Thomas
quelle
0

Wie wäre es mit:

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

und vielleicht einige http://selectivizr.com/

bin
quelle
Dies würde den ersten <li>in jeder ungeordneten Liste auf der Site formatieren, nicht nur im Menü. Es ist auch im Wesentlichen identisch mit dieser Antwort wordpress.stackexchange.com/a/63128/9844
mrwweb
Entschuldigung, Pseudocode.
am
0

Reines CSS, funktioniert bei mir. Dies funktioniert auch mit Untermenüs

ul.nav>li:last-of-type a
Dan Green-Leipciger
quelle
nur in IE9 und höher, was es für so ziemlich alles ausschließt, was ich tue :)
Milo