Menyoroti wp_nav_menu () Ancestor Class w / o Children in Nav Structure?

30

( Catatan Moderator: Awalnya berjudul "wp_nav_menu kelas Leluhur tanpa anak dalam struktur navigasi")

Saya memiliki wp_nav_menudi header saya yang memiliki tiga halaman di dalamnya. Ketika saya berada di salah satu halaman itu, halaman liyang berisi di menu mendapatkan kelas .current_page_item. Tiga halaman ini memiliki template, dan template ini berisi permintaan khusus untuk mendapatkan semua posting dari jenis konten tertentu. Akibatnya, "anak-anak" yang dirasakan dari halaman tingkat atas ini sebenarnya bukan anak-anak, mereka hanya tipe konten yang saya kaitkan dengan halaman tingkat atas itu menggunakan templat.

Saya ingin item menu tingkat atas untuk mendapatkan 'current-ancestor'kelas ketika pengguna menelusuri satu halaman dari jenis posting tertentu, sekali lagi, yang terkait dengan halaman itu hanya dalam kueri khusus dalam file template.

Harapan itu masuk akal - jika tidak, beri tahu saya di mana saya kehilangan Anda! Sangat menghargai bantuan apa pun.

--Edited untuk spesifik: Misalnya, saya memiliki halaman statis yang disebut Lokakarya yang menggunakan templat. Siputnya adalah bengkel . Templat memiliki fungsi get_posts khusus dan loop di dalamnya, yang menarik dan menampilkan semua posting dari jenis konten khusus yang disebut workshop . Jika saya mengklik salah satu judul bengkel ini, saya akan dibawa ke konten lengkap dari konten itu. Struktur permalink dari jenis posting khusus diatur ke bengkel / postname, jadi seperti yang dilihat pengguna, konten ini adalah anak-anak dari halaman Lokakarya, padahal sebenarnya mereka semua adalah satu jenis konten tetapi tidak terkait dengan halaman tersebut. Itulah celah yang harus saya tutup secara efektif di menu, menyoroti item menu 'Lokakarya' saat menelusuri konten bertipe 'lokakarya'.

Sekali lagi, harapan itu masuk akal, saya pikir saya mengatakan 'lokakarya' ke atas sebanyak 20 kali dalam satu paragraf!

Gavin
sumber
@ Gavin - Dapatkah Anda memasukkan beberapa hal spesifik yang ingin Anda capai. Lebih mudah untuk menulis jawaban secara konkret daripada jika kita mencoba melakukannya secara abstrak. Juga jika Anda dapat menjelaskan struktur URL Anda yang terkait dengan ini, akan sangat membantu.
MikeSchinkel
1
@ Gavin - Itu membantu. Jadi opsi menu tingkat atas Anda adalah daftar bengkel di "Lokakarya" dengan lintasan /workshops/dan ketika pengguna berada di halaman bengkel (yaitu /workshops/example-workshop/) Anda ingin item menu "Lokakarya" memiliki kelas yang current_page_itemditugaskan, benar?
MikeSchinkel
wp_nav_menu () mengekspos kelas menu-leluhur saat ini
Daniel Sachs

Jawaban:

29

Ada solusi yang lebih sederhana. Lupakan membuat halaman untuk setiap jenis posting agar Anda dapat memiliki item nav, karena seperti yang telah Anda pelajari, WP tidak memiliki cara untuk mengenali bahwa jenis kustom yang Anda jelajahi terkait dengan halaman itu.

Sebagai gantinya, buat tautan khusus di Appearance-> Menus. Cukup masukkan URL yang akan mengembalikan jenis kustom Anda dan beri label, lalu tekan "Tambahkan ke Menu".

http://example.com/workshops/

atau non-cantik-permalink:

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

ini saja akan membuat tombol nav yang menampilkan semua posting dengan jenis posting khusus itu, dan juga akan menambahkan kelas item menu saat ini ketika Anda mengklik item nav itu - tetapi itu belum menambahkan kelas nav pada sembarang URL selain yang ini

Kemudian, setelah dibuat, masuk ke konfigurasi untuk item baru itu, dan masukkan siput dari jenis posting kustom di bidang "Judul Atribut" (Anda juga bisa menggunakan bidang deskripsi, tetapi yang tersembunyi di opsi layar admin secara default).

Sekarang, Anda perlu menghubungkan nav_menu_css_classfilter (yang dipecat untuk setiap item nav) dan memeriksa apakah konten yang dilihat adalah jenis posting yang ditunjukkan dalam item nav kustom Anda:

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

Dalam hal ini, kita akan memeriksa bahwa isian judul Atribut Judul tidak kosong dan jika cocok dengan post_type saat ini yang ditanyai. Jika demikian, kami menambahkan kelas item menu saat ini ke array kelasnya, lalu mengembalikan array yang dimodifikasi.

Anda dapat memodifikasi ini untuk hanya mencocokkan judul item nav, tetapi jika karena alasan tertentu Anda ingin memberi judul item nav berbeda dari siput polos jenis posting, menggunakan bidang Judul Atribut atau Deskripsi memberi Anda fleksibilitas.

Sekarang setiap kali Anda melihat satu item (atau bahkan daftar arsip) dari jenis posting yang cocok dengan item menu nav, item tersebut akan diberi item-menu-item kelas CSS sehingga penyorotan Anda akan berfungsi.

Tidak perlu halaman atau templat halaman ;-) Permintaan URL menangani pengambilan posting yang tepat. Template lingkaran Anda berhati-hati menampilkan output permintaan. Fungsi ini menangani mengenali apa yang sedang ditampilkan dan menambahkan kelas CSS.

