How do I toggle sub menu items on a navigation? - javascript

I am working on an accessible navigation and would like to toggle submenu items on click using the same click handler but their closest respective sub-menu-items. (Any accessibility help is a bonus.) Is the only way to do this by setting an ID? If so, I would like this to be dynamic in the JS where the data-id is not hardcoded.
function handleSubmenuToggle() {
console.log('click');
document.querySelector('.sub-menu-items').style.display = 'block';
}
.nav-menu-container {
background: black;
color: white;
font-size: 0.875rem;
padding: 1.3125rem 1.875rem;
}
.menu-item {
display: inline;
padding: 0 0.75rem;
position: relative;
}
.menu-item button {
background-color: transparent;
border: none;
color: white;
}
.sub-menu-items {
background: white;
display: none;
left: -25px;
min-width: 183px;
padding: 10px 0;
position: absolute;
top: 40px;
}
.sub-menu-items.show {
display: block !important;
}
.sub-menu-items:after {
width: 0;
height: 0;
border-left: 15px solid transparent;
border-right: 15px solid transparent;
border-bottom: 15px solid white;
content: " ";
position: absolute;
top: -10px;
left: 42%;
}
.sub-menu-items a {
color: black;
text-decoration: none;
padding: .5rem 1rem;
display: block;
}
.sub-menu-items a:hover {
background-color: lightgray;
}
<header>
<nav aria-label="Empower Reservation Navigation" class="nav-menu-container">
<ul class="menu-items">
<li class="menu-item slds-is-relative">
<button aria-label='Toggle Button' aria-pressed='pressed' onclick="handleSubmenuToggle();">Menu Item 1 <i class="fa-solid fa-chevron-down"></i></button>
<ul class="sub-menu-items">
<li>
Sub Menu Item
</li>
<li>
Sub Menu Item 2
</li>
<li>
Sub Menu Item 3
</li>
<li>
Sub Menu Item 4
</li>
</ul>
</li>
<li class="menu-item slds-is-relative">
<button aria-label='Toggle Button' aria-pressed='pressed' onclick="handleSubmenuToggle()">Menu Item 2<i class="fa-solid fa-chevron-down"></i></button>
<ul class="sub-menu-items">
<li>
Sub Menu Item
</li>
<li>
Sub Menu Item 2
</li>
<li>
Sub Menu Item 3
</li>
<li>
Sub Menu Item 4
</li>
</ul>
</li>
<li class="menu-item slds-is-relative">
<button aria-label='Toggle Button' aria-pressed='pressed'>Tools <i class="fa-solid fa-chevron-down"></i></button>
<ul class="sub-menu-items">
<li>
Sub Menu Item
</li>
<li>
Sub Menu Item 2
</li>
<li>
Sub Menu Item 3
</li>
<li>
Sub Menu Item 4
</li>
</ul>
</li>
<li class="menu-item slds-is-relative">
<button aria-label='Toggle Button' aria-pressed='pressed'>Contact [Name] <i class="fa-solid fa-chevron-down"></i></button>
<ul class="sub-menu-items">
<li>
Sub Menu Item
</li>
<li>
Sub Menu Item 2
</li>
<li>
Sub Menu Item 3
</li>
<li>
Sub Menu Item 4
</li>
</ul>
</li>
</ul>
</nav>
</header>
Thanks in advance!
https://codepen.io/fawn-marie/pen/GRBobNX?editors=1111

