Hiển thị một phần / nhánh của cây menu bằng wp_nav_menu ()


109

Tôi có một menu được định nghĩa trong WP Admin trông như thế này:

văn bản thay thế

Tôi muốn có thể hiển thị tất cả các liên kết con trên thanh bên bất cứ khi nào tôi ở trang mẹ. Ví dụ: nếu người dùng ở trang "Giới thiệu" của tôi, tôi muốn một danh sách gồm 4 liên kết được tô sáng màu xanh lá cây sẽ xuất hiện trên thanh bên.

Tôi đã xem tài liệu về wp_nav_menu () và dường như không có cách dựng sẵn nào để chỉ định một nút cụ thể của menu đã cho để sử dụng làm điểm bắt đầu khi tạo liên kết.

Tôi đã tạo ra một giải pháp cho một tình huống tương tự dựa trên các mối quan hệ được tạo bởi cha mẹ trang, nhưng tôi đang tìm kiếm một giải pháp sử dụng hệ thống menu cụ thể. Bất kỳ trợ giúp sẽ được đánh giá cao.


2
Vì vậy, bạn muốn duy trì toàn bộ menu dưới dạng một menu tùy chỉnh, nhưng tạo một walker tùy chỉnh hiển thị nó chỉ mở rộng các cây con đang hoạt động? Thích mã này , nhưng mở rộng wp_nav_menu thay vì wp_list_pages? Gần đây tôi đã làm một cái gì đó tương tự và có thể đăng mã nếu đó là những gì bạn đang tìm kiếm ...
Goldenapples

1
@goldenapples, đó chính xác là những gì tôi đang theo đuổi. Nếu bạn không nhớ đăng mã của bạn như một câu trả lời, tôi sẽ rất biết ơn.
jessegavin

1
Tôi tự hỏi rằng một chức năng hữu ích rõ ràng như vậy chưa được xây dựng. Điều đó nói chung rất hữu ích cho bất kỳ trang web nào "CMS".
hakre

Tôi đang cố gắng giải quyết vấn đề trên hoặc một cái gì đó tương tự. Để thay thế, tôi đã đưa ra một giải pháp CSS tại đây: stackoverflow.com/q/7640837/518169
hyperjack

Câu trả lời:


75

Điều này vẫn còn trong tâm trí của tôi vì vậy tôi đã xem lại nó và kết hợp giải pháp này, nó không dựa vào bối cảnh nhiều như vậy:

add_filter( 'wp_nav_menu_objects', 'submenu_limit', 10, 2 );

function submenu_limit( $items, $args ) {

    if ( empty( $args->submenu ) ) {
        return $items;
    }

    $ids       = wp_filter_object_list( $items, array( 'title' => $args->submenu ), 'and', 'ID' );
    $parent_id = array_pop( $ids );
    $children  = submenu_get_children_ids( $parent_id, $items );

    foreach ( $items as $key => $item ) {

        if ( ! in_array( $item->ID, $children ) ) {
            unset( $items[$key] );
        }
    }

    return $items;
}

function submenu_get_children_ids( $id, $items ) {

    $ids = wp_filter_object_list( $items, array( 'menu_item_parent' => $id ), 'and', 'ID' );

    foreach ( $ids as $id ) {

        $ids = array_merge( $ids, submenu_get_children_ids( $id, $items ) );
    }

    return $ids;
}

Sử dụng

$args = array(
    'theme_location' => 'slug-of-the-menu', // the one used on register_nav_menus
    'submenu' => 'About Us', // could be used __() for translations
);

wp_nav_menu( $args );

Kỹ thuật đáng yêu! Tôi có thể hỏi điều gì đó có thể liên quan đến cái này không: Làm thế nào bạn sẽ hiển thị nội dung của các trang menu con được liệt kê trong mẫu?
daniel.tosaba

2
@ daniel.tosaba bạn sẽ cần phải phân lớp hoặc sử dụng các bộ lọc trong Walker_Nav_Menulớp. Giống như tất cả các công cụ thực đơn quá nhiều cho bình luận - đặt câu hỏi mới về nó?
Hết


3
Thật là một câu trả lời tuyệt vời. Cảm ơn bạn rất nhiều. Đây thực sự nên là một tùy chọn mặc định trong WordPress.
chấm

