web-dev-qa-db-fra.com

Mise en surbrillance wp_nav_menu () Classe d'ancêtres sans enfants dans la structure de navigation?

( Note du modérateur: A été initialement intitulé "wp_nav_menu Classe d'ancêtre sans enfants dans la structure de navigation")}

J'ai un wp_nav_menu dans mon en-tête qui contenait trois pages. Lorsque je suis sur l'une de ces pages, la li contenant cette page dans le menu obtient la classe .current_page_item. Ces trois pages ont des modèles, et ces modèles contiennent des requêtes personnalisées pour obtenir toutes les publications d'un certain type de contenu. En effet, les "enfants"} perçus de cette page de niveau supérieur ne sont pas réellement des enfants, ils sont simplement d'un type de contenu que j'ai associé à cette page de niveau supérieur à l'aide d'un modèle.

J'aimerais que les éléments de menu de niveau supérieur obtiennent une classe 'current-ancestor' lorsque l'utilisateur parcourt une seule page d'un type de publication spécifique, à nouveau, associé à cette page uniquement dans une requête personnalisée dans le fichier de modèle.

J'espère que cela a du sens - si non, laissez-moi savoir où je vous ai perdu! Apprécions beaucoup toute aide.

- Edité pour plus de détails: Par exemple, j'ai une page statique appelée Ateliers qui utilise un modèle. Sa limace est ateliers. Le modèle comporte une fonction get_posts personnalisée et une boucle dans celle-ci, qui extrait et affiche toutes les publications d’un type de contenu personnalisé appelé ateliers. Si je clique sur le titre de l'un de ces ateliers, je découvre tout le contenu de ce contenu. La structure de permalien du type de message personnalisé est définie sur workshops/postname, de sorte que, comme le voit l'utilisateur, ces éléments de contenu sont des enfants de la page Workshops, alors qu'en réalité ils sont tous d'un même type de contenu. mais sans rapport avec la page. C'est cet espace que je dois combler efficacement dans le menu, en mettant en surbrillance l'élément de menu "Ateliers" lors de la navigation dans le contenu de type "atelier".

Encore une fois, espérons que cela a du sens, je pense avoir dit "atelier" plus de 20 fois en un paragraphe!

30
Gavin

Il y a une solution plus simple. Oubliez la création de pages pour chaque type d'article afin de pouvoir disposer d'éléments de navigation, car, comme vous l'avez appris, WP n'a aucun moyen de reconnaître que les types personnalisés que vous parcourez sont liés à cette page.

Au lieu de cela, créez un lien personnalisé dans Apparence-> Menus. Il suffit de mettre l'URL qui va retourner votre type personnalisé et lui donner une étiquette, puis appuyez sur "Ajouter au menu".

http://example.com/workshops/

ou non-jolis-permaliens:

http://example.com/?post_type=workshops

cela seul créera simplement un bouton de navigation qui affichera toutes les publications avec ce type de publication personnalisé, et ajoutera également la classe d'élément de menu en cours lorsque vous aurez cliqué sur cet élément de navigation - mais il n'ajoutera pas encore la navigation. classe sur n'importe quelle URL autre que celle-ci

Ensuite, une fois créé, accédez à la configuration de ce nouvel élément et entrez le slug du type d'article personnalisé dans le champ "Attribut de titre" (vous pouvez également utiliser le champ de description, mais celui-ci est masqué dans les options de l'écran d'administration. par défaut).

Maintenant, vous devez accrocher le filtre nav_menu_css_class (qui est déclenché pour chaque élément de navigation) et vérifier si le contenu affiché est du type de message indiqué dans votre élément de navigation personnalisé:

add_filter('nav_menu_css_class', 'current_type_nav_class', 10, 2 );
function current_type_nav_class($classes, $item) {
    $post_type = get_query_var('post_type');
    if ($item->attr_title != '' && $item->attr_title == $post_type) {
        array_Push($classes, 'current-menu-item');
    };
    return $classes;
}