W3 has some great examples how to implement WCAG features with ARIA attributes. A specific example could be found here: Navigation Menubar Example.
Give the <button> element two new aria attributes
aria-haspopup to indicate that there is a flyout submenu;
aria-expanded to provide information if the flyout is visible or not
By doing this you're giving the <button> the control over the state of the submenu. aria-expanded will now tell you the current state of the submenu. You can manipulate this state through JavaScript by setting the attribute value with Element.setAttribute.
Then you can open and close your submenu by styling the submenu based on the aria-expanded value. Since the button is a sibling of the submenu, you can use the sibling selector + to select the submenu whenever the button has a certain attribute, like this.
ul.submenu {
display: none;
}
button[aria-expanded="true"] + ul.submenu {
display: block;
}
The cool thing about this is that the <button> is the only authority over the submenu. From here you only have to listen for clicks on the button to toggle the aria-expanded state. The rest will be governed by CSS.
I suggest you look at the W3 link as it shows more attributes that you should use in this kind of structure to improve accessibility.
const subMenuToggles = document.querySelectorAll('.sub-menu-toggle');
document.addEventListener('click', event => {
const subMenuToggle = event.target.closest('.sub-menu-toggle');
if (subMenuToggle === null) {
return;
}
for (const toggle of subMenuToggles) {
if (toggle.hasAttribute('aria-haspopup')) {
toggle.setAttribute('aria-expanded', 'false');
}
}
if (!subMenuToggle.hasAttribute('aria-haspopup')) {
return;
}
if (subMenuToggle.getAttribute('aria-expanded') === 'true') {
subMenuToggle.setAttribute('aria-expanded', 'false');
} else {
subMenuToggle.setAttribute('aria-expanded', 'true');
}
});
.nav-menu-container {
background: black;
color: white;
font-size: 0.875rem;
padding: 1.3125rem 1.875rem;
}
.menu-item {
display: inline;
padding: 0 0.75rem;
position: relative;
}
.menu-item button {
background-color: transparent;
border: none;
color: white;
}
.sub-menu-items {
display: none;
background: white;
left: -25px;
min-width: 183px;
padding: 10px 0;
position: absolute;
top: 40px;
}
.sub-menu-toggle[aria-expanded="true"] + .sub-menu-items {
display: block;
}
.sub-menu-items:after {
width: 0;
height: 0;
border-left: 15px solid transparent;
border-right: 15px solid transparent;
border-bottom: 15px solid white;
content: " ";
position: absolute;
top: -10px;
left: 42%;
}
.sub-menu-items a {
color: black;
text-decoration: none;
padding: .5rem 1rem;
display: block;
}
.sub-menu-items a:hover {
background-color: lightgray;
}
<header>
<nav aria-label="Empower Reservation Navigation" class="nav-menu-container">
<ul class="menu-items">
<li class="menu-item slds-is-relative">
<button class="sub-menu-toggle" aria-label='Toggle Button' aria-haspopup="true" aria-expanded="false">Menu Item 1 <i class="fa-solid fa-chevron-down"></i></button>
<ul class="sub-menu-items">
<li>
Sub Menu Item
</li>
<li>
Sub Menu Item 2
</li>
<li>
Sub Menu Item 3
</li>
<li>
Sub Menu Item 4
</li>
</ul>
</li>
<li class="menu-item slds-is-relative">
<button class="sub-menu-toggle" aria-label='Toggle Button' aria-haspopup="true" aria-expanded="false">Menu Item 2<i class="fa-solid fa-chevron-down"></i></button>
<ul class="sub-menu-items">
<li>
Sub Menu Item
</li>
<li>
Sub Menu Item 2
</li>
<li>
Sub Menu Item 3
</li>
<li>
Sub Menu Item 4
</li>
</ul>
</li>
<li class="menu-item slds-is-relative">
<button class="sub-menu-toggle" aria-label='Toggle Button' aria-haspopup="true" aria-expanded="false">Tools <i class="fa-solid fa-chevron-down"></i></button>
<ul class="sub-menu-items">
<li>
Sub Menu Item
</li>
<li>
Sub Menu Item 2
</li>
<li>
Sub Menu Item 3
</li>
<li>
Sub Menu Item 4
</li>
</ul>
</li>
<li class="menu-item slds-is-relative">
<button aria-label='Toggle Button' aria-pressed='pressed'>Contact [Name] <i class="fa-solid fa-chevron-down"></i></button>
<ul class="sub-menu-items">
<li>
Sub Menu Item
</li>
<li>
Sub Menu Item 2
</li>
<li>
Sub Menu Item 3
</li>
<li>
Sub Menu Item 4
</li>
</ul>
</li>
</ul>
</nav>
</header>

Related

Close Dropdown Submenu After Click in Bootstrap