3
Thực sự gọn gàng. Nếu bất cứ ai quan tâm, để làm điều tương tự nhưng theo ID trang, hãy đổi wp_filter_object_listdòng thànhwp_filter_object_list( $items, array( 'object_id' => $args->submenu ), 'and', 'ID' );
Ben

14

@goldenapples: Lớp Walker của bạn không hoạt động. Nhưng ý tưởng là thực sự tốt. Tôi đã tạo ra một walker dựa trên ý tưởng của bạn:

class Selective_Walker extends Walker_Nav_Menu
{
    function walk( $elements, $max_depth) {

        $args = array_slice(func_get_args(), 2);
        $output = '';

        if ($max_depth < -1) //invalid parameter
            return $output;

        if (empty($elements)) //nothing to walk
            return $output;

        $id_field = $this->db_fields['id'];
        $parent_field = $this->db_fields['parent'];

        // flat display
        if ( -1 == $max_depth ) {
            $empty_array = array();
            foreach ( $elements as $e )
                $this->display_element( $e, $empty_array, 1, 0, $args, $output );
            return $output;
        }

        /*
         * need to display in hierarchical order
         * separate elements into two buckets: top level and children elements
         * children_elements is two dimensional array, eg.
         * children_elements[10][] contains all sub-elements whose parent is 10.
         */
        $top_level_elements = array();
        $children_elements  = array();
        foreach ( $elements as $e) {
            if ( 0 == $e->$parent_field )
                $top_level_elements[] = $e;
            else
                $children_elements[ $e->$parent_field ][] = $e;
        }

        /*
         * when none of the elements is top level
         * assume the first one must be root of the sub elements
         */
        if ( empty($top_level_elements) ) {

            $first = array_slice( $elements, 0, 1 );
            $root = $first[0];

            $top_level_elements = array();
            $children_elements  = array();
            foreach ( $elements as $e) {
                if ( $root->$parent_field == $e->$parent_field )
                    $top_level_elements[] = $e;
                else
                    $children_elements[ $e->$parent_field ][] = $e;
            }
        }

        $current_element_markers = array( 'current-menu-item', 'current-menu-parent', 'current-menu-ancestor' );  //added by continent7
        foreach ( $top_level_elements as $e ){  //changed by continent7
            // descend only on current tree
            $descend_test = array_intersect( $current_element_markers, $e->classes );
            if ( !empty( $descend_test ) ) 
                $this->display_element( $e, $children_elements, 2, 0, $args, $output );
        }

        /*
         * if we are displaying all levels, and remaining children_elements is not empty,
         * then we got orphans, which should be displayed regardless
         */
         /* removed by continent7
        if ( ( $max_depth == 0 ) && count( $children_elements ) > 0 ) {
            $empty_array = array();
            foreach ( $children_elements as $orphans )
                foreach( $orphans as $op )
                    $this->display_element( $op, $empty_array, 1, 0, $args, $output );
         }
        */
         return $output;
    }
}

Bây giờ bạn có thể sử dụng:

<?php wp_nav_menu( 
   array(
       'theme_location'=>'test', 
       'walker'=>new Selective_Walker() ) 
   ); ?>

Đầu ra là một danh sách chứa phần tử gốc hiện tại và đó là con (không phải con của chúng). Def: Phần tử gốc: = Mục menu cấp cao nhất tương ứng với trang hiện tại hoặc là cha mẹ của trang hiện tại hoặc cha mẹ của cha mẹ ...

Điều này không trả lời chính xác câu hỏi ban đầu nhưng hầu như, vì vẫn còn mục cấp cao nhất. Điều này tốt cho tôi, vì tôi muốn yếu tố cấp cao nhất làm tiêu đề của thanh bên. Nếu bạn muốn loại bỏ điều này, bạn có thể phải ghi đè display_element hoặc sử dụng Trình phân tích cú pháp HTML.


12

Xin chào @jessegavin :

Menu Nav được lưu trữ trong sự kết hợp của các loại bài tùy chỉnh và phân loại tùy chỉnh. Mỗi menu được lưu trữ dưới dạng Thuật ngữ (nghĩa là "Giới thiệu về Menu" , được tìm thấy trong wp_terms) Phân loại tùy chỉnh (nghĩa là nav_menuđược tìm thấy trong wp_term_taxonomy.)

