Make parent menu link toggle submenu link - javascript

I have a menu which I have working fine but I need a small change and that is I need the parent menu to toggle the submenu, currently if you click the parent menu the submenu appears but I need it so when you click the parent menu again it closes the sub menu.
You can see the menu in action here.
and this is the javascript that is for the menu:
$('.dropdown-toggle').click(function() {
$('.dropdown').css('display', 'none'); // Hide submenus when other submenus are clicked
$(this).next('.dropdown').toggle();
});
$(document).click(function(e) {
var target = e.target;
if (!$(target).is('.dropdown-toggle') && !$(target).parents().is('.dropdown-toggle')) {
$('.dropdown').hide();
}
});
This is the menu html
<nav class="main">
<a class="dropdown-toggle" href="#" title="Menu">Menu One</a>
<ul class="dropdown">
<li>Menu Item</li>
<li>Menu</li>
<li>Settings</li>
<li>Search</li>
</ul>
</nav>

Replace this code:
$('.dropdown-toggle').click(function() {
$('.dropdown').css('display', 'none'); // Hide submenus when other submenus are clicked
$(this).next('.dropdown').toggle();
});
With the code below:
$('.dropdown-toggle').click(function() {
var $currentDropdown = $(this).next('.dropdown');
$currentDropdown.siblings('.dropdown').not($currentDropdown).removeClass('toggled');
$currentDropdown.siblings('.dropdown').not($currentDropdown).hide();
$currentDropdown.toggleClass('toggled');
$currentDropdown.toggle();
});
That should do it.

I think this is the simplier way :)
Hope you helped
$(".dropdown").css('display', 'none');
$('.dropdown-toggle').click(function(e) {
if ($(this).next().is(":visible")){
$(this).next().hide();
}else{
$(".dropdown").hide();
$(this).next().show();
}
});
a {
display: block;
}
<script src="https://code.jquery.com/jquery-3.1.0.js"></script><nav class="main">
<nav>
<a class="dropdown-toggle" href="#" title="Menu">Menu One</a>
<ul class="dropdown">
<li>Menu Item</li>
<li>Menu</li>
<li>Settings</li>
<li>Search</li>
</ul>
<a class="dropdown-toggle" href="#" title="Menu">Menu One</a>
<ul class="dropdown">
<li>Menu Item</li>
<li>Menu</li>
<li>Settings</li>
<li>Search</li>
</ul>
</nav>

I think this code will be enough.
$('.dropdown-toggle').click(function() {
$(this).next('.dropdown').toggle();
});
Codepen Example

This can be done easily with Bootstrap:
<li class="submenu">
<i class="la la-user"></i>
<span> Main menue </span>
<span class="menu-arrow"></span>
<ul style="display: none;">
<li>sub menu 1</li>
<li> sub menu 2 </li>
<li> sub menu 3 </li>
</ul>
</li>

Related

Can't open dropdown menu using querySelectorAll