Dans ce cas, nous allons vérifier que le contenu du champ Attribut de titre n'est pas vide et s'ils correspondent au type de post_type en cours de requête. Si c'est le cas, nous ajoutons la classe d'item de menu en cours à son tableau de classes, puis nous retournons le tableau modifié.

Vous pouvez le modifier pour qu'il corresponde simplement au titre de l'élément de navigation, mais si, pour une raison quelconque, vous souhaitez titrer l'élément de navigation différemment du slug ordinaire du type de publication, l'utilisation du champ Attribut du titre ou Description vous offre cette souplesse.

Désormais, chaque fois que vous visualisez un seul élément (ou probablement même des listes d'archives) d'un type d'article correspondant à un élément de menu de navigation, cet élément se voit attribuer l'élément de menu actuel de la classe CSS afin que votre surbrillance fonctionne.

Pas de pages ni de modèles de page nécessaires ;-) La requête d'URL se charge de récupérer les bons messages. Votre modèle de boucle prend en charge l'affichage de la sortie de la requête. Cette fonction prend en charge la reconnaissance de ce qui est affiché et l’ajout de la classe CSS.

PRIME

Vous pouvez même automatiser le processus à l'aide de wp_update_nav_menu_item, en générant automatiquement des éléments de menu pour tous vos types de publication. Pour cet exemple, vous devez d’abord avoir récupéré le $menu_id du menu de navigation auquel vous souhaitez ajouter ces éléments.

$types = get_post_types( array( 'exclude_from_search' => false, '_builtin' => false  ), 'objects' );
foreach ($types as $type) {
    wp_update_nav_menu_item( $menu_id, 0, array(
        'menu-item-type' => 'custom',
        'menu-item-title' => $type->labels->name,
        'menu-item-url' => get_bloginfo('url') . '/?post_type=' . $type->rewrite['slug'],
        'menu-item-attr-title' => $type->rewrite['slug'],
        'menu-item-status' => 'publish'
        )
    );
}
29
somatic

à la place d'utiliser

$ post_type = get_query_var ('post_type');

Vous voudrez peut-être essayer:

$ post_type = get_post_type ();

Comme parfois, le type de publication n'est pas défini dans la requête var. C'est le cas pour le post_type par défaut de "post". Par conséquent, si vous souhaitez mettre en surbrillance un message répertorié à partir d'une page de liste, vous devrez l'utiliser. get_very_var () renvoie simplement une chaîne vide pour les types de publication qui ne sont pas personnalisés.

add_filter('nav_menu_css_class', 'current_type_nav_class', 10, 2 );
function current_type_nav_class($classes, $item) {
    $post_type = get_post_type();
    if ($item->attr_title != '' && $item->attr_title == $post_type) {
        array_Push($classes, 'current-menu-item');
    };
    return $classes;
}
4
Eric

@Somatic - c'est fantastique! J'ai légèrement modifié votre code pour qu'il fonctionne également pour une taxonomie spécifique (que j'utilise uniquement pour le post_type associé). L'idée est d'utiliser l'attribut Title de l'élément de menu pour stocker à la fois le nom du type post_type ET le nom de la taxonomie, séparés par un point-virgule, puis décomposés par la fonction.

add_filter('nav_menu_css_class', 'current_type_nav_class', 10, 2 );
function current_type_nav_class($classes, $item) {

    # get Query Vars
    $post_type = get_query_var('post_type');  
    $taxonomy = get_query_var('taxonomy');

    # get and parse Title attribute of Menu item
    $title = $item->attr_title; // menu item Title attribute, as post_type;taxonomy
    $title_array = explode(";", $title);
    $title_posttype = $title_array[0];
    $title_taxonomy = $title_array[1];

    # add class if needed
    if ($title != '' && ($title_posttype == $post_type || $title_taxonomy == $taxonomy)) {
        array_Push($classes, 'current-menu-item');
    };
    return $classes;
}
2
tzeldin88