BONUS

Anda bahkan dapat mengotomatiskan proses menggunakan wp_update_nav_menu_item, dengan memiliki item menu yang dihasilkan secara otomatis untuk semua jenis posting Anda. Untuk contoh ini, Anda harus terlebih dahulu mengambil $menu_idmenu nav yang Anda inginkan.

$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'
        )
    );
}
somatik
sumber
Itu barangnya! Saya menggunakan templat halaman hanya karena tata letak agak rumit untuk halaman-halaman itu dan tidak hanya mencantumkan halaman-halamannya, namun saya masih dapat menggunakan filter yang Anda berikan untuk memeriksa ID halaman. Sifat dari tema ini adalah bahwa opsi tema membuat Anda mencocokkan halaman ('home' adalah halaman ini, 'about' adalah halaman ini, dll.), Sehingga harus bekerja dengan sempurna. Terima kasih atas bantuan (sangat rinci)!
Gavin
saya harus menghapus current_page_parentitem navigasi dari blog saya - tetapi jika tidak berhasil. thx
pkyeck
ini tidak berhasil untuk saya, karena $item->attr_titlemengeluarkan JUDUL, dan saya menulis judul dalam huruf kapital. jadi saya mengubah atribut $item->post_namedan sekarang berfungsi dengan baik untuk saya.
honk31
Saya mencoba membuat kode berfungsi untuk tema saya, tetapi tidak berhasil. Tidak akan ada kelas yang diterapkan pada item induk saya di menu, ketika saya pada jenis posting kustom portfolio. Saya telah menggunakan kode di atas. Apa yang bisa menjadi masalah?
Casper
4

alih-alih menggunakan

$ post_type = get_query_var ('post_type');

Anda mungkin ingin mencoba:

$ post_type = get_post_type ();

Karena kadang-kadang jenis posting tidak diatur dalam var permintaan. Ini adalah kasus untuk post_type default "post", jadi jika Anda ingin menyorot posting yang terdaftar dari halaman daftar, Anda harus menggunakan ini. get_very_var () baru saja mengembalikan string kosong untuk jenis posting yang tidak kustom.

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;
}
Eric
sumber
2

@Somatis - itu fantasic! Saya sedikit memodifikasi kode Anda sehingga juga berfungsi untuk Taksonomi tertentu (yang saya gunakan hanya untuk post_type terkait). Idenya adalah untuk menggunakan atribut Judul item menu untuk menyimpan baik nama post_type DAN nama taksonomi, dipisahkan oleh tanda titik koma, dan kemudian meledak oleh fungsi.

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;
}
tzeldin88
sumber
2

Di sini solusi saya jika Anda ingin bekerja dengan wp_list_pages.

tambahkan ini di functions.php Anda

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

Sekarang hanya menambahkan dalam tabel wp_options baris baru dengan OPTION_NAME dari page_for_custom_post_type-xxxx dan option_value' dengan halaman-ID u ingin menghubungkan.

Mungkin Anda mengenali bahwa sudah ada opsi bernama page_for_posts . Jika Anda hanya memiliki 1 jenis posting khusus, Anda dapat mengatur halaman Anda di /wp-admin/options-reading.php di dropdown dan navigasi akan mengatur current_page dengan benar.

Saya pikir inti wordpress harus memperpanjang bagian ini dengan dropdown untuk setiap jenis posting yang terdaftar.

Temo
sumber
2

Saya memutuskan untuk tetap menggunakan halaman dan menggunakan nama templat halaman sebagai kelas pada item nav. Ini memungkinkan saya untuk menghindari mengacaukan atribut judul yang saya tidak suka tentang beberapa solusi lain.

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

Saya juga memiliki kelas tubuh yang ditambahkan ke header.php

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

Akhirnya solusi ini membutuhkan beberapa css tambahan untuk menerapkan status yang dipilih / aktif ke item menu nav Anda. Saya menggunakannya untuk menampilkan arsip taksonomi dan jenis posting khusus yang terkait dengan halaman ini sebagai anak-anak dari halaman ini:

/* 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;}
Steve
sumber
Ini memberi saya kesalahan berikut: Warning: join() [function.join]: Invalid arguments passed in /home/path/to/wp-includes/nav-menu-template.php on line 76 Adakah yang tahu apa yang terjadi di sini?
Jeff K.
Oh, saya pikir saya melihat apa yang terjadi. Itu karena Anda mengembalikan $ kelas dalam pernyataan if. Cukup pindah ke return $classesluar dan setelah itu iftampaknya menyelesaikan kesalahan di atas.
Jeff K.
1

@Somatis - Kode hebat! Saya memang membuat satu perubahan sendiri. Saya ingin mempertahankan Judul Atribut untuk tujuan yang dimaksudkan, jadi alih-alih saya menempatkan siput Jenis Posting Khusus di properti menu lanjutan Hubungan Tautan (XFN) yang dapat Anda aktifkan di Opsi Layar. Saya dimodifikasi

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

dan mengubahnya menjadi

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

Kerja bagus Somatic.

Sayangnya, saya tidak mengerti bagaimana Anda bisa mendaftarkan jenis posting khusus Anda di halaman seperti yang Anda jelaskan. Jika saya tidak menggunakan halaman-portfolio.php dan menambahkannya ke halaman, yang saya dapatkan adalah halaman 404.

Jika saya menyukai Gavin, saya telah sedikit memodifikasi fungsi Anda untuk menghapus "current_page_parent" dari halaman blog seperti ini.

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;

}

Vayu
sumber