生成子菜单:查看子菜单时显示父类别/页面的子菜单

时间:2013-04-25 作者:AndrettiMilas

我想要一个子菜单,其中用户访问页面、帖子或类别(在本例中为“信息”),然后显示子类别/页面列表。不是下拉菜单,而是仅当用户已在父类别中时才显示的菜单。

我需要一个代码,即使在子页面、帖子或类别上,也可以继续显示父级的子级。也许有一种方法可以做到这一点与WP菜单,我不知道?

代码需要与主菜单分开,并分配传统的CSS类,这些类指示用户是否在当前页面上。代码还需要自动识别父级的子级,而不是在整个站点中分配子级并调用多个菜单。我确信这是可能的,因为我曾经使用过这样的代码。然而,我不记得那是什么代码了!

下面是此类菜单的示例:Classic menu example

2 个回复
最合适的回答,由SO网友:bosco 整理而成

有趣的是,几个月前我遇到了同样的难题。。。

我发现Wordpress对菜单项应用了各种CSS类以区分当前项及其祖先,但却完全忽略了子菜单及其与当前项的关系,这很奇怪。我想要一个.current-sub CSS类,以便我可以隐藏所有内容.sub-menus除外.current-subs

理论经过大量的研究和深入研究,我最终采用的解决方案是the Walker_Nav_Menu class 并在两个不同的点修改其行为,以获得我的想象.current-sub CSS类:

处理菜单项时(请参见Walker_Nav_Menu->start_el() ), 检查Wordpress分配给菜单项的类,以确定它是否对应于当前页面或是menu ancestor 当前页的Walker_Nav_Menu->start_lvl() ), 如果先前处理的菜单项是当前菜单项或其祖先,请将新类应用于子菜单元素,以便将其区分为当前子菜单

Aside

请注意,我鼓起了勇气menu ancestor 在上面在我的情况下,事实证明我实际上并不关心帖子、页面或类别的层次结构或彼此之间的关系(即,B页是否是a页的子页无关紧要)。我唯一需要担心的是它们对应的层次结构menu-items。

在Walker实现之后,我只需要在模板文件中重新调用wp_nav_menu() 以我的新菜单行者的一个实例作为参数。

为了方便和简洁,我在一个过程式插件中提供了我的实现。大部分代码与本机代码相同Walker_Nav_Menu - 我的评论表示我的补充。

//Register a new theme location for a custom menu
function after_setup_theme_97226() {
    register_nav_menu( \'menu-97226\', \'Primary Navigation (uses Menu_Walker_97226)\' );
}
add_action( \'after_setup_theme\', \'after_setup_theme_97226\' );

//Queue up CSS modifications
function enqueue_styles_97226() {
    wp_enqueue_style( \'style-97226\', plugins_url(\'style.css\', __FILE__) );
}
add_action( \'wp_enqueue_scripts\', \'enqueue_styles_97226\' );

//Now walk it out.
class Menu_Walker_97226 extends Walker_Nav_Menu {
    const CURRENT_SUBMENU_CLASS = \'current-sub\';    //The CSS class to apply to the active submenu
    var $is_current_submenu     = FALSE;            //Whether or not the next sub-menu to be processed is related to the current-menu-item.

    function start_lvl( &$output, $depth = 0, $args = array() ) {
        $indent = ( $depth ) ? str_repeat( "\\t", $depth ) : \'\';

        //If we\'ve begun processing an "active" submenu, add a class to indicate as much.
        $current_sub_class = ( $this->is_current_submenu ) ? Menu_Walker_97226::CURRENT_SUBMENU_CLASS : \'\';

        //Add the new sub-menu ul element to the markup. Always give sub-menus the standard Wordpress "sub-menu" class.
        $output .= "\\n$indent<ul class=\\"sub-menu $current_sub_class\\">\\n";

        //We\'ve now processed the sub-menu; reset the flag
        $this->is_current_submenu = FALSE;
    }

    function start_el( &$output, $item, $depth = 0, $args = array() ) {
        //Reset the flag such that "active" menu-items without sub-menus don\'t pass their "current" status on to the sub-menus of their siblings
        $this->is_current_submenu = FALSE;

        $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, $args ) );
        $class_names = $class_names ? \' class="\' . esc_attr( $class_names ) . \'"\' : \'\';

            //Check to see if this element is "current" or a menu ancestor of "current" so that the "current" status may be passed on to any immediate sub-menu of the item.
            //You should add or remove conditions here in order to fit your application.
            //Also see "Final Notes" section below regarding performance
        if (strpos($class_names, \'current-menu-item\')
            || strpos($class_names, \'current-menu-parent\')
            || strpos($class_names, \'current-menu-ancestor\')
            || strpos($class_names, \'current_page_parent\'))
            $this->is_current_submenu = TRUE;

        $id = apply_filters( \'nav_menu_item_id\', \'menu-item-\'. $item->ID, $item, $args );
        $id = $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 );
    }
}
引用的style.css 文件如下:

ul.sub-menu {
    display:none;
}
ul.current-sub {
    display:block;
}
最后,致电wp_nav_menu() 在要显示菜单以使用新Walker的模板文件中(有关其他参数,请参阅文档):

wp_nav_menu( array(
    \'theme_location\' => \'menu-97226\',
    \'walker\' => new Menu_Walker_97226()
) );
我还没有运行基准测试,但使用in_array()$classes 数组已联接,而不是使用strpos() 事后致电。也可以使用array_flip() 并随后使用isset( $classes[ $class_name ] ), 虽然我怀疑翻转会破坏使用isset().should 将显示。。。我的术语有点模糊,目前我的头脑混乱——我会稍后再回来整理;)

SO网友:tfrommen

我正在我的一个网站上使用以下代码:

    if ( // Maybe you want different conditionals?
        (is_page() && ! is_front_page())
        || is_category()
    ) {
        $id = get_the_ID();
        $ancestors = get_ancestors($id, \'page\');
        if (! empty($ancestors)) $id = $ancestors[count($ancestors)-1];
        $subpages = wp_list_pages(\'title_li=&child_of=\'.$id.\'&depth=1&echo=0\');
        if (\'\' !== $subpages) {
            echo \'<nav id="subpages" role="navigation">\'.PHP_EOL
                .\'<ul>\'.PHP_EOL
                .$subpages
                .\'</ul>\'.PHP_EOL
                .\'</nav><!-- #subpages -->\'.PHP_EOL;
        }
    }
请尝试此功能并检查您想要的功能。如果它不能(准确地)满足您的要求,请告诉我,我将尝试更新代码。

结束

相关推荐

Custom menus not showing

作为我上一次关于菜单的未解决查询的后续,这个问题已经进一步扩展。我的菜单没有打印代码中的任何地方。我正在注册菜单功能。php:add_action( \'after_setup_theme\', \'your_newtheme_setup\' ); if ( ! function_exists( \'your_newtheme_setup\' ) ) : function your_newtheme_setup() { if (