J'ai décidé de m'en tenir aux pages et d'utiliser le nom du modèle de page en tant que classe sur l'élément de navigation. Cela me permet d'éviter d'encombrer l'attribut title, ce qui ne me plaisait pas avec certaines des autres solutions.

add_filter('nav_menu_css_class', 'mbudm_add_page_type_to_menu', 10, 2 );
//If a menu item is a page then add the template name to it as a css class 
function mbudm_add_page_type_to_menu($classes, $item) {
    if($item->object == 'page'){
        $template_name = get_post_meta( $item->object_id, '_wp_page_template', true );
        $new_class =str_replace(".php","",$template_name);
        array_Push($classes, $new_class);
        return $classes;
    }   
}

J'ai aussi des classes de corps ajoutées à header.php

<body <?php body_class(); ?>>

Enfin, cette solution nécessite quelques css supplémentaires pour appliquer l’état sélectionné/actif aux éléments de votre menu de navigation. Je l'utilise pour afficher les archives de taxonomie et les types d'articles personnalisés liés à la page en tant qu'enfants de cette page:

/* selected states - include sub pages for anything related to products */
#nav-main li.current-menu-item a,
body.single-mbudm_product #nav-main li.lp_products a,
body.tax-mbudm_product_category #nav-main li.lp_products a,
#nav-main li.current_page_parent a{color:#c00;}
2
Steve

Voici ma solution si vous voulez travailler avec wp_list_pages.

ajoutez ceci dans votre functions.php

add_filter('page_css_class', 'my_page_css_class', 10, 2);
function my_page_css_class($css_class, $page){
    $post_type = get_post_type();
    if($post_type != "page"){
        $parent_page = get_option('page_for_custom_post_type-'.$post_type);
        if($page->ID == $parent_page)
            $css_class[] = 'current_page_parent';
    }
    return $css_class;
}

Ajoutez maintenant à la table wp_options une nouvelle ligne avec un nom_option de page_pour_custom_post_type-xxxx et un valeur_option avec le page-ID u voulez se connecter.

Peut-être avez-vous reconnu qu'il existe déjà une option appelée page_for_posts . Si vous avez seulement 1 type de message personnalisé, vous pouvez définir votre page dans /wp-admin/options-reading.php dans le menu déroulant et la navigation définira correctement la page en cours.

Je pense que wordpress core devrait étendre cette section avec un menu déroulant pour chaque type de message enregistré.

2
Temo

@Somatic - Excellent code! J'ai fait un changement moi-même. Je voulais conserver l'attribut de titre pour l'usage auquel il était destiné. J'ai donc placé le slug Custom Post Type dans les propriétés du menu avancé Link Relationship (XFN) que vous pouvez activer dans les options d'écran. j'ai modifié

if ($item->attr_title != '' && $item->attr_title == $post_type) {

et l'a changé pour

if ($item->xfn != '' && $item->xfn == $post_type) {
1
user8899

Beau travail somatique.

Malheureusement, je ne comprends pas comment vous pouvez répertorier vos types d'articles personnalisés dans une page de la manière que vous expliquez. Si je n'utilise pas un page-portfolio.php et ne l'ajoute pas à une page, tout ce que je reçois est 404 page.

Si je fais comme Gavin, j’ai un peu modifié votre fonction pour supprimer aussi le "current_page_parent" de la page du blog comme ceci.

add_filter('nav_menu_css_class', 'current_type_nav_class', 10, 2);
function current_type_nav_class($css_class, $item) {
$post_type = get_query_var('post_type');

if (get_post_type()=='portfolio') {
    $current_value = "current_page_parent"; 
    $css_class = array_filter($css_class, function ($element) use ($current_value) { return ($element != $current_value); } );
}

if ($item->attr_title != '' && $item->attr_title == $post_type) {       
    array_Push($css_class, 'current_page_parent');
};
return $css_class;

}

0
Vayu