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

29

( Remarque du modérateur: s'appelait à l'origine "wp_nav_menu classe d'ancêtre sans enfants dans la structure de navigation")

J'ai dans mon en-tête un wp_nav_menu contenant trois pages. Lorsque je suis sur l'une de ces pages, le 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 réalité, les "enfants" perçus de cette page de niveau supérieur ne sont pas réellement des enfants, ils sont simplement du 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 - sinon, faites-moi savoir où je vous ai perdu! Apprécions beaucoup toute aide.

- Édité pour plus de détails: Par exemple, j'ai une page statique appelée Workshops 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é workshops . 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 ne font qu'un tapez mais sans rapport avec la page. C’est cette lacune que je dois combler efficacement dans le menu, en mettant en évidence 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!

    
posée Gavin 18.10.2010 - 20:42
la source

7 réponses

29

Il existe 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 les menus Apparence- > Il suffit de mettre l’URL qui renverra votre type personnalisé et de lui attribuer une étiquette, puis cliquez sur "Ajouter au menu".

http://example.com/workshops/

ou non-jolie-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ée, et ajoutera également la classe d'élément de menu en cours lorsque vous aurez cliqué sur cet élément de navigation - mais ce ne sera pas encore le cas. ajouter la classe de navigation 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 de message personnalisé dans le champ "Attribut de titre" (vous pouvez également utiliser le champ de description, mais celui-ci est masqué dans le champ "Attribut de titre". options de l'écran administrateur par défaut).

Maintenant, vous devez accrocher le filtre nav_menu_css_class (qui est activé 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 tel est le cas, nous ajoutons la classe item-menu-item à son tableau de classes, puis nous renvoyons le tableau modifié.

Vous pouvez le modifier pour qu'il corresponde simplement au titre de l'élément de navigation. Toutefois, si, pour une raison quelconque, vous souhaitez attribuer un titre à l'élément de navigation différent du slug ordinaire du type d'article, l'utilisation du champ Attribut du titre ou Description vous offre cette souplesse .

Maintenant, 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 current-menu de la classe CSS afin que votre surbrillance fonctionne.

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

BONUS

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'
        )
    );
}
    
réponse donnée somatic 19.10.2010 - 07:25
la source
4

au lieu d'utiliser

  

$ post_type =   get_query_var ('post_type');

Vous voudrez peut-être essayer:

  

$ post_type = get_post_type ();

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é depuis une page de liste, vous devrez l'utiliser. get_very_var () renvoie simplement une chaîne vide pour les types d'article 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;
}
    
réponse donnée Eric 17.03.2011 - 15:18
la source
2

@Somatic - c'est fantastique! J'ai légèrement modifié votre code afin qu'il fonctionne également pour une taxonomie spécifique (que je n'utilise que 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;
}
    
réponse donnée tzeldin88 13.04.2011 - 02:12
la source
2

Voici ma solution si vous souhaitez utiliser 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 une valeur_option avec le page ID vous souhaitez vous connecter.

Vous avez peut-être reconnu qu'il existe déjà une option appelée page_for_posts . Si vous n’avez qu’un seul 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 la page courante correctement.

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

    
réponse donnée Temo 13.06.2011 - 20:58
la source
2

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 également ajouté des classes de corps à 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 de publication personnalisés liés à la page comme 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;}
    
réponse donnée Steve 15.10.2011 - 04:28
la source
1

@Somatic - Excellent code! J'ai fait un changement moi-même. Je voulais conserver l'attribut Title comme il se doit, donc j'ai plutôt 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é en

if ($item->xfn != '' && $item->xfn == $post_type) {
    
réponse donnée user8899 23.09.2011 - 21:30
la source
0

Beau travail Somatic.

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 que je ne l'ajoute pas à une page, je n'ai que 404 pages.

Si je fais comme Gavin, je vous ai un peu modifié pour supprimer également 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;

}

    
réponse donnée Vayu 10.12.2010 - 13:36
la source

Lire d'autres questions sur les étiquettes