ไฮไลต์ wp_nav_menu () คลาสบรรพบุรุษที่ไม่มีเด็กในโครงสร้าง Nav หรือไม่?


30

( ผู้ดูแลหมายเหตุ:เดิมมีชื่อว่า "คลาสบรรพบุรุษของ wp_nav_menu ที่ไม่มีลูกในโครงสร้างการนำทาง")

ฉันมีwp_nav_menuในส่วนหัวของฉันซึ่งมีสามหน้าในนั้น เมื่อฉันที่หนึ่งของหน้าเว็บเหล่านั้นที่มีหน้าว่าในเมนูที่ได้รับในชั้นเรียนli .current_page_itemหน้าสามหน้านี้มีแม่แบบและแม่แบบเหล่านี้มีแบบสอบถามแบบกำหนดเองเพื่อรับโพสต์ทั้งหมดของเนื้อหาบางประเภท ผลที่ตามมาคือ"เด็ก ๆ " ที่รับรู้ของหน้าระดับบนสุดนี้ไม่ใช่เด็ก ๆ จริง ๆ พวกเขาเป็นเพียงประเภทเนื้อหาที่ฉันเชื่อมโยงกับหน้าระดับบนสุดนั้นโดยใช้เทมเพลต

ฉันต้องการรายการเมนูระดับบนสุดที่จะได้รับ'current-ancestor'คลาสเมื่อผู้ใช้เรียกดูหน้าเดียวของโพสต์ประเภทเฉพาะอีกครั้งเชื่อมโยงกับหน้านั้นเฉพาะในแบบสอบถามที่กำหนดเองในไฟล์เทมเพลต

หวังว่าจะสมเหตุสมผล - ถ้าไม่บอกให้ฉันรู้ว่าฉันทำคุณไปที่ไหน! ขอบคุณมากสำหรับความช่วยเหลือใด ๆ

- แก้ไขเฉพาะ: ตัวอย่างเช่นฉันมีหน้าสแตติกที่เรียกว่าเวิร์กช็อปที่ใช้เทมเพลต กระสุนของมันคือการประชุมเชิงปฏิบัติการ แม่แบบมีฟังก์ชั่ get_posts ที่กำหนดเองและห่วงอยู่ภายในซึ่งจะดึงและแสดงโพสต์ทั้งหมดของชนิดเนื้อหาที่กำหนดเองที่เรียกว่าการประชุมเชิงปฏิบัติการ ถ้าฉันคลิกที่หนึ่งในชื่อเวิร์กช็อปเหล่านี้ฉันจะถูกนำไปสู่เนื้อหาทั้งหมดของเนื้อหานั้น โครงสร้างความคิดเห็นของโพสต์ที่กำหนดเองชนิดมีการตั้งค่าการประชุมเชิงปฏิบัติการ / postnameดังนั้นตามที่ผู้ใช้เห็นเนื้อหาเหล่านี้เป็นลูกของหน้าการประชุมเชิงปฏิบัติการเมื่อในความเป็นจริงพวกเขาเป็นเนื้อหาประเภทเดียว แต่ไม่เกี่ยวข้องกับหน้า เป็นช่องว่างที่ฉันต้องปิดอย่างมีประสิทธิภาพในเมนูเน้นรายการเมนู 'การประชุมเชิงปฏิบัติการ' เมื่อเรียกดูเนื้อหาประเภท 'การประชุมเชิงปฏิบัติการ'

อีกครั้งหวังว่าเหมาะสมฉันคิดว่าฉันพูดว่า 'เวิร์กช็อป' ขึ้นไป 20 ครั้งในวรรคหนึ่ง!


@Gavin - คุณสามารถระบุสิ่งที่คุณพยายามจะทำสำเร็จ มันง่ายกว่าที่จะเขียนคำตอบในแง่ที่เป็นรูปธรรมมากกว่าถ้าเราพยายามทำมันในนามธรรม นอกจากนี้หากคุณสามารถอธิบายโครงสร้าง URL ของคุณเกี่ยวกับสิ่งเหล่านี้จะเป็นประโยชน์
MikeSchinkel

1
@ กาวิน - นั่นช่วย ตัวเลือกเมนูระดับบนสุดของคุณคือรายการเวิร์กช็อปที่"เวิร์กช็อป" ที่มีเส้นทาง/workshops/และเมื่อผู้ใช้อยู่ในเพจเวิร์กช็อป (เช่น/workshops/example-workshop/) คุณต้องการให้รายการเมนู"เวิร์กช็อป"current_page_itemกำหนดคลาสให้ถูกต้องหรือไม่
MikeSchinkel

