Written by me@grafxflow
06 Aug, 2013
0
3,033
I recently had a problem relating to the main menu with a WordPress site which used the e-shop plugin. The main navigation menu had three buttons - 'Contact Us', 'Useful Links' and 'Shop'. I wanted the 'Shop' button to stay highlighted even when the user selected a Shop Category or Shop Tag.
Here is the scenario:
I have a shop with sells several cloths items. The categories would be 't-shirts' and 'shorts'. The tags would be the 'brands', 'colours' and 'sizes'. When choosing the 'Shop' button it takes me to a landing page which shows the top 10 items. Now when choosing a Shop Category it takes me to a page listing all the items for that category. If I then choose a Shop Tag it shows a page listing all the products that use that tag. So how did I make the Shop button stay highlighted all the time?
Well I had to extend the WordPress built in class/functions Walker_Nav_Menu. In order to do this I first added the following to my themes (Appearance->Editor) functions.php file, which replaces WordPress's default menu output.
class example_walker extends Walker_Nav_Menu
{
function start_el(&$output, $item, $depth, $args)
{
global $wp_query;
$indent = ( $depth ) ? str_repeat( "\t", $depth ) : '';
$class_names = $value = '';
$classes = empty( $item->classes ) ? array() : (array) $item->classes;
$class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item ) );
$class_names = ' class="'. esc_attr( $class_names ).'"';
$output .= $indent . '<li id="menu-item-'. $item->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 ) .'"' : '';
$prepend = '<strong>';
$append = '</strong>';
$description = ! empty( $item->description ) ? '<span>'.esc_attr( $item->description ).'</span>' : '';
if($depth != 0)
{
$description = $append = $prepend = "";
}
$item_output = $args->before;
$item_output .= '<a'. $attributes .'>';
$item_output .= $args->link_before .$prepend.apply_filters( 'the_title', $item->title, $item->ID ).$append;
$item_output .= $description.$args->link_after;
$item_output .= '</a>';
$item_output .= $args->after;
$output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
}
}
Then in my themes header.php (Appearance->Editor) file I add the new menu class.
<?php
wp_nav_menu( array(
'theme_location' => 'primary',
'container' =>false,
'menu_class' => 'nav-menu',
'echo' => true,
'before' => '',
'after' => '',
'link_before' => '',
'link_after' => '',
'depth' => 0,
'walker' => new example_walker())
);
?>
In order to sort the issue I amended the extended 'Walker_Nav_Menu' as below.
class example_walker extends Walker_Nav_Menu
{
function start_el(&$output, $item, $depth, $args)
{
global $wp_query;
$indent = ( $depth ) ? str_repeat( "\t", $depth ) : '';
$class_names = $value = '';
$classes = empty( $item->classes ) ? array() : (array) $item->classes;
$class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item ) );
$class_names = ' class="'. esc_attr( $class_names );
if (is_tag() && $item->ID == '35' || is_category() && $item->ID == '35' || is_single() && $item->ID == '35' || is_search() && $item->ID == '35')
{
$class_names .= ' current-menu-item ';
}
$class_names .= '"';
$output .= $indent . '<li id="menu-item-'. $item->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 ) .'"' : '';
$prepend = '<strong>';
$append = '</strong>';
$description = ! empty( $item->description ) ? '<span>'.esc_attr( $item->description ).'</span>' : '';
if($depth != 0)
{
$description = $append = $prepend = "";
}
$item_output = $args->before;
$item_output .= '<a'. $attributes .'>';
$item_output .= $args->link_before .$prepend.apply_filters( 'the_title', $item->title, $item->ID ).$append;
$item_output .= $description.$args->link_after;
$item_output .= '</a>';
$item_output .= $args->after;
$output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
}
}
The part that changed was this...
$class_names = ' class="'. esc_attr( $class_names ).'"';
... to this.
$class_names = ' class="'. esc_attr( $class_names );
if (is_tag() && $item->ID == '35' || is_category() && $item->ID == '35' || is_single() && $item->ID == '35' || is_search() && $item->ID == '35')
{
$class_names .= ' current-menu-item ';
}
$class_names .= '"';
What it's doing is looping through each of the navigation menu items as it outputs them to see if the current one is the 'Shop' button ($item->ID == '35'), but also at the same time is checking to see if:
And then adding the WordPress default css 'current-menu-item' class to the 'Shop' menu item to make it stay highlighted. I found the $item->ID number by viewing the html source code of the menu. It contained something like this.
id="menu-item-(ID_NUMBER)"
17 Mar, 2008
30 Apr, 2017
05 Sep, 2012
I am a Full-stack Developer who also started delving into the world of UX/UI Design a few years back. I blog and tweet to hopefully share a little bit of knowledge that can help others around the web. Thanks for stopping by!
Follow11 Jul, 2023
21 Jun, 2023
Views: 166,095
Views: 40,208
Views: 36,920
Views: 33,515