Mỗi Mục menu Nav được lưu trữ dưới dạng một bài đăng post_type=='nav_menu_item'(ví dụ : "Giới thiệu về công ty" , được tìm thấy wp_posts) với các thuộc tính được lưu dưới dạng meta bài đăng (in wp_postmeta) bằng cách sử dụng meta_keytiền tố trong _menu_item_*đó _menu_item_menu_item_parentlà ID của bài đăng mục menu Menu Nav của mục menu của bạn.

Mối quan hệ giữa các menu và các mục menu được lưu trữ trong wp_term_relationshipsđó object_idliên quan đến $post->IDMục Menu Nav và $term_relationships->term_taxonomy_idliên quan đến menu được định nghĩa chung trong wp_term_taxonomywp_terms.

Tôi chắc chắn rằng nó sẽ có thể treo cả hai 'wp_update_nav_menu''wp_update_nav_menu_item'để tạo các menu thực tế trong wp_termsvà một bộ song song của các mối quan hệ trong wp_term_taxonomywp_term_relationshipsnơi mỗi Nav Menu Item có mục menu phụ Nav cũng trở nên riêng của nó Nav Menu.

Bạn cũng muốn nối 'wp_get_nav_menus' (mà tôi đã đề xuất được thêm vào WP 3.0 dựa trên một số công việc tương tự tôi đã làm cách đây vài tháng) để đảm bảo rằng Menu Nav được tạo của bạn không được hiển thị để thao tác bởi người dùng trong quản trị viên, nếu không họ Sẽ không đồng bộ thực sự nhanh và sau đó bạn sẽ gặp ác mộng dữ liệu trong tay.

Nghe có vẻ là một dự án thú vị và hữu ích, nhưng nó có nhiều mã và thử nghiệm hơn một chút so với khả năng tôi có thể giải quyết ngay bây giờ một phần bởi vì bất kỳ thứ gì đồng bộ hóa dữ liệu đều có xu hướng là một PITA khi nói đến việc loại bỏ tất cả các lỗi (và bởi vì khách hàng trả tiền đang thúc ép tôi hoàn thành công việc. :) Nhưng trang bị thông tin trên Tôi khá là một nhà phát triển plugin WordPress có động lực có thể mã hóa nó nếu họ muốn.

Tất nhiên bây giờ bạn nhận ra nếu bạn viết mã, bạn bắt buộc phải đăng lại ở đây để tất cả chúng ta có thể hưởng lợi từ quy mô lớn của bạn! :-)


Tôi không chắc chắn rằng tôi đang làm theo những gì bạn đang nói. Tôi đang tìm kiếm một giải pháp chỉ đọc để hiển thị "menu phụ" liên quan đến trang hiện tại mà người dùng đang ở. Chúng ta đang nói về những điều tương tự? - Tôi đánh giá cao sự giải thích sâu hơn của bạn về lược đồ cơ sở dữ liệu mặc dù.
jessegavin

@jessegavin - Có, nếu bạn muốn gọi wp_nav_menu()thì bạn sẽ cần sao chép các menu vì wp_nav_menu()được kết hợp chặt chẽ với cấu trúc menu . Tùy chọn khác là sao chép wp_nav_menu()mã và thực hiện các sửa đổi cần thiết để hiển thị dưới dạng menu con.
MikeSchinkel

10

Đây là một tiện ích mở rộng dành cho người đi bộ nên làm những gì bạn đang tìm kiếm:

class Selective_Walker extends Walker_Nav_Menu
{

