Tùy chỉnh Nav walker hiển thị mục menu hiện tại trẻ em hoặc anh chị em không có trẻ em


14

Tôi đã loay hoay / tìm kiếm trong nhiều giờ và vẫn không thể làm việc này, vì vậy cuối cùng tôi đã nhượng bộ và yêu cầu một số trợ giúp.

Tôi đang cố gắng viết một walker tùy chỉnh chỉ hiển thị các trang hiện tại của trẻ em hoặc nếu không có trẻ em hiển thị các anh chị em trang.

Ví dụ: lấy cây menu sau:

  • 1
    • 1.2.0
      • 1.3.0
      • 1.3.1
      • 1.3.2
    • 1.2.1
    • 1.2.2
  • 2.0

Giả sử rằng tôi đang ở trang hiện tại 1.2.0. Trên trang này tôi muốn hiển thị đó là trẻ em (1.3.0, 1.3.1, 1.3.2)

tuy nhiên, nếu tôi ở trang 1.2.2, vì nó không có con, nó sẽ hiển thị anh chị em cấp độ hiện tại của nó, vì vậy nó sẽ hiển thị cho tôi (1.2.0, 1.2.1, 1.2.2).


4
Vui lòng chuyển giải pháp của bạn đến một câu trả lời để nó rõ ràng hơn cho những người khác và các câu hỏi không ám ảnh trang web như chưa được trả lời.
Rarst

Những gì @Rarst nói! Tôi gần như đã bỏ lỡ rằng bạn sẽ đưa ra một giải pháp.
Chris Krycho

Necro trả lời. Tôi đã hỏi ít nhiều câu hỏi tương tự trên SO khoảng 2 năm trước với một câu trả lời rất hay. stackoverflow.com/questions/5826609/
trộm

Đã chuyển câu trả lời bên trong câu hỏi để trả lời riêng biệt. OP: Hãy theo dõi trên đó.
kaiser

Câu trả lời:


4

Đây là walker mà tôi đã sử dụng để chỉ hiển thị con của mục menu hiện tại. Hoặc các món trong thực đơn anh chị em nếu nó không có con riêng.

Có ý kiến ​​trong cả lớp giải thích từng phần

<?php

class SH_Child_Only_Walker extends Walker_Nav_Menu {

private $ID;
private $depth;
private $classes = array();
private $child_count = 0;
private $have_current = false;


// Don't start the top level
function start_lvl(&$output, $depth=0, $args=array()) {

    if( 0 == $depth || $this->depth != $depth )
        return;

    parent::start_lvl($output, $depth,$args);
}

// Don't end the top level
function end_lvl(&$output, $depth=0, $args=array()) {
    if( 0 == $depth || $this->depth != $depth )
        return;

    parent::end_lvl($output, $depth,$args);
}

// Don't print top-level elements
function start_el(&$output, $item, $depth=0, $args=array()) {

    $is_current = in_array('current-menu-item', $this->classes);

    if( 0 == $depth || ! $is_current )
        return;

    parent::start_el($output, $item, $depth, $args);
}

function end_el(&$output, $item, $depth=0, $args=array()) {
    if( 0 == $depth )
        return;

    parent::end_el($output, $item, $depth, $args);
}

// Only follow down one branch
function display_element( $element, &$children_elements, $max_depth, $depth=0, $args, &$output ) {

    // Check if element is in the current tree to display
    $current_element_markers = array( 'current-menu-item', 'current-menu-parent', 'current-menu-ancestor' );
    $this->classes = array_intersect( $current_element_markers, $element->classes );

    // If element has a 'current' class, it is an ancestor of the current element
    $ancestor_of_current = !empty($this->classes);

    // check if the element is the actual page element we are on.
    $is_current = in_array('current-menu-item', $this->classes);

    // if it is the current element
    if($is_current) {

        // set the count / ID / and depth to use in the other functions.
        $this->child_count = ( isset($children_elements[$element->ID]) ) ? count($children_elements[$element->ID]) : 0;
        $this->ID = $element->ID;
        $this->depth = $depth;
        $this->have_current = true;

        if($this->child_count > 0) {

            // if there are children loop through them and display the kids.
            foreach( $children_elements[$element->ID] as $child ) {
                parent::display_element( $child, $children_elements, $max_depth, $depth, $args, $output );
            }

        } else {
            // no children so loop through kids of parent item.
            foreach( $children_elements[$element->menu_item_parent] as $child ) {
                parent::display_element( $child, $children_elements, $max_depth, $depth, $args, $output );
            }

        }
    }

    // if depth is zero and not in current tree go to the next element
    if ( 0 == $depth && !$ancestor_of_current)
        return;

    // if we aren't on the current element proceed as normal
    if(! $this->have_current )
        parent::display_element( $element, $children_elements, $max_depth, $depth, $args, $output );
}
}

Đính kèm nó giống như bạn làm với bất kỳ máy đi bộ tùy chỉnh nào khác trên wp_nav_menu

<?php
wp_nav_menu( array(
    'menu' => 'primary-menu'
    ,'container' => 'nav'
    ,'container_class' => 'subpages'
    ,'depth' => 0
    ,'walker' => new SH_Child_Only_Walker()
 ));
?>

Tôi muốn chỉ ra bình luận của @ Stoosh chỉ ra ở đây. stackoverflow.com/questions/5826609/ trên vì đây là một giải pháp tốt khác
jchamb

0

Tôi đã có một kinh nghiệm tương tự. Bạn có thể muốn nghĩ về việc di chuyển logic các trang ra khỏi khung tập đi. Về cơ bản, biên dịch hệ thống phân cấp trang hiện tại như một đối tượng. Sau đó sử dụng tham số 'loại trừ' trong hàm wp_nav_menu. Bây giờ các trang bị loại sẽ phụ thuộc vào việc trang hiện tại có con hay không. Nếu không có con cho thấy anh em; nếu trẻ em && những đứa trẻ đó là kết thúc của dòng cho thấy anh em và trẻ em; nếu trẻ em && và cháu tồn tại loại trừ anh em và cho thấy con cháu.


excludeThông số này mà bạn giới thiệu là gì? Tôi đang xem tài liệu và không thấy bất kỳ tài liệu tham khảo nào.
Chris Krycho

1
Tôi xin lỗi tôi đã nhầm. Bạn đúng rằng không có tham số 'loại trừ'. Tôi có nghĩa là sử dụng chức năng "wp_list_pages".
Steve Fischer

Rất tốt, và không phải lo lắng. Tôi chỉ tò mò liệu có thứ gì đó không có giấy tờ hay không, nhưng ở phía sau, tôi đã thấy điều đó xảy ra trước đây. Cảm ơn đã xóa nó! Tôi đã không nghĩ đến việc sử dụng wp_list_pages()trong bối cảnh này, vì vậy đó là một ý tưởng thú vị.
Chris Krycho
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.