WordPress

Niestandardowa klasa do menu nawigacyjnego wp

  • 5 lipca, 2013
  • 4 min read
Niestandardowa klasa do menu nawigacyjnego wp


To stare pytanie, ale może być bardzo aktualne dzisiaj, więc pomyślałem, że porzucę fragment kodu, który opracowałem przez lata. Jest to w zasadzie tak blisko, jak to tylko możliwe, aby dostosować klasy do każdego elementu menu w WordPress bez opracowywania niestandardowego Nav Walkera. Staje się to coraz bardziej istotne w przypadku opartych na narzędziach frameworków CSS, takich jak Tailwind, które naprawdę wymagają dostępu do znaczników lub opcji dodawania własnych klas.

Wykorzystuje większość filtrów dostępnych w funkcji i cyklu życia WordPress wp_nav_menu, aby dodawać klasy wszędzie. Najpierw używasz wp_nav_menu jak zwykle, ale następnie przekazujesz niestandardowe parametry do funkcji. Te niestandardowe parametry są następnie wykrywane przez filtry i dodają klasy tam, gdzie powinny.

Można by na przykład utworzyć niestandardowe menu rozwijane, dodając tylko klasy do elementów listy pierwszego poziomu lub dodając obraz tła/ikonę tylko do linków trzeciego poziomu. Wszystkie możliwe opcje są szczegółowo opisane w bloku dokumentów u góry.

<?php
/**
 * WordPress filters to allow custom arguments to wp_nav_menu to,
 * in turn, allow custom classes to every element of a menu.
 *
 * You can apply a class only to certain depth of your menu as well.
 *
 * The filters use the depth argument given by WordPress
 * which is an index, thus starts with level 0 (zero).
 *
 * Custom Arguments supported : 
 * link_atts or link_atts_$depth            ->      Add any attribute to <a> elements
 * a_class or a_class_$depth                ->      Add classes to <a> elements
 * li_class or li_class_$depth              ->      Add classes to <li> elements
 * submenu_class or submenu_class_$depth    ->      Add classes to submenu <ul> elements
 *
 * Ex.: add a "text-black" class to all links and "text-blue" class only to 3rd level links
 * wp_nav_menu([
 *     'theme_location' => 'primary_navigation',
 *     'a_class' => 'text-black',
 *     'a_class_2'
 *     ...
 * ])
 *
 * Ex.: More complete example with some TailwindCSS classes and AlpineJS sugar
 * wp_nav_menu([
 *     'theme_location' => 'primary_navigation',
 *     'menu_class' => 'relative w-full z-10 pl-0 list-none flex',
 *     'link_atts_0' => [
 *         ":class" => "{ 'active': tab === 'foo' }",
 *         "@click" => "tab = 'foo'"
 *     ],
 *     'li_class' => 'w-full',
 *     'li_class_0' => 'mb-12',
 *     'a_class' => 'text-sm xl:text-xl text-white border-b hover:border-white',
 *     'a_class_0' => 'text-3xl xl:text-5xl relative dash-left js-stagger  a-mask after:bg-primary',
 *     'li_class_1' => 'js-stagger a-mask after:bg-primary hidden lg:block',
 *     'a_class_1' => 'flex h-full items-center uppercase py-2 relative border-white border-opacity-40 hover:border-opacity-100',
 *     'submenu_class' => 'list-none pl-0 grid grid-cols-1 lg:grid-cols-2 lg:gap-x-12 xl:gap-x-24 xxl:gap-x-32',
 *     'container'=>false
 * ])
 * 
 * @author davidwebca
 * @link 
 */


/**
 * Add custom attributes or classes to links in wp_nav_menu
 */
add_filter( 'nav_menu_link_attributes', function ( $atts, $item, $args, $depth ) {
    if (property_exists($args, 'link_atts')) {
        $atts = array_merge($atts, $args->link_atts);
    }
    if (property_exists($args, "link_atts_$depth")) {
        $atts = array_merge($atts, $args->{"link_atts_$depth"});
    }

    if(empty($atts['class'])) {
        $atts['class'] = '';
    }

    $classes = explode(' ', $atts['class']);

    /**
     * Fix for tailwindcss classes that include ":" (colon)
     * Enter triple underscore hover___text-primary instaed of hover:text-primary
     *
     * Some filters provided so that you can customize your own replacements,
     * passed directly to preg_replace so supports array replacements as well.
     *
     * WordPress trac following the issue of escaping CSS classes:
     * @link 
     */
    $patterns = apply_filters( 'nav_menu_css_class_unescape_patterns', '/___/');
    $replacements = apply_filters( 'nav_menu_css_class_unescape_replacements', ':' );
    $classes = array_map(function($cssclass) use( $patterns, $replacements) {
        return preg_replace($patterns, $replacements, $cssclass);
    }, $classes);

    if (property_exists($args, 'a_class')) {
        $arr_classes = explode(' ', $args->a_class);
        $classes = array_merge($classes, $arr_classes);
    }
    if (property_exists($args, "a_class_$depth")) {
        $arr_classes = explode(' ', $args->{"a_class_$depth"});
        $classes = array_merge($classes, $arr_classes);
    }

    $atts['class'] = implode(' ', $classes);

    return $atts;
}, 1, 4 );

/**
 * Add custom classes to lis in wp_nav_menu
 */
add_filter( 'nav_menu_css_class', function ( $classes, $item, $args, $depth ) {
    if (property_exists($args, 'li_class')) {
        $arr_classes = explode(' ', $args->li_class);
        $classes = array_merge($classes, $arr_classes);
    }
    if (property_exists($args, "li_class_$depth")) {
        $arr_classes = explode(' ', $args->{"li_class_$depth"});
        $classes = array_merge($classes, $arr_classes);
    }

    return $classes;
}, 1, 4 );

/**
 * Add custom classes to ul.sub-menu in wp_nav_menu
 */
add_filter('nav_menu_submenu_css_class', function( $classes, $args, $depth ) {
    if (property_exists($args, 'submenu_class')) {
        $arr_classes = explode(' ', $args->submenu_class);
        $classes = array_merge($classes, $arr_classes);
    }

    if (property_exists($args, "submenu_class_$depth")) {
        $arr_classes = explode(' ', $args->{"submenu_class_$depth"});
        $classes = array_merge($classes, $arr_classes);
    }

    return $classes;
}, 1, 3);


Źródło

Warto przeczytać!  Jak tworzyć kompaktowe archiwa w WordPress (krok po kroku)