wp_nav_menu () เปิดเผยคลาสเมนูปัจจุบัน - บรรพบุรุษ
Daniel Sachs

คำตอบ:


29

มีทางออกที่ง่ายกว่า ลืมการสร้างหน้าสำหรับโพสต์แต่ละประเภทเพียงเพื่อให้คุณมีรายการ nav เพราะตามที่คุณได้เรียนรู้ WP ไม่มีวิธีการรับรู้ว่าประเภทกำหนดเองที่คุณกำลังเรียกดูเกี่ยวข้องกับหน้านั้น

สร้างลิงก์ที่กำหนดเองในลักษณะที่ปรากฏ -> เมนูแทน เพียงใส่ URL ที่จะคืนประเภทที่กำหนดเองของคุณและให้ป้ายกำกับจากนั้นกด "เพิ่มไปที่เมนู"

http://example.com/workshops/

หรือไม่สวย Permalinks:

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

สิ่งนี้เพียงอย่างเดียวจะสร้างปุ่ม nav ที่แสดงโพสต์ทั้งหมดด้วยโพสต์ที่กำหนดเองประเภทนั้นและจะเพิ่มคลาสไอเท็มเมนูปัจจุบันเมื่อคุณคลิกไอเท็ม nav นั้น - แต่มันจะยังไม่เพิ่มคลาส 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 ปัจจุบันที่ถูกสอบถาม ถ้าเป็นเช่นนั้นเราจะเพิ่มคลาสรายการเมนูปัจจุบันไปยังคลาสอาเรย์ของมันแล้วส่งกลับอาร์เรย์ที่ปรับเปลี่ยน

คุณสามารถแก้ไขสิ่งนี้ให้ตรงกับชื่อเรื่องของรายการ nav แต่ถ้าด้วยเหตุผลบางอย่างที่คุณต้องการตั้งชื่อรายการ nav แตกต่างจากกระสุนธรรมดาของประเภทโพสต์โดยใช้ฟิลด์ชื่อแอตทริบิวต์หรือคำอธิบายให้ความยืดหยุ่นนั้น

ตอนนี้เมื่อใดก็ตามที่คุณกำลังดูรายการเดียว (หรืออาจเป็นรายการที่เก็บถาวร) ของชนิดโพสต์ที่ตรงกับรายการเมนู nav รายการนั้นจะได้รับ CSS เมนูปัจจุบันรายการเมนูเพื่อเน้นการทำงานของคุณ

ไม่จำเป็นต้องมีหน้าหรือเทมเพลทของหน้า ;-) การสืบค้น 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'
        )
    );
}

นั่นคือสิ่งที่! ฉันใช้เทมเพลตหน้าเท่านั้นเนื่องจากเลย์เอาต์ค่อนข้างซับซ้อนสำหรับหน้าเหล่านั้นและไม่เพียง แต่แสดงรายการหน้าเว็บออก แต่ฉันยังสามารถใช้ตัวกรองที่คุณให้เพื่อตรวจสอบ ID หน้าได้ ลักษณะของชุดรูปแบบนี้คือตัวเลือกชุดรูปแบบช่วยให้คุณจับคู่หน้าต่างๆ ('หน้าแรก' คือหน้านี้ 'เกี่ยวกับ' เป็นหน้านี้เป็นต้น) เพื่อให้ทำงานได้อย่างสมบูรณ์ ขอบคุณสำหรับความช่วยเหลือ (มีรายละเอียดเหลือเชื่อ)!
กาวิน

ฉันต้องลบออกcurrent_page_parentจากรายการการนำทางที่เป็นบล็อกของฉัน - แต่อย่างอื่นก็ใช้งานได้ ขอบคุณ
pkyeck

สิ่งนี้ไม่ได้ผลสำหรับฉันตั้งแต่$item->attr_titleดึง TITLE ออกมาและฉันเขียนชื่อเป็นอักษรตัวใหญ่ ดังนั้นฉันจึงเปลี่ยนคุณลักษณะเป็น$item->post_nameและตอนนี้มันทำงานได้ดีสำหรับฉัน
honk31