I have created a website with bootstrap 3 framwork. now problem is, dropdown submenu not closed after clicking the sub-menu item. my templates uses hover function to show up sub-menu items.
I want to close the dropdown when the user clicks sub menu item.
For an example, services menu contains submenu list. when the users clicks anyone of item, entire sub-menu should be closed. how to do? any suggestions?
sitelink
jQuery( ".dropdown-menu li a" ).click(function() {
jQuery("ul.dropdown-menu").css("display", "none");
});
Use display block in the css code
.dropdown:hover .dropdown-content {
display: block;
}
.dropdown-content a:hover {background-color: #f1f1f1}
<div class="dropdown">
<button class="dropbtn">Dropdown</button>
<div class="dropdown-content">
Link 1
Link 2
Link 3
</div>
</div>
You can use extra class to select the menu items which have dropdown element. For this example, a class "trigger" is used for defining which have child elements.
$(function(){
$(".dropdown-menu > li > a.trigger").on("click",function(e){
var current=$(this).next();
var grandparent=$(this).parent().parent();
if($(this).hasClass('left-caret')||$(this).hasClass('right-caret'))
$(this).toggleClass('right-caret left-caret');
grandparent.find('.left-caret').not(this).toggleClass('right-caret left-caret');
grandparent.find(".sub-menu:visible").not(current).hide();
current.toggle();
e.stopPropagation();
});
$(".dropdown-menu > li > a:not(.trigger)").on("click",function(){
var root=$(this).closest('.dropdown');
root.find('.left-caret').toggleClass('right-caret left-caret');
root.find('.sub-menu:visible').hide();
});
});
.dropdown-menu>li
{ position:relative;
-webkit-user-select: none; /* Chrome/Safari */
-moz-user-select: none; /* Firefox */
-ms-user-select: none; /* IE10+ */
/* Rules below not implemented in browsers yet */
-o-user-select: none;
user-select: none;
cursor:pointer;
}
.dropdown-menu .sub-menu {
left: 100%;
position: absolute;
top: 0;
display:none;
margin-top: -1px;
border-top-left-radius:0;
border-bottom-left-radius:0;
border-left-color:#fff;
box-shadow:none;
}
.right-caret:after,.left-caret:after
{ content:"";
border-bottom: 5px solid transparent;
border-top: 5px solid transparent;
display: inline-block;
height: 0;
vertical-align: middle;
width: 0;
margin-left:5px;
}
.right-caret:after
{ border-left: 5px solid #ffaf46;
}
.left-caret:after
{ border-right: 5px solid #ffaf46;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<div class="dropdown" style="position:relative">
Click Here <span class="caret"></span>
<ul class="dropdown-menu">
<li>
<a class="trigger right-caret">Level 1</a>
<ul class="dropdown-menu sub-menu">
<li>Level 2</li>
<li>
<a class="trigger right-caret">Level 2</a>
<ul class="dropdown-menu sub-menu">
<li>Level 3</li>
<li>Level 3</li>
<li>
<a class="trigger right-caret">Level 3</a>
<ul class="dropdown-menu sub-menu">
<li>Level 4</li>
<li>Level 4</li>
<li>Level 4</li>
</ul>
</li>
</ul>
</li>
<li>Level 2</li>
</ul>
</li>
<li>Level 1</li>
<li>Level 1</li>
</ul>
</div>
try this jquery
$( ".dropdown" ).click(function() {
$(".dropdown").removeClass("open");
$("#menulink + .dropdown-menu").css("display", "none");
});
remove the open class of dropdown when a link is clicked

jQuery Reverse Drop Toggle & CSS Fix

≫ Live Demo On JSFiddle ≪
Occurring Problems / Questions
1). Toggling Show/Hide
Upon clicking on the same drop toggle, or another, I need to reverse the process of any already clicked drop toggles and then show the clicked drop toggle. The current version simply uses the following jQuery code:
$(".HonorBarsList a").click(function(){
$(this).parent().parent().parent().css({ marginBottom : "296px" });
$(this).parent().css({ borderBottom : "none" });
$(this).parent().find("ul").show();
});
I understand that I could loop through the entire scope, applying the initial CSS to all, however this seems like a rather lengthy way to do this.
Q). What is my best solution to use here?
2). Last List Set > UL > Top Left Border
This list is generated via a PHP PDO query, therefore the amount of list items will be unknown. On my provided demo, the last set has only three LI's meaning at the top left corner, there appears to be missing border.
Q). Should I fake this by having the link drop toggle's bottom border white and the UL simply have all borders, or is there another trick I can use, remembering that the last set could have 1-4 LI's within.
It is ok to reset the CSS to all the relevant elements. It might be better to do it with an active class though to make the jQuery code a bit cleaner.
Below is an example of just setting the CSS back to it's defaults before applying the relevent CSS to the clicked element.
$(document).ready(function(){
"use strict";
$(".myList a").click(function(){
// store relevent elements
var parentUl = $(this).parent().parent().parent();
var $this = $(this);
if($this.hasClass("active-li")) {
// if clicked element is already active then toggle class
parentUl.toggleClass("active-ul");
$this.toggleClass("active-li");
} else {
// otherwise remove active class from active elements
$(".active-ul").removeClass("active-ul");
$(".active-li").removeClass("active-li");
// then toggle the active class on the clicked parent element
parentUl.toggleClass("active-ul");
$this.toggleClass("active-li");
}
});
});
.myList {
display: block;
float: left;
width: 600px;
height: auto;
margin:0;
padding:0;
border-top:1px solid black;
}
.myList > li,
.myList > li > ul {
display: block;
float: left;
height: 50px;
width: 600px;
margin: 0;
padding: 0;
}
.myList > li > ul > li {
display: block;
float: left;
height: 51px;
width: 150px;
border-left: 1px solid black;
box-sizing: border-box;
overflow: hidden;
}
.myList > li > ul > li:last-of-type { border-right: 1px solid black; }
.myList > li > ul > li a {
display: block;
height: 50px;
width: 100%;
border-bottom: 1px solid black;
position:relative;
z-index:2;
}
.myList > li > ul > li > a > div {
display: block;
float: left;
}
.myList > li > ul > li > ul {
display: none;
position: absolute;
height: 150px;
width: 600px;
margin-top: -1px;
margin-left: -1px;
border-top: 1px solid black;
border-left: 1px solid black;
border-right: 1px solid black;
border-bottom: 1px solid black;
box-sizing: border-box;
z-index:1;
}
.myList > li > ul > li:nth-of-type(2) > ul { margin-left: -151px; }
.myList > li > ul > li:nth-of-type(3) > ul { margin-left: -301px; }
.myList > li > ul > li:nth-of-type(4) > ul { margin-left: -451px; }
.myList .active-ul {
margin-bottom:150px;
}
.myList .active-li {
border-bottom:1px solid white;
}
.myList .active-li + ul {
display:block;
}
<ul class="myList">
<li>
<ul>
<li>
<a href="javascript:;">
Link Area
</a>
<ul>
<p>Additional Informatioin Area...</p>
</ul>
</li>
<li>
<a href="javascript:;">
Link Area
</a>
<ul>
<p>Additional Informatioin Area...</p>
</ul>
</li>
<li>
<a href="javascript:;">
Link Area
</a>
<ul>
<p>Additional Informatioin Area...</p>
</ul>
</li>
<li>
<a href="javascript:;">
Link Area
</a>
<ul>
<p>Additional Informatioin Area...</p>
</ul>
</li>
</ul>
</li>
<li>
<ul>
<li>
<a href="javascript:;">
Link Area
</a>
<ul>
<p>Additional Informatioin Area...</p>
</ul>
</li>
<li>
<a href="javascript:;">
Link Area
</a>
<ul>
<p>Additional Informatioin Area...</p>
</ul>
</li>
<li>
<a href="javascript:;">
Link Area
</a>
<ul>
<p>Additional Informatioin Area...</p>
</ul>
</li>
<li>
<a href="javascript:;">
Link Area
</a>
<ul>
<p>Additional Informatioin Area...</p>
</ul>
</li>
</ul>
</li>
<li>
<ul>
<li>
<a href="javascript:;">
Link Area
</a>
<ul>
<p>Additional Informatioin Area...</p>
</ul>
</li>
<li>
<a href="javascript:;">
Link Area
</a>
<ul>
<p>Additional Informatioin Area...</p>
</ul>
</li>
<li>
<a href="javascript:;">
Link Area
</a>
<ul>
<p>Additional Informatioin Area...</p>
</ul>
</li>
<li>
<a href="javascript:;">
Link Area
</a>
<ul>
<p>Additional Informatioin Area...</p>
</ul>
</li>
</ul>
</li>
<li>
<ul>
<li>
<a href="javascript:;">
Link Area
</a>
<ul>
<p>Additional Informatioin Area...</p>
</ul>
</li>
<li>
<a href="javascript:;">
Link Area
</a>
<ul>
<p>Additional Informatioin Area...</p>
</ul>
</li>
<li>
<a href="javascript:;">
Link Area
</a>
<ul>
<p>Additional Informatioin Area...</p>
</ul>
</li>
<li>
<a href="javascript:;">
Link Area
</a>
<ul>
<p>Additional Informatioin Area...</p>
</ul>
</li>
</ul>
</li>
<li>
<ul>
<li>
<a href="javascript:;">
Link Area
</a>
<ul>
<p>Additional Informatioin Area...</p>
</ul>
</li>
<li>
<a href="javascript:;">
Link Area
</a>
<ul>
<p>Additional Informatioin Area...</p>
</ul>
</li>
<li>
<a href="javascript:;">
Link Area
</a>
<ul>
<p>Additional Informatioin Area...</p>
</ul>
</li>
</ul>
</li>
</ul>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Maybe it's better to use the .toggle from jQuery
you can handle initial state and new state onclick event
$(".myList a").click(function(){
$(this).parent().parent().parent().toggle(function () {
$(this).parent().parent().parent().css({borderBottomLeftRadius: "150px"});
}, function () {
$(this).parent().parent().parent().css({borderBottomLeftRadius: "0px"});
});
)};