    function walk( $elements, $max_depth) {

        $args = array_slice(func_get_args(), 2);
        $output = '';

        if ($max_depth < -1) //invalid parameter
            return $output;

        if (empty($elements)) //nothing to walk
            return $output;

        $id_field = $this->db_fields['id'];
        $parent_field = $this->db_fields['parent'];

        // flat display
        if ( -1 == $max_depth ) {
            $empty_array = array();
            foreach ( $elements as $e )
                $this->display_element( $e, $empty_array, 1, 0, $args, $output );
            return $output;
        }

        /*
         * need to display in hierarchical order
         * separate elements into two buckets: top level and children elements
         * children_elements is two dimensional array, eg.
         * children_elements[10][] contains all sub-elements whose parent is 10.
         */
        $top_level_elements = array();
        $children_elements  = array();
        foreach ( $elements as $e) {
            if ( 0 == $e->$parent_field )
                $top_level_elements[] = $e;
            else
                $children_elements[ $e->$parent_field ][] = $e;
        }

        /*
         * when none of the elements is top level
         * assume the first one must be root of the sub elements
         */
        if ( empty($top_level_elements) ) {

            $first = array_slice( $elements, 0, 1 );
            $root = $first[0];

            $top_level_elements = array();
            $children_elements  = array();
            foreach ( $elements as $e) {
                if ( $root->$parent_field == $e->$parent_field )
                    $top_level_elements[] = $e;
                else
                    $children_elements[ $e->$parent_field ][] = $e;
            }
        }

        $current_element_markers = array( 'current-menu-item', 'current-menu-parent', 'current-menu-ancestor' );

        foreach ( $top_level_elements as $e ) {

            // descend only on current tree
            $descend_test = array_intersect( $current_element_markers, $e->classes );
            if ( empty( $descend_test ) )  unset ( $children_elements );

            $this->display_element( $e, $children_elements, $max_depth, 0, $args, $output );
        }

        /*
         * if we are displaying all levels, and remaining children_elements is not empty,
         * then we got orphans, which should be displayed regardless
         */
        if ( ( $max_depth == 0 ) && count( $children_elements ) > 0 ) {
            $empty_array = array();
            foreach ( $children_elements as $orphans )
                foreach( $orphans as $op )
                    $this->display_element( $op, $empty_array, 1, 0, $args, $output );
         }

         return $output;
    }

}

Dựa vào mã lỏng lẻo của mfields tôi đã tham chiếu trong nhận xét của mình trước đó. Tất cả những gì nó làm là kiểm tra khi đi bộ menu để xem liệu phần tử hiện tại là (1) mục menu hiện tại hay (2) tổ tiên của mục menu hiện tại và chỉ mở rộng cây con bên dưới nó nếu một trong những điều kiện đó là đúng . Hy vọng điều này làm việc cho bạn.

Để sử dụng nó, chỉ cần thêm một đối số "walker" khi bạn gọi menu, tức là:

<?php wp_nav_menu( 
   array(
       'theme_location'=>'test', 
       'walker'=>new Selective_Walker() ) 
   ); ?>

Ồ ... tôi vừa đọc lại câu hỏi của bạn và nhận ra rằng tôi đã hiểu nhầm nó lúc đầu. Walker này sẽ hiển thị tất cả các mục menu cấp cao nhất khác, chỉ cần không mở rộng chúng. Đây không phải là chính xác những gì bạn đã muốn làm. Tuy nhiên, mã này có thể được sửa đổi theo bất kỳ cách nào bạn muốn. Chỉ cần nhìn vào vòng lặp $top_level_elementsvà thêm bài kiểm tra của riêng bạn trước khi gọi đến $this->display_element.
Goldenapples