I have a mobile navigation with two dropdown menus. Here is the markup of the nav:
<div id="mobile-menu" class="mobile-menu container fixed">
<ul>
<li>Home</li>
<li class="dropdown">
Articles <i class="bi bi-chevron-down"></i>
<ul class="submenu hidden">
<li>Submenu item 1</li>
<li>Submenu item 2</li>
</ul>
</li>
<li>Contact</li>
<li class="dropdown">
My account <i class="bi bi-chevron-down"></i>
<ul class="submenu hidden">
<li>Dashboard</li>
<li>Profile</li>
</ul>
</li>
</ul>
</div>
The dropdown menus should open/expand when clicked. Originally I grabbed the dropdown and submnenu classes like this:
const mobileDropdown = document.querySelector(".dropdown");
const mobileSubMenu = document.querySelector('.submenu');
and used an eventlistener to toggle the "hidden" class which is just a display:none
mobileDropdown.addEventListener('click', () => {
mobileSubMenu.classList.toggle('hidden');
});
The problem with this is that this will only open the first dropdown menu and I cannot open the second.
When I try to use querySelectorAll instead of just querySelector then i get thiserror:
Uncaught typeError addEventListener is not a function
Here I read that with querySelectorAll I need to use a for or foreach loop.
but i think I'm messing it up. I tried this:
const mobileDropdown = document.querySelectorAll(".dropdown");
const mobileSubMenu = document.querySelector('.submenu');
mobileDropdown.forEach(md => md.addEventListener('click', () => {
mobileSubMenu.classList.toggle('hidden');
}));
Now I don't get an error, I can open the first dropdown menu, but when I try to open the second dropdown menu, the first one opens. What am I doing wrong? Thanks in advance.
The problem in your code is that each mobileDropdown's clickEvent was linked to the first submenu, you should link mobileDropdown's clickEvents to their submenu children like that
document.querySelectorAll(".dropdown").forEach(md => md.addEventListener('click', () => {
md.querySelector(".submenu").classList.toggle('hidden');
}));
.hidden {
visibility: hidden;
}
<div class="mobile-menu container fixed" id="mobile-menu">
<ul>
<li>Home</li>
<li class="dropdown">
Articles <i class="bi bi-chevron-down"></i>
<ul class="submenu hidden">
<li>Submenu item 1</li>
<li>Submenu item 2</li>
</ul>
</li>
<li>Contact</li>
<li class="dropdown">
My account <i class="bi bi-chevron-down"></i>
<ul class="submenu hidden">
<li>Dashboard</li>
<li>Profile</li>
</ul>
</li>
</ul>
</div>
here is a solution. You have to listen to the 'click' event for "submenu" on the element of "dropdown".
const mobileDropdown = document.querySelectorAll(".dropdown");
mobileDropdown.forEach((md) => {
md.addEventListener("click", () => {
const mobileSubMenu = md.querySelector(".submenu");
mobileSubMenu.classList.toggle("hidden");
});
});
mobileSubMenu always the first!

JQuery trouble understanding event order