how make specific number of button can be selected and after select change the colors of those that selected

ul.number-list li {
list-style: none;
display: inline-block;
}
ul.number-list li a {
display: block;
width: 35px;
height: 35px;
-webkit-border-radius: 35px;
border-radius: 35px;
line-height: 35px;
text-align: center;
background: purple;
color: #fff;
cursor: pointer;
}
<ul class="number-list">
<li>
<a role="button">1</a>
</li>
<li>
<a role="button">11</a>
</li>
<li>
<a role="button">31</a>
</li>
<li>
<a role="button">12</a>
</li>
<li>
<a role="button">16</a>
</li>
<li>
<a role="button">6</a>
</li>
<li>
<a role="button">12</a>
</li>
<li>
<a role="button">21</a>
</li>
<li>
<a role="button">2</a>
</li>
<li>
<a role="button">44</a>
</li>
</ul>
I'm new in javascript and I need help and I would be grateful if sombody help !
in this case I have a list of buttons and I want restrict the number of selecting buttons like 6 buttons.and each button can be select just for once and after select color of it get change.help me please to write this code.thank you
var SelectCount=0;
function ButtonSelected(id) {
if (SelectCount < 3) {
document.getElementById(id).style.backgroundColor="red";
SelectCount+=1;
}
}
ul.number-list li {
list-style: none;
display: inline-block;
}
ul.number-list li a {
display: block;
width: 35px;
height: 35px;
-webkit-border-radius: 35px;
border-radius: 35px;
line-height: 35px;
text-align: center;
background: purple;
color: #fff;
cursor: pointer;
}
<ul class="number-list">
<li >
<a id="n1" onclick="ButtonSelected('n1')" role="button">1</a>
</li>
<li>
<a id="n2" onclick="ButtonSelected('n2')" role="button">11</a>
</li>
<li>
<a id="n3" onclick="ButtonSelected('n3')" role="button">31</a>
</li>
<li>
<a id="n4" onclick="ButtonSelected('n4')" role="button">12</a>
</li>
<li>
<a id="n5" onclick="ButtonSelected('n5')" role="button">16</a>
</li>
<li>
<a id="n6" onclick="ButtonSelected('n6')" role="button">6</a>
</li>
<li>
<a id="n7" onclick="ButtonSelected('n7')" role="button">12</a>
</li>
<li>
<a id="n8" onclick="ButtonSelected('n8')" role="button">21</a>
</li>
<li>
<a id="n9" onclick="ButtonSelected('n9')" role="button">2</a>
</li>
<li>
<a id="n10" onclick="ButtonSelected('n10')" role="button">44</a>
</li>
</ul>
This code will change the button to red and increment the counter. In this code, three buttons max can be selected. Buttons cannot be deselected.
var SelectCount = 0;
function ButtonSelected(id) {
if (document.getElementById(id).style.backgroundColor == "red") {
SelectCount -= 1;
document.getElementById(id).style.backgroundColor = "purple";
document.getElementById("checker").innerHTML = SelectCount + " selected (3 max)";
} else {
if (SelectCount < 3) {
document.getElementById(id).style.backgroundColor = "red";
SelectCount += 1;
document.getElementById("checker").innerHTML = SelectCount + " selected (3 max)";
} else {
document.getElementById("checker").innerHTML = "You must unselect another button before selecting this one.<br />Maximum of three buttons selected reached.";
}
}
}
ul.number-list li {
list-style: none;
display: inline-block;
}
ul.number-list li a {
display: block;
width: 35px;
height: 35px;
-webkit-border-radius: 35px;
border-radius: 35px;
line-height: 35px;
text-align: center;
background: purple;
color: #fff;
cursor: pointer;
}
<ul class="number-list">
<li>
<a id="n1" onclick="ButtonSelected('n1')" role="button">1</a>
</li>
<li>
<a id="n2" onclick="ButtonSelected('n2')" role="button">11</a>
</li>
<li>
<a id="n3" onclick="ButtonSelected('n3')" role="button">31</a>
</li>
<li>
<a id="n4" onclick="ButtonSelected('n4')" role="button">12</a>
</li>
<li>
<a id="n5" onclick="ButtonSelected('n5')" role="button">16</a>
</li>
<li>
<a id="n6" onclick="ButtonSelected('n6')" role="button">6</a>
</li>
<li>
<a id="n7" onclick="ButtonSelected('n7')" role="button">12</a>
</li>
<li>
<a id="n8" onclick="ButtonSelected('n8')" role="button">21</a>
</li>
<li>
<a id="n9" onclick="ButtonSelected('n9')" role="button">2</a>
</li>
<li>
<a id="n10" onclick="ButtonSelected('n10')" role="button">44</a>
</li>
</ul>
<div id="checker">
Select up to three buttons.
</div>
This answer allows deselecting a button and provides user feedback as well. As in my other answer, a max of three buttons can be selected at a time.
ul.number-list li {
list-style: none;
display: inline-block;
}
ul.number-list li a {
display: block;
width: 35px;
height: 35px;
-webkit-border-radius: 35px;
border-radius: 35px;
line-height: 35px;
text-align: center;
background: purple;
color: #fff;
cursor: pointer;
}
ul.number-list li a.selected {
background: red;
}
<ul class="number-list">
<li>
<a role="button">1</a>
</li>
<li>
<a role="button">11</a>
</li>
<li>
<a role="button">31</a>
</li>
<li>
<a role="button">12</a>
</li>
<li>
<a role="button">16</a>
</li>
<li>
<a role="button">6</a>
</li>
<li>
<a role="button">12</a>
</li>
<li>
<a role="button">21</a>
</li>
<li>
<a role="button">2</a>
</li>
<li>
<a role="button">44</a>
</li>
</ul>
<script>
window.addEventListener('load', function () {
document.querySelectorAll("ul.number-list li a").addEventListener('click', function() {
this.className = 'selected';
});
});
</script>

