wp_nav_menu()Nav構造の子のない祖先クラスを強調表示しますか?


30

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

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

'current-ancestor'ユーザーがテンプレートファイルのカスタムクエリでのみそのページに関連付けられている特定の投稿タイプの単一のページを閲覧しているときに、トップレベルのメニュー項目にクラスを取得してほしい。

それが理にかなっていることを願っています-そうでない場合は、私があなたを失った場所を教えてください!どんな助けにも感謝します。

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

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


@Gavin-あなたが達成しようとしていることのいくつかの詳細を含めることができます。答えを具体的な用語で書くほうが、抽象的に答えようとするよりも簡単です。 また、これらに関連するURL構造を説明できると便利です。
MikeSchinkel

1
@Gavin-それが役立ちます。あなたのトップレベルのメニューオプションようにワークショップのリストである「ワークショップ」のパスと/workshops/、ユーザーがワークショップのページ上にある場合(つまり/workshops/example-workshop/)したい「ワークショップ」メニュー項目がクラスをしているためにcurrent_page_item割り当てられ、正しいですか?
MikeSchinkel

wp_nav_menu()はcurrent-menu-ancestorクラスを公開します
ダニエルサックス

回答:


29

より簡単な解決策があります。学習したように、WPは閲覧しているカスタムタイプがそのページに関連していることを認識する方法がないため、各投稿タイプのページを作成するのを忘れてください。

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

http://example.com/workshops/

または非かなりパーマリンク:

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

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

次に、作成したら、その新しいアイテムの構成に移動し、[タイトル属性]フィールドにカスタム投稿タイプのスラッグを入力します(説明フィールドも使用できますが、管理画面オプションでは非表示になります)デフォルトで)。

今、あなたはフックする必要があります nav_menu_css_classフィルター(各navアイテムに対して起動される)表示されているコンテンツがカスタムnavアイテムで示されている投稿タイプであるかどうかを確認する必要があります。

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

この場合、タイトル属性フィールドの内容が空ではなく、それらが現在照会されているpost_typeと一致するかどうかを確認します。その場合、current-menu-itemクラスをそのクラス配列に追加し、変更された配列を返します。

これを単純にnavアイテムのタイトルに一致するように変更することもできますが、何らかの理由でnavアイテムに投稿タイプのプレーンスラッグとは異なるタイトルを付けたい場合、Title AttributeまたはDescriptionフィールドを使用すると柔軟性が得られます。

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

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

ボーナス

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

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

それはものです!ページテンプレートを使用しているのは、それらのページのレイアウトがかなり複雑で、ページを一覧表示するだけではないためですが、提供されたフィルターを引き続き使用してページIDを確認できます。このテーマの性質は、テーマオプションを使用してページを一致させることです(「ホーム」はこのページ、「アバウト」はこのページなど)。(非常に詳細な)支援をありがとう!
ギャビン

current_page_parentブログであるナビゲーションアイテムからを削除する必要がありましたが、それ以外は機能しました。thx
pkyeck

$item->attr_titleTITLEを引き出して以来、これは私にとってはうまくいきませんでした。タイトルを大文字で書きました。そのため、属性をに変更しましたが$item->post_name、今ではうまく機能します。
-honk31

私は自分のテーマに合わせてコードを機能させようとしましたが、機能しません。カスタム投稿タイプを使用している場合、メニューの親アイテムに適用されるクラスはありませんportfolio。上記のコードを使用しました。何が問題になりますか?
キャスパー14年

4

使用する代わりに

$ post_type = get_query_var( 'post_type');

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

$ post_type = get_post_type();

ときどき、クエリの種類に投稿タイプが設定されていません。これは、デフォルトの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;
}

2

@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

ここで、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_NAMEpage_for_custom_post_type-XXXXoption_valueページ-ID uが接続したいです。

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

wordpressコアは、登録されたすべての投稿タイプのドロップダウンでこのセクションを拡張する必要があると思います。


2

私はページにこだわって、ページテンプレート名をナビゲーションアイテムのクラスとして使用することにしました。これにより、他のソリューションのいくつかで気に入らなかった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;}

これは私に次のエラーを与えました: Warning: join() [function.join]: Invalid arguments passed in /home/path/to/wp-includes/nav-menu-template.php on line 76 ここで何が起こったのか考えていますか?
ジェフK.11年

ああ、私は何が起こっているのかわかります。これは、ifステートメント内で$ classesを返すためです。return $classes外に移動するだけで、その後ifは上記のエラーを解決するようです。
ジェフK.

1

@Somatic-すばらしいコード!私は自分で1つの変更を加えました。タイトル属性を意図した目的のために保持したかったので、代わりに、リンクオプション(XFN)の詳細メニュープロパティにカスタム投稿タイプのスラッグを配置しました。これは、画面オプションで有効にできます。変更した

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

に変更しました

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

0

素敵な仕事ソマティック。

残念ながら、あなたが説明した方法でカスタム投稿タイプをページにリストする方法はわかりません。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;

}

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.