Có thể có được lớp này để hiển thị độ sâu của trang con hiện tại? Đó là .. Nếu tôi có độ sâu từ ba cấp trở lên, thì cấp thứ ba và cấp tiếp theo được hiển thị cho trang (phụ) hiện tại? Hiện tại, nó chỉ hiển thị A> B chứ không hiển thị> C (C là cấp ba (cấp độ)
Zolomon

@Zolomon - Tôi không chắc là tôi hiểu câu hỏi của bạn. Điều này sẽ mở rộng toàn bộ cây dưới bất kỳ mục menu nào với các lớp 'menu-menu-item', 'current-menu-Parent' hoặc 'current-menu-aneopor'. Khi tôi kiểm tra nó, nó sẽ hiển thị tất cả các cấp độ của trang con trong menu. Bạn đang muốn làm gì?
Goldenapples

Có lẽ bạn muốn truyền depththam số cho cuộc gọi đến wp_nav_menu, trong trường hợp chủ đề của bạn bằng cách nào đó vượt quá mặc định là 0 (hiển thị tất cả các cấp)?
Goldenapples

8

Cập nhật: Tôi đã thực hiện điều này thành một plugin. Tải về tại đây .


Tôi cần phải tự giải quyết vấn đề này và cuối cùng đã viết ra một bộ lọc về kết quả tra cứu menu. Nó cho phép bạn sử dụng wp_nav_menunhư bình thường, nhưng chọn một phần phụ của menu dựa trên tiêu đề của phần tử cha. Thêm một submenutham số vào menu như vậy:

wp_nav_menu(array(
  'menu' => 'header',
  'submenu' => 'About Us',
));

Bạn thậm chí có thể đi sâu một vài cấp bằng cách đặt dấu gạch chéo vào:

wp_nav_menu(array(
  'menu' => 'header',
  'submenu' => 'About Us/Board of Directors'
));

Hoặc nếu bạn thích với một mảng:

wp_nav_menu(array(
  'menu' => 'header',
  'submenu' => array('About Us', 'Board of Directors')
));

Nó sử dụng một phiên bản sên của tiêu đề, làm cho nó tha thứ cho những thứ như chữ hoa và dấu chấm câu.


Có thể đạt được menu con thông qua id? Ý tôi là id trang, hoặc id bài.
Digerkam

split () không được dùng nữa, thay thế $loc = split( "/", $loc );trong plugin bằng$loc = preg_split( "~/~", $loc );
Floris

Tôi cũng sẽ đề nghị làm $ submenu tùy chọn. Vì vậy, bạn vẫn có thể lấy toàn bộ menu khi cần. Thêm phần này vào bộ lọc lên trên cùng: `if (! [Et ($ args-> submenu)) {return $ items; } `
Floris

8

Tôi tập hợp các lớp sau đây cho bản thân mình. Nó sẽ tìm thấy cha mẹ điều hướng hàng đầu của trang hiện tại hoặc bạn có thể cung cấp cho nó một ID điều hướng hàng đầu mục tiêu trong hàm tạo của walker.

class Walker_SubNav_Menu extends Walker_Nav_Menu {
    var $target_id = false;

    function __construct($target_id = false) {
        $this->target_id = $target_id;
    }

    function walk($items, $depth) {
        $args = array_slice(func_get_args(), 2);
        $args = $args[0];
        $parent_field = $this->db_fields['parent'];
        $target_id = $this->target_id;
        $filtered_items = array();

        // if the parent is not set, set it based on the post
        if (!$target_id) {
            global $post;
            foreach ($items as $item) {
                if ($item->object_id == $post->ID) {
                    $target_id = $item->ID;
                }
            }
        }

        // if there isn't a parent, do a regular menu
        if (!$target_id) return parent::walk($items, $depth, $args);

        // get the top nav item
        $target_id = $this->top_level_id($items, $target_id);

        // only include items under the parent
        foreach ($items as $item) {
            if (!$item->$parent_field) continue;

            $item_id = $this->top_level_id($items, $item->ID);

            if ($item_id == $target_id) {
                $filtered_items[] = $item;
            }
        }

        return parent::walk($filtered_items, $depth, $args);
    }

    // gets the top level ID for an item ID
    function top_level_id($items, $item_id) {
        $parent_field = $this->db_fields['parent'];

        $parents = array();
        foreach ($items as $item) {
            if ($item->$parent_field) {
                $parents[$item->ID] = $item->$parent_field;
            }
        }

        // find the top level item
        while (array_key_exists($item_id, $parents)) {
            $item_id = $parents[$item_id];
        }

        return $item_id;
    }
}

Cuộc gọi hải quân:

wp_nav_menu(array(
    'theme_location' => 'main_menu',
    'walker' => new Walker_SubNav_Menu(22), // with ID
));

4

@davidn @hakre Xin chào, tôi có một giải pháp xấu mà không cần Trình phân tích cú pháp HTML hoặc ghi đè display_element.

 class Selective_Walker extends Walker_Nav_Menu
    {
        function walk( $elements, $max_depth) {

            $args = array_slice(func_get_args(), 2);
            $output = '';

            if ($max_depth < -1) //invalid parameter
                return $output;

            if (empty($elements)) //nothing to walk
                return $output;

            $id_field = $this->db_fields['id'];
            $parent_field = $this->db_fields['parent'];

            // flat display
            if ( -1 == $max_depth ) {
                $empty_array = array();
                foreach ( $elements as $e )
                    $this->display_element( $e, $empty_array, 1, 0, $args, $output );
                return $output;
            }

            /*
             * need to display in hierarchical order
             * separate elements into two buckets: top level and children elements
             * children_elements is two dimensional array, eg.
             * children_elements[10][] contains all sub-elements whose parent is 10.
             */
            $top_level_elements = array();
            $children_elements  = array();
            foreach ( $elements as $e) {
                if ( 0 == $e->$parent_field )
                    $top_level_elements[] = $e;
                else
                    $children_elements[ $e->$parent_field ][] = $e;
            }

            /*
             * when none of the elements is top level
             * assume the first one must be root of the sub elements
             */
            if ( empty($top_level_elements) ) {

                $first = array_slice( $elements, 0, 1 );
                $root = $first[0];

                $top_level_elements = array();
                $children_elements  = array();
                foreach ( $elements as $e) {
                    if ( $root->$parent_field == $e->$parent_field )
                        $top_level_elements[] = $e;
                    else
                        $children_elements[ $e->$parent_field ][] = $e;
                }
            }

            $current_element_markers = array( 'current-menu-item', 'current-menu-parent', 'current-menu-ancestor' );  //added by continent7
            foreach ( $top_level_elements as $e ){  //changed by continent7
                // descend only on current tree
                $descend_test = array_intersect( $current_element_markers, $e->classes );
                if ( !empty( $descend_test ) ) 
                    $this->display_element( $e, $children_elements, 2, 0, $args, $output );
            }

            /*
             * if we are displaying all levels, and remaining children_elements is not empty,
             * then we got orphans, which should be displayed regardless
             */
             /* removed by continent7
            if ( ( $max_depth == 0 ) && count( $children_elements ) > 0 ) {
                $empty_array = array();
                foreach ( $children_elements as $orphans )
                    foreach( $orphans as $op )
                        $this->display_element( $op, $empty_array, 1, 0, $args, $output );
             }
            */

/*added by alpguneysel  */
                $pos = strpos($output, '<a');
            $pos2 = strpos($output, 'a>');
            $topper= substr($output, 0, $pos).substr($output, $pos2+2);
            $pos3 = strpos($topper, '>');
            $lasst=substr($topper, $pos3+1);
            $submenu= substr($lasst, 0, -6);

        return $submenu;
        }
    }

Sau khi thử tất cả, giải pháp của Alp là giải pháp duy nhất phù hợp với tôi. Tuy nhiên một vấn đề với nó. Nó chỉ hiển thị cho trẻ em cấp một, nhưng không hiển thị trẻ em cấp ba hoặc cấp bốn. Tôi đã cố gắng trong nhiều ngày để có được nó để làm như vậy. Bất cứ ai biết làm thế nào để sửa đổi giải pháp của mình như vậy? Tái bút Nó sẽ không cho phép tôi thêm ý kiến ​​vì vậy cần phải làm điều đó như một câu trả lời.
cchiera

3

Đầu ra của menu điều hướng bao gồm rất nhiều lớp cho mục hiện tại, tổ tiên của mục hiện tại, v.v. chỉ trẻ em của trang hiện tại, vv


3

Tôi đã thực hiện một walker sửa đổi sẽ giúp! Không hoàn hảo - nó để lại một vài yếu tố trống rỗng, nhưng nó thực hiện các mẹo. Việc sửa đổi về cơ bản là các bit $ current_branch. Hy vọng nó sẽ giúp được ai đó!

class Kanec_Walker_Nav_Menu extends Walker {
/**
 * @see Walker::$tree_type
 * @since 3.0.0
 * @var string
 */
var $tree_type = array( 'post_type', 'taxonomy', 'custom' );

/**
 * @see Walker::$db_fields
 * @since 3.0.0
 * @todo Decouple this.
 * @var array
 */
var $db_fields = array( 'parent' => 'menu_item_parent', 'id' => 'db_id' );

/**
 * @see Walker::start_lvl()
 * @since 3.0.0
 *
 * @param string $output Passed by reference. Used to append additional content.
 * @param int $depth Depth of page. Used for padding.
 */
function start_lvl(&$output, $depth) {
    $indent = str_repeat("\t", $depth);
    $output .= "\n$indent<ul class=\"sub-menu\">\n";
}

/**
 * @see Walker::end_lvl()
 * @since 3.0.0
 *
 * @param string $output Passed by reference. Used to append additional content.
 * @param int $depth Depth of page. Used for padding.
 */
function end_lvl(&$output, $depth) {
    global $current_branch;
    if ($depth == 0) $current_branch = false;
    $indent = str_repeat("\t", $depth);
    $output .= "$indent</ul>\n";
}

/**
 * @see Walker::start_el()
 * @since 3.0.0
 *
 * @param string $output Passed by reference. Used to append additional content.
 * @param object $item Menu item data object.
 * @param int $depth Depth of menu item. Used for padding.
 * @param int $current_page Menu item ID.
 * @param object $args
 */
function start_el(&$output, $item, $depth, $args) {
    global $wp_query;
    global $current_branch;

    // Is this menu item in the current branch?
    if(in_array('current-menu-ancestor',$item->classes) ||
    in_array('current-menu-parent',$item->classes) ||
    in_array('current-menu-item',$item->classes)) {
        $current_branch = true; 
    }

    if($current_branch && $depth > 0) {
        $indent = ( $depth ) ? str_repeat( "\t", $depth ) : '';

        $class_names = $value = '';

        $classes = empty( $item->classes ) ? array() : (array) $item->classes;
        $classes[] = 'menu-item-' . $item->ID;

        $class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item ) );
        $class_names = ' class="' . esc_attr( $class_names ) . '"';

        $id = apply_filters( 'nav_menu_item_id', 'menu-item-'. $item->ID, $item, $args );
        $id = strlen( $id ) ? ' id="' . esc_attr( $id ) . '"' : '';

        $output .= $indent . '<li' . $id . $value . $class_names .'>';

        $attributes  = ! empty( $item->attr_title ) ? ' title="'  . esc_attr( $item->attr_title ) .'"' : '';
        $attributes .= ! empty( $item->target )     ? ' target="' . esc_attr( $item->target     ) .'"' : '';
        $attributes .= ! empty( $item->xfn )        ? ' rel="'    . esc_attr( $item->xfn        ) .'"' : '';
        $attributes .= ! empty( $item->url )        ? ' href="'   . esc_attr( $item->url        ) .'"' : '';

        $item_output = $args->before;
        $item_output .= '<a'. $attributes .'>';
        $item_output .= $args->link_before . apply_filters( 'the_title', $item->title, $item->ID ) . $args->link_after;
        $item_output .= '</a>';
        $item_output .= $args->after;

        $output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
    }

}