ฉันพยายามทำให้โค้ดใช้งานได้กับธีม แต่ไม่สามารถใช้งานได้ portfolioมีระดับจะไม่นำไปใช้กับรายการสินค้าหลักของฉันในเมนูเมื่อฉันในโพสต์ที่กำหนดเองชนิด ฉันได้ใช้รหัสด้านบน มีปัญหาอะไรบ้าง?
Casper

4

แทนการใช้

$ post_type = get_query_var ('post_type');

คุณอาจต้องการลอง:

$ post_type = get_post_type ();

เนื่องจากบางครั้งชนิดโพสต์ไม่ได้ตั้งค่าในแบบสอบถาม var นี่เป็นกรณีของ post_type เริ่มต้นของ "โพสต์" ดังนั้นหากคุณต้องการเน้นโพสต์ที่ระบุไว้จากหน้ารายการคุณจะต้องใช้สิ่งนี้ 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

@ โซมาติก - นั่นเป็นเรื่องเพ้อฝัน! ฉันปรับเปลี่ยนรหัสของคุณเล็กน้อยดังนั้นจึงสามารถใช้งานกับ Taxonomy ที่เฉพาะเจาะจง (ซึ่งฉันใช้เฉพาะกับ post_type ที่เกี่ยวข้องเท่านั้น) แนวคิดคือการใช้แอททริบิวต์ Title ของรายการเมนูเพื่อเก็บทั้งชื่อ post_type และชื่อของ taxonomy คั่นด้วยเซมิโคลอนจากนั้นขยายโดยฟังก์ชัน

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

เพิ่มสิ่งนี้ในฟังก์ชั่นของคุณ

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และoption_valueด้วยpage-ID ที่คุณต้องการเชื่อมต่อ

บางทีคุณอาจจำได้ว่ามีตัวเลือกชื่อpage_for_postsอยู่แล้ว หากคุณมีประเภทโพสต์ที่กำหนดเองเพียง 1 ตัวคุณสามารถตั้งค่าหน้าเว็บของคุณที่ /wp-admin/options-reading.php ในดรอปดาวน์และการนำทางจะตั้งค่า current_page อย่างถูกต้อง

ฉันคิดว่าเวิร์ดเพรสคอร์ควรขยายส่วนนี้ด้วยการเลื่อนลงสำหรับโพสต์ทุกประเภทที่ลงทะเบียน


2

ฉันตัดสินใจที่จะใช้เพจและใช้ชื่อเทมเพลตของเพจเป็นคลาสในรายการ nav สิ่งนี้ทำให้ฉันสามารถหลีกเลี่ยงความยุ่งเหยิงของแอตทริบิวต์หัวเรื่องที่ฉันไม่ชอบเกี่ยวกับโซลูชันอื่น ๆ

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 ความคิดอะไรที่เกิดขึ้นที่นี่
Jeff K.

โอ้ฉันคิดว่าฉันเห็นสิ่งที่เกิดขึ้น เป็นเพราะคุณส่งคืนคลาส $ ภายในคำสั่ง if เพียงแค่ย้ายreturn $classesออกไปข้างนอกและหลังจากนั้นifดูเหมือนว่าจะแก้ไขข้อผิดพลาดข้างต้น
Jeff K.

1

@Somatic - รหัสที่ยอดเยี่ยม! ฉันทำการเปลี่ยนแปลงตัวเอง ฉันต้องการเก็บแอตทริบิวต์ของชื่อตามวัตถุประสงค์ที่ต้องการดังนั้นฉันจึงวางทับชนิดโพสต์ที่กำหนดเองในคุณสมบัติเมนูขั้นสูงของ Link Relationship (XFN) ที่คุณสามารถเปิดใช้งานในตัวเลือกหน้าจอ ฉันแก้ไข

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

และเปลี่ยนเป็น

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

0

การทำงานที่ดีโซมาติก

น่าเสียดายที่ฉันไม่เข้าใจวิธีที่คุณสามารถระบุประเภทโพสต์ที่คุณกำหนดเองในหน้าเว็บในแบบที่คุณอธิบาย ถ้าฉันไม่ใช้ page-portfolio.php และเพิ่มไปยังหน้าสิ่งที่ฉันได้รับคือ 404 หน้า

ถ้าฉันชอบกาวินทำฉันปรับเปลี่ยนให้คุณทำหน้าที่เล็กน้อยเพื่อลบ "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.