web-dev-qa-db-ja.com

Wp_nav_menu()Nav構造内の子供のない先祖クラスの強調表示

モデレータによるメモ: 当初は「wp_nav_menuナビゲーション構造内に子がない先祖クラス」というタイトルでした)

ヘッダーにwp_nav_menuがあり、3ページあります。私がそれらのページの1つにいるとき、そのページをメニューに含むliはクラス.current_page_itemを取得します。これら3つのページにはテンプレートがあり、これらのテンプレートには特定のコンテンツタイプのすべての投稿を取得するためのカスタムクエリが含まれています。実際には、このトップレベルページで認識されている "children" は実際には子供ではなく、テンプレートを使用してそのトップレベルページに関連付けたコンテンツタイプにすぎません。

ユーザーが特定の投稿タイプの単一のページを参照しているときに、最上位のメニュー項目に'current-ancestor'クラスを取得してもらいたい。この場合も、テンプレートファイルのカスタムクエリでのみそのページに関連付けられています。

それが理にかなっていることを願っています - そうでなければ、私があなたを失った場所を私に知らせてください!どうもありがとうございました。

- 詳細の編集: たとえば、テンプレートを使用している ワークショップ という静的ページがあります。そのスラッグは workshops です。テンプレートにはカスタムのget_posts関数があり、その中にループがあります。これにより、 workshops というカスタムコンテンツタイプの投稿がすべて表示されます。これらのワークショップのタイトルの1つをクリックすると、そのコンテンツの全内容に移動します。カスタム投稿タイプのパーマリンク構造はworkshops / postname に設定されているので、ユーザーが見ると、これらのコンテンツは実際にはすべて1つのコンテンツタイプである場合、Workshopsページの子になります。しかし、そのページとは無関係です。それは私がメニューで効果的に閉じる必要があるそのギャップです、タイプ 'workshop'の内容を閲覧するときに 'Workshops'メニュー項目をハイライトします。

繰り返しますが、それが理にかなっていることを願って、私は1つの段落で20回以上の「ワークショップ」を言ったと思います!

30
Gavin

もっと簡単な解決策があります。 WPには、参照しているカスタムタイプがそのページに関連していることを認識する方法がないため、各投稿タイプのページを作成しないでください。

代わりに、外観 - >メニューでカスタムリンクを作成してください。カスタムタイプを返すURLを入力してラベルを付けて、[メニューに追加]を押すだけです。

http://example.com/workshops/

またはあまりパーマリンクがない:

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

これだけで、そのカスタム投稿タイプのすべての投稿を表示するナビゲーションボタンが作成され、そのナビゲーションアイテムをクリックしたときにcurrent-menu-itemクラスも追加されます - ただし、ナビゲーションは追加されません。これ以外のURLのクラス

それからそれが作成されたら、その新しいアイテムの設定に入り、そして "Title Attribute"フィールドにカスタム投稿タイプのスラッグを入力します(あなたはdescriptionフィールドを使うこともできますが、それは管理画面オプションに隠されます)デフォルトで)。

さて、あなたはnav_menu_css_classフィルタ(各ナビゲーションアイテムに対して起動される)をフックし、表示されているコンテンツがあなたのカスタムナビゲーションアイテムに示された投稿タイプであるかどうかをチェックする必要があります:

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

この場合は、[Title Attribute]フィールドの内容が空ではないこと、およびそれらが現在クエリされているpost_typeと一致するかどうかを確認します。そうであれば、current-menu-itemクラスをそのクラス配列に追加してから、変更された配列を返します。

ナビゲーションアイテムのタイトルと単純に一致するようにこれを変更することができますが、何らかの理由で投稿タイプの単純なスラグとは異なる方法でナビゲーションアイテムにタイトルを付けたい場合は、Title属性またはDescriptionフィールドを使用します。

ナビゲーションメニュー項目に一致する投稿タイプの単一の項目(またはおそらくアーカイブリスト)を表示しているときはいつでも、その項目にはCSSクラスcurrent-menu-itemが与えられるので、強調表示は機能します。

ページやページテンプレートは必要ありません;-) URLクエリは正しい投稿を取得します。ループテンプレートはクエリ出力を表示します。この関数は、表示されている内容を認識してCSSクラスを追加します。

_ボーナス_

すべての投稿タイプに対してメニュー項目を自動的に生成することで、wp_update_nav_menu_itemを使用してプロセスを自動化することもできます。この例では、最初にこのアイテムを追加するナビゲーションメニューの$menu_idを取得しておく必要があります。

$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

使用する代わりに

$ post_type = get_query_var( 'post_type');

あなたが試してみたいかもしれません:

$ post_type = get_post_type();

時々投稿タイプはクエリvarに設定されません。これはデフォルトのpost_typeが "post"の場合です。そのため、リスティングページからリストされた投稿を強調表示したい場合はこれを使用する必要があります。 get_very_var()は、カスタムではない投稿タイプに対して空の文字列を返すだけです。

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 - それは幻想的です!私はあなたのコードを少し修正したので、それは特定の分類法(私は関連するpost_typeのためだけに使っています)のためにも働く。アイデアは、メニュー項目のTitle属性を使用して、post_typeの名前と分類の名前の両方をセミコロンで区切って格納し、その後関数によって展開することです。

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

私はページを使い続けて、ナビゲーションテンプレートのクラスとしてページテンプレート名を使うことにしました。これは私が私が他の解決策のいくつかについて好きではなかったtitle属性を雑然とさせるのを避けることを可能にします。

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

ボディクラスもheader.phpに追加しました

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

最後に、このソリューションはあなたのナビゲーションメニュー項目に選択された/アクティブな状態を適用するためにいくつかの追加のCSSを必要とします。このページの子として、ページに関連する分類アーカイブとカスタム投稿タイプを表示するために使用します。

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

あなたがwp_list_pagesを使用したい場合は、ここに私の解決策。

あなたの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;
}

Wp_optionsテーブルに option_name / page_for_custom_post_type-xxxx page_ID /を持つ page-ID uの新しい行を追加します。

おそらくあなたは、 page_for_posts と呼ばれるオプションがすでにあることを認識しました。カスタム投稿タイプが1つだけの場合は、ドロップダウンの/wp-admin/options-reading.phpでページを設定でき、ナビゲーションによってcurrent_pageが正しく設定されます。

私はwordpress coreが登録されたあらゆる投稿タイプのドロップダウンでこのセクションを拡張するべきであると思います。

2
Temo

@Somatic - 素晴らしいコード!私は自分自身を1つ変更しました。私はTitle Attributeを本来の目的のために残しておきたかったので、代わりに画面オプションで有効にできるLink Relationship(XFN)詳細メニュープロパティにCustom Post Typeスラッグを配置しました。修正しました

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

そしてそれを

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

素晴らしい作品Somatic。

残念ながら、私はあなたが説明したようにページにあなたのカスタム投稿タイプをリストすることができる方法を手に入れません。 page-portfolio.phpを使わずにそれをページに追加すると、404ページしか手に入りません。

私がGavinのようにするならば、私はこのようにブログページから "current_page_parent"も削除するようにあなたが少し機能を変更しました。

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