Làm nổi bật wp_nav_menu () Lớp tổ tiên w / o Trẻ em trong cấu trúc Nav?


30

( Người điều hành lưu ý: Ban đầu có tiêu đề "lớp tổ tiên wp_nav_menu không có trẻ em trong cấu trúc điều hướng")

Tôi có một wp_nav_menutrong phần đầu của tôi trong đó có ba trang trong đó. Khi tôi ở một trong những trang đó, trang lichứa trong menu đó sẽ nhận được lớp .current_page_item. Ba trang này có các mẫu và các mẫu này chứa các truy vấn tùy chỉnh để có được tất cả các bài đăng của một loại nội dung nhất định. Trên thực tế, "trẻ em" được nhận thức của trang cấp cao nhất này thực tế không phải là trẻ em, chúng chỉ là một loại nội dung mà tôi đã liên kết với trang cấp cao nhất đó bằng cách sử dụng một mẫu.

Tôi muốn các mục trình đơn cấp cao nhất để có được một 'current-ancestor'lớp khi người dùng đang duyệt một trang của một loại bài đăng cụ thể, một lần nữa, được liên kết với trang đó trong một truy vấn tùy chỉnh trong tệp mẫu.

Hy vọng điều đó có ý nghĩa - nếu không, hãy cho tôi biết tôi mất bạn ở đâu! Rất đánh giá cao bất kỳ sự giúp đỡ.

- Chỉnh sửa cho các chi tiết cụ thể: Ví dụ: tôi có một trang tĩnh có tên là Hội thảo đang sử dụng một mẫu. Sên của nó là xưởng . Mẫu có chức năng get_posts tùy chỉnh và vòng lặp bên trong nó, nó kéo và hiển thị tất cả các bài đăng của một loại nội dung tùy chỉnh được gọi là hội thảo . Nếu tôi nhấp vào một trong những tiêu đề của các hội thảo này, tôi sẽ được đưa đến toàn bộ nội dung của phần nội dung đó. Cấu trúc permalink của bài tùy thuộc vào thiết lập để các hội thảo / postname, vì vậy, khi người dùng nhìn thấy nó, những phần nội dung này là con của trang Hội thảo, trong thực tế, tất cả chúng đều thuộc một loại nội dung nhưng không liên quan đến trang. Đó là khoảng trống mà tôi cần phải đóng một cách hiệu quả trong menu, làm nổi bật mục menu 'Hội thảo' khi duyệt nội dung của loại 'hội thảo'.

Một lần nữa, hy vọng điều đó có ý nghĩa, tôi nghĩ rằng tôi đã nói 'hội thảo' lên tới 20 lần trong một đoạn!


@Gavin - Bạn có thể bao gồm một vài chi tiết cụ thể hơn về những gì bạn đang cố gắng thực hiện. Thật dễ dàng để viết một câu trả lời bằng các thuật ngữ cụ thể hơn là nếu chúng ta cố gắng thực hiện nó trong bản tóm tắt. Ngoài ra nếu bạn có thể giải thích cấu trúc URL của mình liên quan đến những cấu trúc này thì nó sẽ hữu ích.
MikeSchinkel

1
@Gavin - Điều đó giúp. Vì vậy, tùy chọn menu cấp cao nhất của bạn là danh sách các hội thảo tại "Hội thảo" với đường dẫn /workshops/và khi người dùng ở trang hội thảo (tức là /workshops/example-workshop/) bạn muốn mục trình đơn "Hội thảo"current_page_item được phân công lớp , đúng không?
MikeSchinkel

wp_nav_menu () trưng bày lớp hiện tại-menu-tổ tiên
Daniel Sachs

Câu trả lời:


29

Có một giải pháp đơn giản hơn. Quên việc tạo các trang cho từng loại bài đăng để bạn có thể có các mục điều hướng, vì như bạn đã học, WP không có cách nào để nhận ra rằng các loại tùy chỉnh bạn đang duyệt có liên quan đến trang đó.

Thay vào đó, hãy tạo một liên kết tùy chỉnh trong Giao diện-> Menu. Chỉ cần đặt URL sẽ trả về loại tùy chỉnh của bạn và đặt cho nó một nhãn, sau đó nhấn "Thêm vào Menu".