/**
 * @see Walker::end_el()
 * @since 3.0.0
 *
 * @param string $output Passed by reference. Used to append additional content.
 * @param object $item Page data object. Not used.
 * @param int $depth Depth of page. Not Used.
 */
function end_el(&$output, $item, $depth) {
    global $current_branch;
    if($current_branch && $depth > 0) $output .= "</li>\n";
    if($depth == 0) $current_branch = 0;
}

}


3

Kiểm tra mã trong plugin của tôi hoặc sử dụng nó cho mục đích của bạn;)

Plugin này thêm tiện ích "Menu điều hướng" nâng cao. Nó cung cấp nhiều tùy chọn có thể được đặt để tùy chỉnh đầu ra của menu tùy chỉnh thông qua widget.

Các tính năng bao gồm:

  • Phân cấp tùy chỉnh - "Chỉ các mục phụ liên quan" hoặc "Chỉ các mục phụ liên quan nghiêm ngặt".
  • Độ sâu bắt đầu và mức tối đa để hiển thị + màn hình phẳng.
  • Hiển thị tất cả các mục menu bắt đầu với một mục đã chọn.
  • Chỉ hiển thị đường dẫn trực tiếp đến phần tử hiện tại hoặc chỉ con của
    mục đã chọn (tùy chọn để bao gồm mục cha).
  • Lớp tùy chỉnh cho một khối widget.
  • Và hầu như tất cả các tham số cho hàm wp_nav_menu.

http://wordpress.org/extend/plugins/advified-menu-widget/

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.