webentwicklung-frage-antwort-db.com.de

Fügen Sie dem letzten <li> in jedem ul-Untermenü eine letzte Klasse hinzu

Ich habe eine Menge Code zum Hinzufügen einer first- und last-Klasse zu einem WordPress-Menü gesehen, aber in meinem Fall möchte ich der letzten li im Untermenü, das WPenthält, eine last-Klasse hinzufügen. _ erzeugt. Folgendes möchte ich in seiner einfachsten Form erreichen.

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

Und hier ist, was ich derzeit habe, das erste und letzte Klasse nur zu den übergeordneten Menüelementen hinzufügt. Könnte dies angepasst werden?

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

Ich würde gerne bei PHP bleiben und weder :last-child (soll in ie7 & 8 funktionieren) noch jQuery verwenden.

4
Andrew

Tragen Sie folgendes in Ihren functions.php ein

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

Verwendungszweck

Wenn Sie wp_nav_menu verwenden und möchten, dass die letzte Klasse hinzugefügt wird, geben Sie den Wanderer oben an:

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

theme_location und depth können beliebig sein, der wichtige Teil ist das Attribut walker.

Nebenbemerkungen

Dieser Code kann verbessert werden, indem potenziell jedes Element im Array $children_elements[$parent_id] beim Aufruf deaktiviert und überprüft wird, ob es sich um das letzte Element handelt (d. H. Wenn es nur ein Element enthält). Ich denke, wp_list_filter wäre hier geeignet. Dies verbessert möglicherweise nicht die Effizienz, ist jedoch möglicherweise ordentlicher.

Außerdem können Sie die übergeordneten Felder und die ID-Felder fest codieren. Dies wurde aus Gründen der Portabilität nicht durchgeführt. Die folgende Klasse kann möglicherweise eine der bereitgestellten Erweiterungen der Walker-Klasse (Seitenlisten, Kategorielisten usw.) erweitern.

4
Stephen Harris

Die jQuery würde ungefähr so ​​aussehen.

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

} );

Aber was PHP angeht, werfen Sie bitte einen Blick auf diese Antwort von Rarst HIER und sehen Sie, ob dies Ihnen überhaupt hilft.

AKTUALISIEREN

Rart 'Lösung aus dem obigen Link funktioniert es tatsächlich und das Code-Snippet ist;

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

Die Ausgabe gab mir so etwas;

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

Das bedeutet dann, dass Sie Ihr ul ul li -Element über CSS-Selektoren erfolgreich formatieren können.

3
userabuser

was zu beachten ist: Während IE7 und IE8 Last-Child nicht unterstützen, unterstützen sie First-Child. Je nachdem, welches CSS Sie für das letzte Element unterschiedlich anwenden müssen, können Sie es umkehren.

fWIW, Ihr Design verwendet jQuery bereits standardmäßig in anderen Bereichen (z. B. im Kommentarbereich), sodass dies eine schnellere und sauberere Option wäre.

2
Norcross