Friends,
Tell me how to generate more than 1 levels of sub-menu in VB6 at runtime? Explain in brief? Any specific controls are there? But i dont want to use external controls!
Dynamic two or more levels sub-menu generation in vb6
creationdynamicsubmenuvb6
Related Solutions
For anyone who tackles something similar here's my solution:
Quick code example on a gist
Here's the code on a github gist for anyone who wants to get in on the copy paste action.
TL;DR
TL;DR Loop over list, drill down if there's a sub menu, close if we reach the end of the sub menu and menu.
Complete Code explanation
Firstly get the menu items as a flat array:
<?php
$menu_name = 'main_nav';
$locations = get_nav_menu_locations();
$menu = wp_get_nav_menu_object( $locations[ $menu_name ] );
$menuitems = wp_get_nav_menu_items( $menu->term_id, array( 'order' => 'DESC' ) );
?>
Then iterate over the array of the menu items:
<nav>
<ul class="main-nav">
<?php
$count = 0;
$submenu = false;
foreach( $menuitems as $item ):
// set up title and url
$title = $item->title;
$link = $item->url;
// item does not have a parent so menu_item_parent equals 0 (false)
if ( !$item->menu_item_parent ):
// save this id for later comparison with sub-menu items
$parent_id = $item->ID;
?>
Write the first parent item <li>
:
<li class="item">
<a href="<?php echo $link; ?>" class="title">
<?php echo $title; ?>
</a>
<?php endif; ?>
Check that this items' parent id matches the stored parent id:
<?php if ( $parent_id == $item->menu_item_parent ): ?>
Start sub-menu <ul>
and set $submenu
flag to true for later referance:
<?php if ( !$submenu ): $submenu = true; ?>
<ul class="sub-menu">
<?php endif; ?>
Write the sub-menu item:
<li class="item">
<a href="<?php echo $link; ?>" class="title"><?php echo $title; ?></a>
</li>
If the next item does not have the same parent id and we have a sub-menu declared then close the sub-menu <ul>
<?php if ( $menuitems[ $count + 1 ]->menu_item_parent != $parent_id && $submenu ): ?>
</ul>
<?php $submenu = false; endif; ?>
<?php endif; ?>
Again, if the next item in the array does not have the same parent id close the <li>
<?php if ( $menuitems[ $count + 1 ]->menu_item_parent != $parent_id ): ?>
</li>
<?php $submenu = false; endif; ?>
<?php $count++; endforeach; ?>
</ul>
</nav>
Bootstrap 5 (update 2021)
Add some JavaScript to prevent the submenu from closing when the parent dropdown is open. This can be done be toggle display:block
...
let dropdowns = document.querySelectorAll('.dropdown-toggle')
dropdowns.forEach((dd)=>{
dd.addEventListener('click', function (e) {
var el = this.nextElementSibling
el.style.display = el.style.display==='block'?'none':'block'
})
})
Bootstrap 5 Multi-level Dropdown - click
Bootstrap 5 Multi-level Dropdown - hover
Or, you can use this CSS only method for Navbar dropdowns...
.dropdown-submenu {
position: relative;
}
.dropdown-submenu .dropdown-menu {
top: 0;
left: 100%;
margin-top: -1px;
}
.navbar-nav li:hover > ul.dropdown-menu {
display: block;
}
Bootstrap 5 Navbar Dropdown Hover Submenus (CSS only)
Bootstrap 4 (update 2018)
The dropdown-submenu
has been removed in Bootstrap 3 RC. In the words of Bootstrap author Mark Otto..
"Submenus just don't have much of a place on the web right now, especially the mobile web. They will be removed with 3.0" - https://github.com/twbs/bootstrap/pull/6342
But, with a little extra CSS you can get the same functionality.
navbar submenu on hover:
.navbar-nav li:hover > ul.dropdown-menu {
display: block;
}
.dropdown-submenu {
position:relative;
}
.dropdown-submenu>.dropdown-menu {
top:0;
left:100%;
margin-top:-6px;
}
Navbar submenu dropdown hover
Navbar submenu dropdown hover (right aligned)
Navbar submenu dropdown click (right aligned)
Navbar dropdown hover (no submenu)
Bootstrap 3
Here is an example that uses 3.0 RC 1: http://bootply.com/71520
Here is an example that uses Bootstrap 3.0.0 (final): http://bootply.com/86684
CSS
.dropdown-submenu {
position:relative;
}
.dropdown-submenu>.dropdown-menu {
top:0;
left:100%;
margin-top:-6px;
margin-left:-1px;
-webkit-border-radius:0 6px 6px 6px;
-moz-border-radius:0 6px 6px 6px;
border-radius:0 6px 6px 6px;
}
.dropdown-submenu:hover>.dropdown-menu {
display:block;
}
.dropdown-submenu>a:after {
display:block;
content:" ";
float:right;
width:0;
height:0;
border-color:transparent;
border-style:solid;
border-width:5px 0 5px 5px;
border-left-color:#cccccc;
margin-top:5px;
margin-right:-10px;
}
.dropdown-submenu:hover>a:after {
border-left-color:#ffffff;
}
.dropdown-submenu.pull-left {
float:none;
}
.dropdown-submenu.pull-left>.dropdown-menu {
left:-100%;
margin-left:10px;
-webkit-border-radius:6px 0 6px 6px;
-moz-border-radius:6px 0 6px 6px;
border-radius:6px 0 6px 6px;
}
Sample Markup
<div class="navbar navbar-default navbar-fixed-top" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
<div class="collapse navbar-collapse navbar-ex1-collapse">
<ul class="nav navbar-nav">
<li class="menu-item dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Drop Down<b class="caret"></b></a>
<ul class="dropdown-menu">
<li class="menu-item dropdown dropdown-submenu">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Level 1</a>
<ul class="dropdown-menu">
<li class="menu-item ">
<a href="#">Link 1</a>
</li>
<li class="menu-item dropdown dropdown-submenu">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Level 2</a>
<ul class="dropdown-menu">
<li>
<a href="#">Link 3</a>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
</div>
</div>
P.S. - Example in navbar that adjusts left position: http://bootply.com/92442
Best Solution
You Can Create More than One level of Submenu by using API function
To display
The menu is not displayed until
TrackPopupMenu
is called. Its return value can indicate which (if any) menu item was selected. e.g., it could return '107' if "Menu1" was selected.