I am trying to create a Bootstrap dropdown menu with two sub-menus. My problem is that the dropdowns are dynamically created after the document is loaded, and don't respond to how I would normally get them to work.
How I would normally go about it would be
$(document).ready(function(){
addItem(); //adds the first instance of the drop down
$('ul.dropdown-menu [data-toggle=dropdown]').on('click', function(e){
e.stopPropagation();
e.preventDefault();
$(this).siblings().removeClass("open");
$(this).parent().toggleClass("open");
});
});
But this obviously doesn't work for dynamically created content. I saw elsewhere online that this would work for dynamic content;
//still has first instance of dropdown, just later in the doc
$(document).on('click', 'ul.dropdown-menu [data-toggle=dropdown]', function(e){
e.stopPropagation();
e.preventDefault();
$(this).siblings().removeClass("open");
$(this).parent().toggleClass("open");
});
but for the life of me, I can't figure out why this doesn't work. What I'm seeing is that it is adding the open class to the sub-menu, but toggle the parent menu(not stopping propagation?) So, my question is, why doesn't the second one execute as expected, and how can I make it?
List structure for reference:
<div class="dropdown open">
<button id="select0" class="btn new-btn" data-toggle="dropdown" aria-expanded="true">Select Your Item <span class="caret"></span></button>
<ul class="dropdown-menu">
<li><a class="sub" data-toggle="dropdown">Item 1</a>
<ul class="dropdown-menu sub-menu">
<li><a data-def-cost="6">Item 1.1</a></li>
<li><a data-def-cost="8">Item 1.2</a></li>
</ul>
</li>
<li><a class="sub" data-toggle="dropdown">Item 2</a>
<ul class="dropdown-menu sub-menu">
<li><a data-def-cost="5">Item 2.1</a></li>
<li><a data-def-cost="3">Item 2.2</a></li>
</ul>
</li>
<li><a data-plu="xyz" data-def-cost="8.00">Item 3</a></li>
<li><a data-plu="xyz" data-def-cost="8.00">Item 4</a></li>
<li><a data-plu="xyz" data-def-cost="10.00">Item 5</a></li>
<li class="dropdown-header">Other Items</li>
<li><a data-plu="143">Item 6</a></li>
<li><a data-plu="xyz">Item 7</a></li>
<li><a data-plu="xyz">Item 8</a></li>
</ul>
<input type="text" class="hidden" name="input1">
<input type="text" class="hidden" name="otherinput1">
</div>
$(this).siblings() points to an ul element, however, the .open class is supposed to be added to the parent li : http://getbootstrap.com/javascript/#dropdowns-usage.
Via data attributes or JavaScript, the dropdown plugin toggles hidden content (dropdown menus) by toggling the .open class on the parent list item.
Here is a suggestion (inspired by the following code snippet : Multi-Level Dropdowns) :
$(document).ready(function () {
// this variable keeps track of the last open menus
// in order to close them when another link is clicked
// or when the entire dropdown is closed
var open;
$("#my-dropdown").on("hide.bs.dropdown", function () {
if (open) open.removeClass("open");
});
$(".dropdown-submenu > a").on("click", function (e) {
if (open) open.removeClass("open");
open = $(this).parents(".dropdown-submenu");
open.addClass("open");
e.stopPropagation();
e.preventDefault();
});
});
.dropdown-submenu {
position: relative;
}
.dropdown-submenu .dropdown-menu {
top: 0;
left: 100%;
margin-top: -1px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<div class="dropdown" id="my-dropdown">
<button type="button" data-toggle="dropdown">
Dropdown trigger
<span class="caret"></span>
</button>
<ul class="dropdown-menu">
<li>Action 1</li>
<li>Action 2</li>
<li class="dropdown-submenu">
Submenu 1
<ul class="dropdown-menu">
<li>Action 1.1</li>
<li>Action 1.2</li>
</ul>
</li>
<li class="dropdown-submenu">
Submenu 2
<ul class="dropdown-menu">
<li>Action 2.1</li>
<li>Action 2.2</li>
<li class="dropdown-submenu">
Submenu 2.3
<ul class="dropdown-menu">
<li>Action 2.3.1</li>
<li>Action 2.3.2</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
Unsure as to efficiency of my solution, but I rearranged the order a bit, and forced the parent to stay open
$(document).on('click', 'ul.dropdown-menu [data-toggle=dropdown]', function(e){
$(this).siblings().removeClass("open");
$(this).parent().addClass("open");
$(this).parent().parent().parent().addClass("open");
e.stopPropagation();
e.preventDefault();
});
and this solved my issue
use one of these below lines.
$(this).siblings('.dropdown-menu').removeClass('open');
$(this).next('.dropdown-menu').removeClass('open');

Javascript - Bootstrap dropdown on hover open all menu levels of submenu

I already have javascript function that works well with dropdown list items which has just one dropdown-menu, but the problem occurs when I have dropdown list item with two or menu submenu levels, because on hover it opens all menu levels of submenu... Site is live, take a look - http://mile.x3.rs/mile/uram/
JavaScript that works fine with one dropdown-menu level
// MENU HOVER
$(document).ready(function() {
$(".dropdown, .dropdown-active").hover(function() {
$(this).find('.dropdown-menu').stop(true, true).delay(200).fadeIn(500);
}, function() {
$(this).find('.dropdown-menu').stop(true, true).delay(200).fadeOut(500);
});
});
<li class="dropdown">
Partneri <i class="fa fa-angle-down"></i>
<ul class="dropdown-menu" role="menu">
<li>Partner 1
</li>
<li>Partner 2
</li>
<li>Partner 3
</li>
<li>Partner 4
</li>
<li>Partner 5
</li>
<li>Partner 6
</li>
</ul>
</li>
But this
<li class="dropdown">
Reference <i class="fa fa-angle-down"></i>
<ul class="dropdown-menu">
<li class="dropdown dropdown-submenu">
Prehrambena industrija
<ul class="dropdown-menu">
<li class="dropdown dropdown-submenu">
Pivare<i class="fa fa-angle-right"></i>
<ul class="dropdown-menu">
<li>Option 1
</li>
<li>Option 2
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
You just need to edit your jquery code to be like that .
$(document).ready(function() {
$(".dropdown, .dropdown-active").hover(function() {
$(this).find('.dropdown-menu').eq(0).stop(true, true).delay(200).fadeIn(500);
}, function() {
$(this).find('.dropdown-menu').eq(0).stop(true, true).delay(200).fadeOut(500);
});
});
so the script will only run on the first element only .
https://jsfiddle.net/IA7medd/63Lfgjnm/
You need to select only direct descendants of an element using jQuery's find().
Try this and notice $(this).find('> .dropdown-menu'):
$(document).ready(function() {
$(".dropdown, .dropdown-active").hover(function() {
$(this).find('> .dropdown-menu').stop(true, true).delay(200).fadeIn(500);
}, function() {
$(this).find('> .dropdown-menu').stop(true, true).delay(200).fadeOut(500);
});
});
Here is the full demo:
$(document).ready(function() {
$(".dropdown, .dropdown-active").hover(function() {
$(this).find('> .dropdown-menu').stop(true, true).delay(200).fadeIn(500);
}, function() {
$(this).find('> .dropdown-menu').stop(true, true).delay(200).fadeOut(500);
});
});
<script src="//cdn.bootcss.com/jquery/2.1.0/jquery.js"></script>
<script src="//cdn.bootcss.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
<link href="//cdn.bootcss.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet" />
<link href="//cdn.bootcss.com/bootstrap/3.0.0/css/bootstrap-theme.min.css" rel="stylesheet" />
<link href="//cdn.bootcss.com/bootstrap/3.0.0/css/bootstrap-theme.css" rel="stylesheet" />
<div class="container">
<header>
<li class="dropdown">
Reference <i class="fa fa-angle-down"></i>
<ul class="dropdown-menu">
<li class="dropdown dropdown-submenu">
Prehrambena industrija
<ul class="dropdown-menu">
<li class="dropdown dropdown-submenu">
Pivare<i class="fa fa-angle-right"></i>
<ul class="dropdown-menu">
<li>Option 1
</li>
<li>Option 2
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</header>
</div>
You are using .find which traverses all descendants of the menu. You only need the "next level" per your comment so you should use .children as that will not traverse to the next level.
$(document).ready(function() {
$(".dropdown, .dropdown-active").hover(function() {
$(this).children('.dropdown-menu').stop(true, true).delay(200).fadeIn(500);
}, function() {
$(this).children('.dropdown-menu').stop(true, true).delay(200).fadeOut(500);
});
});
Reference: https://api.jquery.com/children/

When User Open One DropDown Close Other DropDowns

I Want When User Click On One DropDown All Other open DropDown Get Closed . I looked for answer in google but that is not working for my dropdown i know it's simple but i am unable to this pls help me !!
<div class="hh_drop_down">
<ul class="hh_main">
<li class="hh_main_menu">
Chemicals
<ul class="hh_inner">
<li>Additives / Boosters</li>
<li>Anti-Allergen</li>
<li>Concrete</li>
</ul>
</li>
<li class="hh_main_menu" >
<a class="hh_sf" href="#">Equipment</a>
<ul class="hh_inner">
<li>Deodorization</li>
<li>Duct Cleaning Equipment</li>
<li>Hard Surface</li>
</ul>
</li>
<li class="hh_main_menu" >
<a class="hh_sf" href="#">Accessories</a>
<ul class="hh_inner">
<li>Bonnets/Pads</li>
<li>Brush/Rake/Sponge</li>
<li>Carpet Rakes</li>
</ul>
</li>
</ul>
</div>
And jquery i am using in this :
<script>
$(document).ready(function(){
$(".hh_main").on('click' , '.hh_sf' , function(event){
event.preventDefault();
if($(this).next().hasClass('hh_inner')) {
$(this).next().slideToggle();
}
});
});
</script>
Try this:
HTML:
<div class="hh_drop_down">
<ul class="hh_main">
<li class="hh_main_menu">
Chemicals
<ul class="hh_inner expanded">
<li>Additives / Boosters</li>
<li>Anti-Allergen</li>
<li>Concrete</li>
</ul>
</li>
<li class="hh_main_menu">
<a class="hh_sf" href="#">Equipment</a>
<ul class="hh_inner expanded">
<li>Deodorization</li>
<li>Duct Cleaning Equipment</li>
<li>Hard Surface</li>
</ul>
</li>
<li class="hh_main_menu">
<a class="hh_sf" href="#">Accessories</a>
<ul class="hh_inner expanded">
<li>Bonnets/Pads</li>
<li>Brush/Rake/Sponge</li>
<li>Carpet Rakes</li>
</ul>
</li>
</ul>
</div>
JQuery:
<script>
$(document).ready(function () {
$(".hh_sf").next().addClass("collapsed").slideUp();
$(".hh_main").on('click', '.hh_sf', function (event) {
event.preventDefault();
var currentClass = $(this).next().prop('class');
if (currentClass == "hh_inner expanded") {
$(this).next().removeClass("expanded");
$(this).next().addClass("collapsed");
$(this).next().slideUp();
} else {
$(".expanded").slideUp().addClass("collapsed").removeClass("expanded");
$(this).next().removeClass("collapsed");
$(this).next().addClass("expanded");
$(this).next().slideDown();
}
});
});
</script>
JsFiddle
I opened dropmenu with show and hide and made event on li you can use different way
try this :
JQuery :
$(".hh_main_menu").click(
function(){
$(this).next(".hh_inner").toggle();
if($(this).siblings(".hh_main_menu").children(".hh_inner").css("display")=="block")
{
$(this).siblings(".hh_main_menu").children(".hh_inner").hide();
}
} );

click blank area go back to selected section

<li class="list ">A
<ul class="names">
<li class="list">1
</li>
<li class="list">2
</li>
</ul>
</li>
<li class="list ">B
<ul class="names selected">
<li class="list selected">1
</li>
<li class="list">2
</li>
<li class="list">3
</li>
<li class="list">4
</li>
</ul>
</li>
<li class="list ">C
<ul class="names">
<li class="list">1
</li>
<li class="list">2
</li>
<li class="list">3
</li>
<li class="list">4
</li>
</ul>
</li>
$('.list').click(function () {
var that = this;
$('.list').each(function () {
if (that == this) return true; //continue
$('.names:not(:hidden)', this).slideToggle();
});
$('ul.names', this).slideToggle();
})
ul.names{display: none;}
li.list{
width:150px;
background:#A9FF7A;
}
ul.names {
width:150px;
background:#A9FF7A;
}
ul.selected{
display: block;
}
li.selected{
background:red;
}
online Sample: http://jsfiddle.net/gyYyd/
B's submenu 1 is highlighted. If I click on menu A or C, then A or C section will be opened, but how do I click PAGE BLANK area (outside of the background color) to go back to B section (to open B section)
Thanks in advance
You can capture clicks on the document object and trigger a click on the required list item.
$(document).click(function() {
var selected = $('.selected:first');
if(!selected.closest('ul.names').is(':visible')) {
selected.closest('.list').trigger('click');
}
});
Also, make sure to return false from your current list item click handler - so that normal clicks on list items don't propagate to the above handler.
DEMO: http://jsfiddle.net/gyYyd/2/

Categories

Resources