http://example.com/workshops/

hoặc không đẹp-permalinks:

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

điều này một mình sẽ chỉ tạo một nút điều hướng hiển thị tất cả các bài đăng với loại bài đăng tùy chỉnh đó và cũng sẽ thêm lớp mục trình đơn hiện tại khi bạn nhấp vào mục điều hướng đó - nhưng nó sẽ không thêm lớp điều hướng vào bất kỳ URL khác với URL này

Sau đó, khi được tạo, hãy đi vào cấu hình cho mục mới đó và nhập sên của loại bài đăng tùy chỉnh trong trường "Thuộc tính tiêu đề" (bạn cũng có thể sử dụng trường mô tả, nhưng mục đó được ẩn trong các tùy chọn màn hình quản trị viên theo mặc định).

Bây giờ, bạn cần nối nav_menu_css_classbộ lọc (được kích hoạt cho từng mục điều hướng) và kiểm tra xem nội dung đang xem có thuộc loại bài đăng được chỉ định trong mục điều hướng tùy chỉnh của bạn không:

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

Trong trường hợp này, chúng tôi sẽ kiểm tra xem nội dung của trường Thuộc tính Tiêu đề không trống và liệu chúng có khớp với post_type hiện tại đang được truy vấn không. Nếu vậy, chúng ta thêm lớp mục trình đơn hiện tại vào mảng lớp của nó, sau đó trả về mảng đã sửa đổi.

Bạn có thể sửa đổi điều này để đơn giản phù hợp với tiêu đề của mục điều hướng, nhưng nếu vì lý do nào đó bạn muốn đặt tiêu đề cho mục điều hướng khác với sên đơn giản của loại bài đăng, sử dụng trường Thuộc tính Tiêu đề hoặc Mô tả cho phép bạn linh hoạt.

Bây giờ bất cứ khi nào bạn đang xem một mục duy nhất (hoặc thậm chí có thể lưu trữ danh sách) của loại bài đăng phù hợp với mục trình đơn điều hướng, mục đó sẽ được cung cấp mục trình đơn hiện tại của lớp CSS để tính năng tô sáng của bạn sẽ hoạt động.

Không có trang hoặc mẫu trang nào cần thiết ;-) Truy vấn URL đảm nhiệm việc tìm nạp đúng bài đăng. Mẫu vòng lặp của bạn đảm nhiệm việc hiển thị đầu ra truy vấn. Hàm này đảm nhận việc nhận ra những gì đang được hiển thị và thêm lớp CSS.

THƯỞNG

Bạn thậm chí có thể tự động hóa quá trình bằng cách sử dụng wp_update_nav_menu_itemcác mục menu được tạo tự động cho tất cả các loại bài đăng của bạn. Trong ví dụ này, trước tiên bạn cần phải lấy $menu_idmenu điều hướng mà bạn muốn các mục này được thêm vào.

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

Đó là các công cụ! Tôi chỉ sử dụng các mẫu trang vì bố cục khá phức tạp đối với các trang đó và không chỉ liệt kê các trang đó, tuy nhiên tôi vẫn có thể sử dụng bộ lọc mà bạn cung cấp để kiểm tra ID trang. Bản chất của chủ đề này là các tùy chọn chủ đề giúp bạn khớp các trang ('home' là trang này, 'about' là trang này, v.v.), do đó, nó sẽ hoạt động hoàn hảo. Cảm ơn bạn đã hỗ trợ (cực kỳ chi tiết)!
Gavin

tôi đã phải xóa current_page_parentmục điều hướng là blog của mình - nhưng nếu không thì nó đã hoạt động. thx
pkyeck

điều này không hiệu quả với tôi, vì $item->attr_titleđã rút ra TITLE và tôi đã viết tiêu đề bằng chữ in hoa. Vì vậy, tôi đã thay đổi thuộc tính $item->post_namevà bây giờ nó hoạt động tốt với tôi.
honk31

Tôi đã cố gắng làm cho mã hoạt động cho chủ đề của mình, nhưng không thể làm cho nó hoạt động được. Sẽ không có lớp áp dụng cho mục cha mẹ của tôi trong menu, khi tôi ở loại bài đăng tùy chỉnh portfolio. Tôi đã sử dụng mã trên. Những gì có thể là vấn đề?
Casper