menu acordeon : div stuck in my list because of the overflow

I want to create a side menu and my code look like this :
function opensubmenus() {
$('#submenus').css("display", "block");
}
#menus {
overflow-y: scroll;
width: 150px;
background-color: blue;
}
#submenus {
background-color: green;
display: none;
}
submenus ul {
float: right;
position: relative;
}
nav {
overflow: hidden;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<nav>
<div id='menus'>
<ul>
<li>
<span onclick='opensubmenus()'>Menu 1</span>
<ul id='submenus'>
<li>SubMenu 1
</li>
<li>
SubMenu 2
</li>
<li>
SubMenu 3
</li>
</ul>
</li>
<li>
Menu 2
</li>
<li>
Menu 3
</li>
</ul>
</div>
</nav>
But I when I show my submenu, he do not apear outside the box...
I want a menu like this :
I need absolutely need the "overflow-y" because I have a lot of menu and I need to have a scrolling option. Did you know how to have this result?
You have <ul id="submenus"> within <div id="menus">, if you don't want the sub menus inside of the menu, make another <div>, and put it in that:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<nav>
<div id='menus'>
<ul>
<li>
<span onclick='opensubmenus()'>Menu 1</span>
</li>
<li>
Menu 2
</li>
<li>
Menu 3
</li>
</ul>
</div>
<div>
<ul id='submenus'>
<li>SubMenu 1
</li>
<li>
SubMenu 2
</li>
<li>
SubMenu 3
</li>
</ul>
</div>
</nav>
Then to get them side-by-side, apply float:left; to #menus:
#menus {
overflow-y: scroll;
width: 150px;
background-color: blue;
float: left;
}
#submenus {
background-color: green;
display: none;
}
submenus, ul {
float: right;
position: relative;
}
nav {
overflow: hidden;
}
You can change your CSS and use absolute position on the submenu:
function opensubmenus() {
$('#submenus').css("display", "block");
}
#menus {
position:relative;
display:inline-block;
}
.main {
overflow-y: scroll;
margin:0;
width: 150px;
background-color: blue;
}
#submenus {
position:absolute;
left:100%;
top:0;
background-color: green;
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<nav>
<div id='menus'>
<ul class="main">
<li>
<span onclick='opensubmenus()'>Menu 1</span>
<ul id='submenus'>
<li>SubMenu 1
</li>
<li>
SubMenu 2
</li>
<li>
SubMenu 3
</li>
</ul>
</li>
<li>
Menu 2
</li>
<li>
Menu 3
</li>
</ul>
</div>
</nav>
Bonus -- Quick Multiple SubMenus
$('span').click(function(){
var col = $(this).data('color');
$('.submenus').hide();
$('span').css('background', '');
$(this).css('background', col);
$(this).next('.submenus').show().css('background', col);
})
#menus {
position:relative;
display:inline-block;
}
.main {
overflow-y: scroll;
margin:0;
width: 150px;
background-color: blue;
}
.submenus {
position:absolute;
left:100%;
top:0;
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<nav>
<div id='menus'>
<ul class="main">
<li>
<span data-color="red">Menu 1</span>
<ul class='submenus'>
<li>SubMenu 1
</li>
<li>
SubMenu 2
</li>
<li>
SubMenu 3
</li>
</ul>
</li>
<li>
<span data-color="yellow">Menu 2</span>
<ul class='submenus'>
<li>SubMenu 21
</li>
<li>
SubMenu 22
</li>
<li>
SubMenu 23
</li>
</ul>
</li>
<li>
<span data-color="green">Menu 3</span>
<ul class='submenus'>
<li>SubMenu 31
</li>
<li>
SubMenu 32
</li>
<li>
SubMenu 33
</li>
</ul>
</li>
</ul>
</div>
</nav>

Accordion menu - active state

I've lately managed to make my accordion menu. I did everything besides this one thing I'm looking for help.
This is my accordion menu:
HTML
<div class="sidebar-wrapper">
<ul class="main_nav">
<li><a href='#'>MAIN 1</a>
<ul class="sub-menu">
<li><a href='#'>SUB MENU</a>
<ul class="sub-menu">
<li><a href='#'>SUB-SUB MENU</a></li>
<li><a href='#'>SUB-SUB MENU</a></li>
<li><a href='#'>SUB-SUB MENU</a></li>
<li><a href='#'>SUB-SUB MENU</a></li>
<li><a href='#'>SUB-SUB MENU</a></li>
<li><a href='#'>SUB-SUB MENU</a></li>
</ul>
</li>
<li><a href='#'>SUB MENU</a>
<ul class="sub-menu">
<li><a href='#'>SUB-SUB MENU</a></li>
</ul>
</li>
<li><a href='#'>SUB MENU</a>
<ul class="sub-menu">
<li><a href='#'>SUB-SUB MENU</a></li>
</ul>
</li>
<li><a href='#'>SUB MENU</a>
<ul class="sub-sub-menu">
<li><a href='#'>SUB-SUB MENU</a></li>
</ul>
</li>
<li><a href='#'>SUB MENU</a>
<ul class="sub-menu">
<li><a href='#'>SUB-SUB MENU</a></li>
</ul>
</li>
</ul>
</li>
<li><a href='#'>MAIN 2</a></li>
</ul>
</div>
CSS
.sidebar-wrapper {
width: 250px;
margin-top: 30px;
}
.main_nav {
width: 250px;
list-style: none;
padding: 40px 30px 25px 0;
font-family: Arial;
}
ul.main_nav {
padding: 0;
margin: 0;
list-style-type: none;
}
ul.main_nav li {
list-style-type: none;
}
ul.main_nav li a {
background-image: url('../images/acmenu_bg.png');
background-repeat: repeat-x;
line-height: 10px;
padding: 13px 10px;
display: block;
text-decoration: none;
font-size: 13px;
color: #fff;
font-weight: bold;
list-style: none;
}
ul.main_nav li a:hover {
/* background-image: url(''); HOVER ?!*/
color: #ef7b0b;
}
ul.main_nav ul {
margin: 0;
padding: 0;
display: none;
}
ul.main_nav ul li {
margin: 0;
padding: 0;
clear: both;
}
ul.main_nav ul li a {
background-image: url('../images/acmenu2_bg.png');
background-repeat: repeat-x;
padding-left: 20px;
font-size: 12px;
font-weight: bold;
}
ul.main_nav ul li a:hover {
color: #dcdcdc;
/* HOVER */
}
ul.main_nav ul li a:active {
background-image: url('../images/acmenu1_bg.png');
background-repeat: repeat-x;
}
ul.main_nav ul ul li a {
background: #f6f6f6;
color: #000;
padding-left: 40px;
border-bottom: 1px solid #e7e7e7;
}
ul.main_nav ul ul li a:hover {
color: #ef7b0b;
text-decoration: underline;
}
JS
$(document).ready(function() {
$('.sidebar-wrapper ul li a').click(function(ev) {
$('.sidebar-wrapper .sub-menu').not($(this).parents('.sub-menu')).slideUp();
$(this).next('.sub-menu').slideToggle();
$('.main_nav ul li a').removeClass('active');
$(this).addClass('active');
ev.stopPropagation();
});
});
My accordion menu example jsFiddle
As you can see I've tried to write the code as simple as possible. There are 2 things I can't handle with:
1st. ) I made a hover background to my sub-menus (only) - when It's clicked sub-sub menu list is showing - I would like to have only sub-menu items to be hovered (with that orange gradient), not sub-sub menu items, because when you click on sub-sub menu item it takes active state from sub-menu item, remove it and assign for yourself. I have a problem fixing that. ?
2nd. ) It's related to sub sub menu items. I would like to have sub-menu item active (covered with orange gradient background) when I have active sub sub menu item clicked (which is orange underline). One more thing, I'd like it to be always collapsed if sub sub menu item is active.
If something is unclear to you or I wrote something wrong please correct me and do not hesitate to ask for more details.
I would really appreciate for your help.
Thank you. Greetings -
Chris
While I definitely applaud the abstraction of your Javascript, which is almost always considered a benefit and a proper coding practice, it appears as though you may be sacrificing control of the elements themselves; this is most likely due to the fact that each of your menus (sub-menu, sub-sub-menu) share the same class ("sub-menu").
In order to gain greater control over your Javascript, it might be worth specifying distinct class names for each of the menu elements:
Sub-Menu (class: sub-menu)
<ul class="sub-menu">
<li><a href='#'>SUB-SUB MENU</a></li>
<li><a href='#'>SUB-SUB MENU</a></li>
<li><a href='#'>SUB-SUB MENU</a></li>
<li><a href='#'>SUB-SUB MENU</a></li>
<li><a href='#'>SUB-SUB MENU</a></li>
<li><a href='#'>SUB-SUB MENU</a></li>
</ul>
Sub-Sub-Menu (class: sub-menu)
<ul class="sub-menu">
<li><a href='#'>SUB-SUB MENU</a></li>
</ul>
By specifying distinct class names, you can determine what to do/not do when a certain element is accessed in the DOM, that is:
<ul class="sub-sub-menu">
<li><a href='#'>SUB-SUB MENU</a></li>
</ul>

Categories

Resources