I have a HTML structure and I want to change those menu elements for a WordPress Menu maintaining the class and id's, and I want to change these elements for the ones I obtain using wp_get_nav_menu_items() and for each, but don't know how.
The thing is changing all Categories for parent and subitem WP menu category and so on, until 5 level of depth that has the menu. For example, replace Devices with first item depth 0, inside change Mobile Phones for second level, and go changing.
<!-- mp-menu -->
<nav id="mp-menu" class="mp-menu mp-overlap">
<div class="mp-level mp-level-open" data-level="1">
<h2 class="icon icon-world">All Categories</h2>
<ul>
<li class="icon icon-arrow-left">
<a class="icon icon-display" href="#">Devices</a>
<div class="mp-level" data-level="2">
<h2 class="icon icon-display">Devices</h2>
<a class="mp-back" href="#">back</a>
<ul>
<li class="icon icon-arrow-left">
<a class="icon icon-phone" href="#">Mobile Phones</a>
<div class="mp-level">
<h2>Mobile Phones</h2>
<a class="mp-back" href="#">back</a>
<ul>
<li>Super Smart Phone</li>
<li>Thin Magic Mobile</li>
<li>Performance Crusher</li>
<li>Futuristic Experience</li>
</ul>
</div>
</li>
<li class="icon icon-arrow-left">
<a class="icon icon-tv" href="#">Televisions</a>
<div class="mp-level">
<h2>Televisions</h2>
<a class="mp-back" href="#">back</a>
<ul>
<li>Flat Superscreen</li>
<li>Gigantic LED</li>
<li>Power Eater</li>
<li>3D Experience</li>
<li>Classic Comfort</li>
</ul>
</div>
</li>
<li class="icon icon-arrow-left">
<a class="icon icon-camera" href="#">Cameras</a>
<div class="mp-level">
<h2>Cameras</h2>
<a class="mp-back" href="#">back</a>
<ul>
<li>Smart Shot</li>
<li>Power Shooter</li>
<li>Easy Photo Maker</li>
<li>Super Pixel</li>
</ul>
</div>
</li>
</ul>
</div>
</li>
<li class="icon icon-arrow-left">
<a class="icon icon-news" href="#">Magazines</a>
<div class="mp-level">
<h2 class="icon icon-news">Magazines</h2>
<a class="mp-back" href="#">back</a>
<ul>
<li>National Geographic</li>
<li>Scientific American</li>
<li>The Spectator</li>
<li>The Rambler</li>
<li>Physics World</li>
<li>The New Scientist</li>
</ul>
</div>
</li>
<li class="icon icon-arrow-left">
<a class="icon icon-shop" href="#">Store</a>
<div class="mp-level">
<h2 class="icon icon-shop">Store</h2>
<a class="mp-back" href="#">back</a>
<ul>
<li class="icon icon-arrow-left">
<a class="icon icon-t-shirt" href="#">Clothes</a>
<div class="mp-level">
<h2 class="icon icon-t-shirt">Clothes</h2>
<a class="mp-back" href="#">back</a>
<ul>
<li class="icon icon-arrow-left">
<a class="icon icon-female" href="#">Women's Clothing</a>
<div class="mp-level">
<h2 class="icon icon-female">Women's Clothing</h2>
<a class="mp-back" href="#">back</a>
<ul>
<li>Tops</li>
<li>Dresses</li>
<li>Trousers</li>
<li>Shoes</li>
<li>Sale</li>
</ul>
</div>
</li>
<li class="icon icon-arrow-left">
<a class="icon icon-male" href="#">Men's Clothing</a>
<div class="mp-level">
<h2 class="icon icon-male">Men's Clothing</h2>
<a class="mp-back" href="#">back</a>
<ul>
<li>Shirts</li>
<li>Trousers</li>
<li>Shoes</li>
<li>Sale</li>
</ul>
</div>
</li>
</ul>
</div>
</li>
<li>
<a class="icon icon-diamond" href="#">Jewelry</a>
</li>
<li>
<a class="icon icon-music" href="#">Music</a>
</li>
<li>
<a class="icon icon-food" href="#">Grocery</a>
</li>
</ul>
</div>
</li>
<li><a class="icon icon-photo" href="#">Collections</a></li>
<li><a class="icon icon-wallet" href="#">Credits</a></li>
</ul>
</div>
</nav>
<!-- /mp-menu -->
you can customize nav menu walker class of wordpress to put your N level HTML menu structure. Hers is a example of bootstrap nav walker
if (!class_exists('BootstrapBasicMyWalkerNavMenu')) {
class BootstrapBasicMyWalkerNavMenu extends Walker_Nav_Menu
{
//Overwrite display_element function to add has_children attribute. Not needed in >= Wordpress 3.4
/**
* #link https://gist.github.com/duanecilliers/1817371 copy from this url
*/
function display_element($element, &$children_elements, $max_depth, $depth = 0, $args, &$output)
{
if (!$element)
return;
$id_field = $this->db_fields['id'];
//display this element
if (is_array($args[0]))
$args[0]['has_children'] = !empty($children_elements[$element->$id_field]);
else if (is_object($args[0]))
$args[0]->has_children = !empty($children_elements[$element->$id_field]);
$cb_args = array_merge(array(&$output, $element, $depth), $args);
call_user_func_array(array(&$this, 'start_el'), $cb_args);
$id = $element->$id_field;
// descend only when the depth is right and there are childrens for this element
if (($max_depth == 0 || $max_depth > $depth + 1) && isset($children_elements[$id])) {
foreach ($children_elements[$id] as $child) {
if (!isset($newlevel)) {
$newlevel = true;
//start the child delimiter
$cb_args = array_merge(array(&$output, $depth), $args);
call_user_func_array(array(&$this, 'start_lvl'), $cb_args);
}
$this->display_element($child, $children_elements, $max_depth, $depth + 1, $args, $output);
}
unset($children_elements[$id]);
}
if (isset($newlevel) && $newlevel) {
//end the child delimiter
$cb_args = array_merge(array(&$output, $depth), $args);
call_user_func_array(array(&$this, 'end_lvl'), $cb_args);
}
//end this element
$cb_args = array_merge(array(&$output, $element, $depth), $args);
call_user_func_array(array(&$this, 'end_el'), $cb_args);
}// display_element
/**
* #link https://gist.github.com/duanecilliers/1817371 copy from this url
*/
public function start_el(&$output, $item, $depth = 0, $args = array(), $id = 0)
{
if ((is_object($item) && $item->title == null) || (!is_object($item))) {
return ;
}
$indent = ($depth) ? str_repeat("\t", $depth) : '';
$li_attributes = '';
$class_names = $value = '';
$classes = empty($item->classes) ? array() : (array) $item->classes;
//Add class and attribute to LI element that contains a submenu UL.
if (is_object($args) && $args->has_children) {
//$classes[] = 'dropdown';
$li_attributes .= ' data-dropdown="dropdown"';
}
$classes[] = 'menu-item-' . $item->ID;
//If we are on the current page, add the active class to that menu item.
$classes[] = ($item->current) ? 'active' : '';
//Make sure you still add all of the WordPress classes.
$class_names = join(' ', apply_filters('nav_menu_css_class', array_filter($classes), $item, $args));
$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 . $li_attributes . '>';
//Add attributes to link element.
$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) . '"' : '';
$attributes .= (is_object($args) && $args->has_children) ? ' class="dropdown-toggle" data-toggle="dropdown"' : '';
$item_output = (is_object($args)) ? $args->before : '';
$item_output .= '<a' . $attributes . '>';
$item_output .= (is_object($args) ? $args->link_before : '') . apply_filters('the_title', $item->title, $item->ID) . (is_object($args) ? $args->link_after : '');
$item_output .= (is_object($args) && $args->has_children) ? ' <span class="caret"></span> ' : '';
$item_output .= '</a>';
$item_output .= (is_object($args) ? $args->after : '');
$output .= apply_filters('walker_nav_menu_start_el', $item_output, $item, $depth, $args);
}// start_el
public function start_lvl(&$output, $depth = 0, $args = array())
{
$indent = str_repeat("\t", $depth);
$output .= "\n$indent<ul class=\"sub-menu dropdown-menu\">\n";
}
}
}
How to use this,
<?php wp_nav_menu(array('theme_location' => 'your-menu-location', 'container' => false, 'menu_class' => 'nav navbar-nav', 'walker' => new BootstrapBasicMyWalkerNavMenu())); ?>
Hope this will helps you.
For more information,
Understanding the Walker Class
WP Bootstrap Navwalker
Custom Nav Menu Walker Function
Related
This class creates a menu with different sub-levels :
class Bootstrap_Collapse_NavWalker extends Walker_Nav_Menu{
public function start_lvl( &$output, $depth = 0, $args = null ) {
$output .= "<ul>";
}
public function end_lvl(&$output, $depth = 0, $args = []){
$output .= "</ul>";
}
public function start_el(&$output, $item, $depth = 0, $args = [], $id = 0){
$itemClasses = empty( $item->classes ) ? array() : (array) $item->classes;
$class_names_li = "";
$class_names_a = "";
$class_names_i = "";
$item_output = "";
$hasChildrenElm = $args->walker->has_children;
if ( $hasChildrenElm ) {
$class_names_li = 'dropdown';
}
if ( $depth === 0 && !$hasChildrenElm ) {
$class_names_a = 'nav-link scrollto';
}
$activeElement = "";
if ( in_array( 'current-menu-item', $itemClasses ) ) $activeElement .'active';
$elementUrl = ! empty( $item->url ) ? esc_url($item->url) : '';
$output .= '<li class="'.$class_names_li.'">';
if ( $hasChildrenElm ) {
$output .= '<a class="'.$class_names_a.$activeElement.'" href="'.$elementUrl.'">
<span>'.$item->title.'</span>';
$class_names_i .= ($depth !== 0) ? "bi bi-chevron-right" : "bi bi-chevron-down";
$output .= '<i class="'.$class_names_i.'"></i>';
}elseif($item->title !== ""){
$output .= '<a class="'.$class_names_a.$activeElement.'" href="'.$elementUrl.'-1">'.$item->title.'</a>';
}
}
public function end_el(&$output, $item, $depth = 0, $args = []){
$output .= "</li>";
}
}
I am waiting for the following HTML :
<ul>
<li><a class="nav-link scrollto" href="#menu1">menu 1</a></li>
<li><a class="nav-link scrollto" href="#menu2">menu 2</a></li>
<li class="dropdown">
<span>Drop Down</span> <i class="bi bi-chevron-down"></i>
<ul>
<li>Drop Down 1</li>
<li class="dropdown">
<span>Deep Drop Down</span> <i class="bi bi-chevron-right"></i>
<ul>
<li>Deep Drop Down 1</li>
</ul>
</li>
</ul>
</li>
</ul>
But It print this HTML :
<ul>
<li><a class="nav-link scrollto" href="#menu1">menu 1</a></li>
<li><a class="nav-link scrollto" href="#menu2">menu 2</a></li>
<li class="dropdown">
<span>Drop Down</span> <i class="bi bi-chevron-down"></i>
<ul>
<a class="" href="#dropdownLink"></a>
<li>
<a class="" href="#dropdownLink"></a>
Drop Down 1
</li>
<li class="dropdown">
<span>Deep Drop Down</span> <i class="bi bi-chevron-right"></i>
<ul>
<a class="" href="#dropdownLink"></a>
<li>
<a class="" href="#dropdownLink"></a>
Deep Drop Down 1
</li>
</ul>
</li>
</ul>
</li>
</ul>
As you can see at each menu level the script prints again the anchor tag of the parent menu, I am not being able to identify when the script loop inserts the parent TAG anchor, you can help me with this problem
Fixed, missing close anchor tag correct code:
class Bootstrap_Collapse_NavWalker extends Walker_Nav_Menu{
public function start_lvl( &$output, $depth = 0, $args = null ) {
$output .= "<ul>";
}
public function end_lvl(&$output, $depth = 0, $args = [])
{
$output .= "</ul>";
}
public function start_el(&$output, $item, $depth = 0, $args = [], $id = 0){
$itemClasses = empty( $item->classes ) ? array() : (array) $item->classes;
$class_names_li = "";
$class_names_a = "";
$class_names_i = "";
$item_output = "";
$hasChildrenElm = $args->walker->has_children;
if ( $hasChildrenElm ) {
$class_names_li = 'dropdown';
}
if ( $depth === 0 && !$hasChildrenElm ) {
$class_names_a = 'nav-link scrollto';
}
$activeElement = "";
if ( in_array( 'current-menu-item', $itemClasses ) ) $activeElement .'active';
$elementUrl = ! empty( $item->url ) ? esc_url($item->url) : '';
if(!empty($elementUrl)){
$output .= '<li class="'.$class_names_li.'">';
if ( $hasChildrenElm ) {
$output .= '<a class="'.$class_names_a.$activeElement.'" href="'.$elementUrl.'">
<span>'.$item->title.'</span>';
$class_names_i .= ($depth !== 0) ? "bi bi-chevron-right" : "bi bi-chevron-down";
$output .= '<i class="'.$class_names_i.'"></i></a>';
}else{
$output .= '<a class="'.$class_names_a.$activeElement.'11" href="'.$elementUrl.'">'.$item->title.'</a>';
}
}
}
public function end_el(&$output, $item, $depth = 0, $args = [])
{
$output .= "</li>";
}
}
I'm trying to build my own Walker_Nav_Menu class for a vertical sidebar menu inside my Wordpress Theme. I'm using Bootstrap 4 as a Framework.
My goal is to build something like the following html with the Walker class.
<div id="accordion">
<ul>
<li>
<a href="#" class="custom-class" id="indiceheading-1" data-toggle="collapse" data-target="#indicecollapse-1" aria-expanded="true" aria-controls="indicecollapse-1">
Link 1 but it's an accordion
</a>
<ul id="indicecollapse-1" class="collapse show" aria-labelledby="indiceheading-1" data-parent="#sidebarIndice">
<li>Link inside the dropdown</li>
</ul>
</li>
<li>Link 2</li>
<li>Link 3</li>
<li>
<a href="#" class="collapsed" id="indiceheading-2" data-toggle="collapse" data-target="#indicecollapse-2" aria-expanded="false" aria-controls="indicecollapse-2">
Link 4 but it's an accordion
</a>
<ul id="indicecollapse-2" class="collapse" aria-labelledby="indiceheading-2" data-parent="#sidebarIndice">
<li>Link inside the second dropdown</li>
</ul>
</li>
</ul>
</div>
The walker class I wrote is the following one (but it's not working)
<?php
class Walker_Indice extends Walker_Nav_Menu{
public function start_lvl( &$output, $depth = 0, $args = array() ) {
$indent = str_repeat("\t",$depth);
$output .= "\n$indent<ul class=\"collapse deph_$depth\">\n";
} //start_lvl
public function end_lvl( &$output, $depth = 0, $args = array() ) {
$indent = str_repeat("\t", $depth);
$output .= "$indent</ul>\n"; //da cambiare a seconda di come apro in start_lvl
} //end_lvl
function start_el(&$output, $item, $depth=0, $args=array(), $id=0){
$indent = ($depth) ? str_repeat("\t",$depth): '';
$li_attributes='';
$class_names=$value='';
$classes = empty( $item->classes ) ? array() : (array) $item->classes;
$classes[] = ($item->current || $item->current_item_anchestor)? 'active' : '';
$classes[] = 'menu-item-'.$item->ID;
$class_names = join(' ', apply_filters('nav_menu_css_class', array_filter( $classes ), $item, $args ));
$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 . $li_attributes . '>';
$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) . '"' : '';
if($args->walker->has_children){
$attributes .= ( $args->walker->has_children ) ? ' class="nav-link dropdown-toggle" data-toggle="dropdown"' : '';
}else{
$attributes .= ' class="nav-link"';
}
$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 .= $args->after;
$output .= apply_filters ( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
} //start_el
}
Can someone help me with this? I'm new and I can't find a tutorial for this, because every tutorials on the web are for normal Bootstrap navbar, but with accordions I need dynamic data-target, aria-controls ecc.
Thanks for your help.
I want to ask something which I don't have any idea if its possible or not.
I will show you first as html to explain what I need.
<nav class="nav-categories">
<ul>
<li class="no-filter">
<strong>Category Name</strong> <span class="count">25</span>
</li>
<li class="no-filter">
<strong>Category Name</strong> <span class="count">25</span>
</li>
<li class="no-filter">
<strong>Category Name</strong> <span class="count">25</span>
</li>
<li class="no-filter">
<strong>Category Name</strong> <span class="count">25</span>
</li>
</ul>
<div class="hidden-content" id="hidden-categories">
<ul>
<li class="no-filter">
Category Name<span class="count">25</span>
</li>
<li class="no-filter">
Category Name<span class="count">25</span>
</li>
<li class="no-filter">
Category Name<span class="count">25</span>
</li>
<li class="no-filter">
Category Name<span class="count">25</span>
</li>
</ul>
</div>
<button class="category-toggle" data-action="content-toggle" data-target="#hidden-categories" data-more="Display More Categories" data-less="Display Less Categories">Display All Categories</button>
</nav>
As you see on the code above there are 2 <ul> elements two menus, but one is visible and one is hidden which I can display hidden-content by clicking on the button.
With the code below I can display all WordPress categories but would be nice to know if its possible to display the half of categories in the first div and the other half in hidden-content class.
<?php
$categories = get_categories();
echo '<nav class="nav-categories"><ul>';
foreach($categories as $category) {
echo '<li class="no-filter"><a href="' . get_category_link( $category->term_id ) . '">' . $category->name.'';
echo '<span class="count">' . $category->count . '</span>';
echo '</a></li>';
}
echo '</ul></nav>';
?>
Yes it is possible, and there are many ways to achieve this, probably the easiest and fastest is (this is extremely naive and I just added a few additions and modifications to your code, the concept is just find the index that is half the array length), this should work assuming your originally code works, if it doesn't then I'm sure you can understand the concept.
<?php
$categories = get_categories();
$firstNav = "";
$secondNav = "<div class="hidden-content" id="hidden-categories">";
echo '<nav class="nav-categories"><ul>';
$maxIndex = count($categories) - 1;
$half = floor($maxIndex / 2); //To get the middle of the array, or you can use ceil();
$curIndex = 0;
foreach($categories as $category) {
if ($curIndex <= $half) {
$firstHalf .= '<li class="no-filter"><a href="' . get_category_link( $category->term_id ) . '">' . $category->name.'';
$firstHalf .= '<span class="count">' . $category->count . '</span>';
$firstHalf .= '</a></li>';
}
else {
$secondHalf .= '<li class="no-filter"><a href="' . get_category_link( $category->term_id ) . '">' . $category->name.'';
$secondHalf .= '<span class="count">' . $category->count . '</span>';
$secondHalf .= '</a></li>';
}
$curIndex++;
}
$firstHalf .= "</ul>";
$secondHalf .= "</div>";
echo $firstHalf;
echo $secondHalf;
echo '</ul></nav>';
?>
I require the following output for my site menus for my theme, which I generated using Weebly.
<!--Top level-->
<div class="nav-container">
<ul class='wsite-menu-default'>
<li id='active'>
<a href='/'>Home</a></li>
<li id='pg460790036268222251'>
<a href='/about.html'>About US</a>
<!--Second Level-->
<div class='wsite-menu-wrap' style='display:none'>
<ul class='wsite-menu'>
<li id='wsite-nav-887406923503161985'>
<a href='/our-community.html' >
<span class='wsite-menu-title'>Our Community</span>
</a></li>
<li id='wsite-nav-920389812461078079'>
<a href='/our-approach.html' >
<span class='wsite-menu-title'>Our Approach</span>
<span class='wsite-menu-arrow'>></span></a>
<!--Third level-->
<div class='wsite-menu-wrap' style='display:none'>
<ul class='wsite-menu'>
<li id='wsite-nav-351232458403900697'>
<a href='/research.html' >
<span class='wsite-menu-title'>Research</span></a>
</li>
<li id='wsite-nav-824453669863261400'>
<a href='/advocacy.html' >
<span class='wsite-menu-title'>Advocacy</span></a>
</li>
<li id='wsite-nav-802033955677651213'>
<a href='/publications.html' >
<span class='wsite-menu-title'>Publications</span></a>
</li>
</ul>
</div>
<!--Repeat above block as required -->
........................
<!--End Third-->
</li>
<li id='wsite-nav-307985062116431544'>
<a href='/our-constitution.html' >
<span class='wsite-menu-title'>Our Constitution</span></a>
</li>
<li id='wsite-nav-347537193311521165'>
<a href='/job-opportunities.html' >
<span class='wsite-menu-title'>Job Opportunities</span></a>
</li>
</ul>
</div>
<!--Repeat above block as required -->
..............
<!--End Second-->
</li>
<!--Repeat above block as required -->
..............
<!--End Top-->
</ul></div>
Now I need to port this over to a Wordpress system. I am familiar with menu basics, but need to know how to configure a Walker or custom function for this task for my theme. All jQuery, CSS scripts are in place, all I need to do is nest the following output as it is with the respective ids, classes and specified inline styling. I have created the menu hierarchy at Wordpress admin like I did in Weebly. I have been searching for examples but cant seem to find one that fits my requirement. Below is my Walker function.
class my_menu_walker extends Walker_Nav_Menu
{
function start_lvl(&$output, $depth)
{
$indent = str_repeat("\t", $depth);
if($depth === 0)
{
$output .= "\n$indent<ul class='wsite-menu-default'>\n";
}
else
{
$output .= "\n$indent<ul class='wsite-menu-default' style='display:none'>\n";
}
}
function start_el(&$output, $item, $depth, $args)
{
global $wp_query;
$indent = ($depth)? str_repeat("\t", $depth): '';
$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 ) .'"' : '';
//if second level menus
/*$unit_output = $args->before;*/
$unit_output = "<a".$attributes.">";
$unit_output .= /*$args->link_before.*/ "<span>".apply_filters( 'the_title', $item->title, $item->ID )."</span>";
/*$unit_output .= $args->link_after;*/
$unit_output .= "</a>";
/*$unit_output .= $args->after;*/
//for top menu page navigation
if($item->current)
{
$output .= $indent."<li id='active'>";
}
else
{
$output .= $indent."<li id='pg".$item->ID."'>";
}
$output .= apply_filters( 'walker_nav_menu_start_el', $unit_output, $item, $depth, $args );
}
}
At the top of functions.php
add_theme_support( 'menus' );
And in header.php
<?php wp_nav_menu(array(
'theme_location' => 'header-menu',
'container' => 'div',
'container_class' => 'wsite-menu-default',
'menu_class' => 'nav-container',
'echo' => true,
'walker'=> new my_menu_walker()
)); ?>
My $depth is not receiving the correct data, please advise
function start_lvl(&$output, $depth)
{
$indent = str_repeat("\t", $depth);
if($depth > 1)
{
$output .= "\n$indent<ul class='wsite-menu'>\n";
}
else
{
$output .= "\n$indent<ul class='wsite-menu-default'>\n";
}
}
I created a custom menu called "sub-top-nav" and now I'd like to override the html output. In particular I would like to add an unique class to each item like.
This is how it looks atm:
<div class="clear-block block block-menu" id="block-menu-menu-sub-top-nav">
<div class="content">
<ul class="menu">
<li class="leaf first"><a title="Test 1" href="/test1">Test 1</a></li>
<li class="leaf"><a title="Test 2" href="/test2">Test 2</a></li>
<li class="leaf active-trail"><a class="active" title="Test 3" href="/test3">Test 3</a></li>
<li class="leaf last"><a title="Test 4" href="/test4">Test 4</a></li>
</ul>
</div>
</div>
And I'd like to change it into:
<div class="clear-block block block-menu" id="block-menu-menu-sub-top-nav">
<div class="content">
<ul class="menu">
<li class="leaf test1 first"><a title="Test 1" href="/test1">Test 1</a></li>
<li class="leaf test2"><a title="Test 2" href="/test2">Test 2</a></li>
<li class="leaf test3 active-trail"><a class="active" title="Test 3" href="/test3">Test 3</a></li>
<li class="leaf test4 last"><a title="Test 4" href="/test4">Test 4</a></li>
</ul>
</div>
</div>
This would give me more styling power.
Any idea how that works?
Thanks in advance!
Drupal 7 uses theme_menu_link instead of theme_menu_item
<?php
function theme_menu_link(array $variables) {
$element = $variables['element'];
$sub_menu = '';
if ($element['#below']) {
$sub_menu = drupal_render($element['#below']);
}
$output = l($element['#title'], $element['#href'], $element['#localized_options']);
return '<li' . drupal_attributes($element['#attributes']) . '>' . $output . $sub_menu . "</li>\n";
}
?>
I got it to work now. This piece of code might help someone else as well!
It goes into yourtheme/template.php
function phptemplate_menu_item($link, $has_children, $menu = '', $in_active_trail = FALSE, $extra_class = NULL) {
$class = ($menu ? 'expanded' : ($has_children ? 'collapsed' : 'leaf'));
if (!empty($extra_class))
$class .= ' '. $extra_class;
if ($in_active_trail)
$class .= ' active-trail';
$class .= ' ' . preg_replace('/[^a-zA-Z0-9]/', '', strtolower(strip_tags($link)));
return '<li class="'. $class .'">'. $link . $menu ."</li>\n";
}
After looking through the API I finally found an easy solution to tag the root menu with the same class (this is useful to style only the top level menus uniquely, while maintaining them dynamically friendly). Simply use the plid instead of mlid. I noticed the plid is always 0 for top level menus.
function theme_menu_link(array $variables) {
$element = $variables['element'];
$sub_menu = '';
$element['#attributes']['class'][] = 'menu-' . $element['#original_link']['plid'];
if ($element['#below']) {
$sub_menu = drupal_render($element['#below']);
}
$output = l($element['#title'], $element['#href'], $element['#localized_options']);
$count = 1;
return '<li' . drupal_attributes($element['#attributes']) . '>' . $output . $sub_menu . "</li>\n";
}
You can use the theme_menu_item function in your theme's template.php to do pretty much whatever you want to those menu items, including adding classes, ID's, etc.