4

thay vì sử dụng

$ post_type = get_query_var ('post_type');

Bạn có thể muốn thử:

$ post_type = get_post_type ();

Vì đôi khi loại bài đăng không được đặt trong truy vấn var. Đây là trường hợp cho post_type mặc định của "bài đăng", vì vậy nếu bạn muốn làm nổi bật một bài đăng được liệt kê từ trang danh sách, bạn sẽ cần sử dụng bài này. get_very_var () chỉ trả về một chuỗi rỗng cho các loại bài đăng không tùy chỉnh.

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 - đó là tưởng tượng! Tôi đã sửa đổi mã của bạn một chút để nó cũng hoạt động cho Phân loại cụ thể (mà tôi chỉ sử dụng cho post_type có liên quan). Ý tưởng là sử dụng thuộc tính Title của mục menu để lưu trữ cả tên của post_type VÀ tên của phân loại, được phân tách bằng dấu chấm phẩy và sau đó phát nổ bởi hàm.

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

Đây là giải pháp của tôi nếu bạn muốn làm việc với wp_list_pages.

thêm cái này vào hàm của bạn

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

Bây giờ chỉ cần thêm vào bảng wp_options một hàng mới với một OPTION_NAME của page_for_custom_post_type-xxxxoption_value với trang-ID u muốn kết nối.

Có lẽ bạn đã nhận ra rằng đã có một tùy chọn được gọi là page_for_posts . Nếu bạn chỉ có 1 loại bài đăng tùy chỉnh, bạn có thể đặt trang của mình tại /wp-admin/options-reading.php trong danh sách thả xuống và điều hướng sẽ đặt chính xác current_page.

Tôi nghĩ rằng lõi wordpress nên mở rộng phần này với một danh sách thả xuống cho mỗi loại bài đăng ký.


2

Tôi quyết định gắn bó với các trang và sử dụng tên mẫu trang làm một lớp trên mục điều hướng. Điều này cho phép tôi tránh làm lộn xộn thuộc tính tiêu đề mà tôi không thích về một số giải pháp khác.

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

Tôi cũng có các lớp cơ thể được thêm vào header.php

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

Cuối cùng, giải pháp này yêu cầu một số css bổ sung để áp dụng trạng thái đã chọn / hoạt động cho các mục menu điều hướng của bạn. Tôi sử dụng nó để hiển thị tài liệu lưu trữ phân loại và các loại bài đăng tùy chỉnh liên quan đến trang như là con của trang này:

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

Điều này đã cho tôi lỗi sau: Warning: join() [function.join]: Invalid arguments passed in /home/path/to/wp-includes/nav-menu-template.php on line 76 Bất kỳ ý tưởng những gì đã xảy ra ở đây?
Jeff K.

Oh tôi nghĩ rằng tôi thấy những gì đang xảy ra. Đó là bởi vì bạn đang trả về các lớp $ trong câu lệnh if. Đơn giản chỉ cần di chuyển ra return $classesngoài và sau đó ifdường như để giải quyết lỗi trên.
Jeff K.

1

@Somatic - Mã tuyệt vời! Tôi đã làm một thay đổi bản thân mình. Tôi muốn giữ Thuộc tính Tiêu đề cho mục đích đã định, vì vậy thay vào đó tôi đã đặt sên Loại bài đăng tùy chỉnh trong thuộc tính trình đơn nâng cao Mối quan hệ liên kết (XFN) mà bạn có thể bật trong Tùy chọn màn hình. Tôi đã sửa đổi

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

và đổi nó thành

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

0

Làm tốt lắm Somatic.

Thật không may, tôi không hiểu làm thế nào bạn có thể liệt kê các loại bài đăng tùy chỉnh của bạn trong một trang theo cách bạn giải thích. Nếu tôi không sử dụng page-portfolio.php và thêm nó vào một trang, tất cả những gì tôi nhận được là trang 404.

Nếu tôi làm như Gavin, tôi đã sửa đổi chức năng của bạn một chút để cũng xóa "current_page_parent" khỏi trang blog như thế này.

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;

}

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.