How to prevent opening child sub menu in nested menu - javascript

I like to prevent opening nested child categories when you open sub categori
for example i have nested tree like this
Test 1
Sub cat 1/1
Sub Sub cat 1/1
Sub cat 1/2
Test 2
Sub cat 2/1
Sub cat 2/2
When i click Test 1 is opening all nested categories how to prevent opening Sub Sub cat 1/1 ?
PS. system wont let me post question because is mostly code , but i dont see reason to spam random text when i can examplain question in 2-3 lines
$('ul li').click(function(e){
e.preventDefault();
$('.menu-wrapper ul', this).toggleClass('menu-close')
$(this).toggleClass('menu-open')
})
ul{
padding: 0px;
list-style: none;
}
ul li{
padding: 5px 0;
}
ul li a{
width: 100%;
display: inline-block;
}
.menu-close{
display: none;
}
/* Main menu */
.menu-main{
width: 250px;
}
.menu-main li{
position: relative;
}
.has-menu:before{
content: '+';
position: absolute;
right: 0;
}
.has-menu.menu-open:before{
content: '-' !important;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul class="menu-main">
<li class="has-menu">
Test 1
<div class="menu-wrapper">
<ul class="menu-child menu-close">
<li class="has-menu">
Sub cat 1/1
<div class="menu-wrapper">
<ul class="menu-subchild menu-close">
<li>
Sub Sub cat 1/1
</li>
</ul>
</div>
</li>
</ul>
<ul class="menu-child menu-close">
<li class="">
Sub cat 1/2
</li>
</ul>
</div>
</li>
</ul>

Is this what you want?
$("li").click(function (e) {
e.preventDefault();
e.stopPropagation();
$(this).children("div").children("ul").toggleClass("menu-close");
$(this).toggleClass("menu-open");
});
ul{
padding: 0px;
list-style: none;
}
ul li{
padding: 5px 0;
}
ul li a{
width: 100%;
display: inline-block;
}
.menu-close{
display: none;
/*background-color:red;*/
}
/* Main menu */
.menu-main{
width: 250px;
}
.menu-main li{
position: relative;
}
.has-menu:before{
content: '+';
position: absolute;
right: 0;
}
.has-menu.menu-open:before{
content: '-' !important;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul class="menu-main">
<li class="has-menu">
Test 1
<div class="menu-wrapper">
<ul class="menu-child menu-close">
<li class="has-menu">
Sub cat 1/1
<div class="menu-wrapper">
<ul class="menu-subchild menu-close">
<li>
Sub Sub cat 1/1
</li>
</ul>
</div>
</li>
</ul>
<ul class="menu-child menu-close">
<li class="">
Sub cat 1/2
</li>
</ul>
</div>
</li>
</ul>

Use the child-selector:
$('ul li').click(function(e){
e.stopPropagation();
$('> .menu-wrapper > ul', this).toggleClass('menu-close');
$(this).toggleClass('menu-open');
});
(Updated)

Related

toggleClass triggering twice when resizing browser window

I'm currently in the middle of creating a responsive navigation. I've managed to finish and trying to fix an issue. Whenever I tried resizing the browser, it seems the toggleClass seems to be triggering multiple times. If refresh the browser it works OK, but after resizing it seems to trigger a couple of times in one click.
Here is the code that I have been working on.
JSFiddle - https://jsfiddle.net/kvpyzbxr/1/
<header>
<ul class="navigation secondary-navigation">
<li>
Schools
</li>
<li>
Faculty
</li>
<li>
Research
</li>
<li>
Contact Us
</li>
</ul>
<ul class="navigation primary-navigation">
<li>
Programs
<ul>
<li>Degree Programs</li>
<li>Master in Business Administration</li>
<li>Executive Master in Business Administration</li>
<li>Master in Entrepreneurship</li>
<li>Master of Science and Innovation and Business</li>
<li>Master in Development Management</li>
</ul>
</li>
<li>
Admissions
<ul>
<li>How to Apply</li>
<li>Application Form</li>
<li>Scholarship and Financial Aid</li>
</ul>
</li>
<li>
About Us
<ul>
<li>Why AIM</li>
<li>Leadership</li>
<li>Network and Alliances</li>
<li>Our Brand Story</li>
</ul>
</li>
<li>
News
</li>
<li>
Alumni
<ul>
<li>AIM Leader Magazine</li>
<li>My AIM Connect</li>
<li>Triple A Awardees</li>
</ul>
</li>
<li>
Give
<ul>
<li>Make A Gift</li>
</ul>
</li>
</ul>
</header>
<script>
$(document).ready(function() {
function detectMobile() {
if ($(window).width() < 1080) {
$('header').addClass('mobile');
$('.secondary-navigation').insertAfter('.primary-navigation');
}
else {
$('header').removeClass('mobile');
$('.secondary-navigation').insertBefore('.primary-navigation');
}
$('.navigation li').on('click', function() {
console.log('open');
$(this).toggleClass('expand-menu');
})
}
detectMobile();
$(window).resize(function() {
detectMobile();
})
})
</script>
header {
max-width: 1336px;
margin: 0 auto;
}
header .navigation {
padding: 10px 0;
clear: both;
}
header .navigation li {
padding: 10px;
display: inline-block;
position: relative;
font-family: 'Arial', sans-serif;
background-color: #272041;
color: #fff;
float: left;
}
header .navigation li a {
color: #fff;
}
header .navigation li ul {
position: absolute;
top: 0;
left: 0;
padding-top: 30px;
display: none;
}
header .navigation li ul li {
background-color: #231d39;
color: #95939e;
}
header .navigation li:hover ul {
display: block;
}
header.mobile .navigation li {
display: block;
float: none;
}
header.mobile .navigation li ul {
position: static;
display: none;
height: 0;
}
header.mobile .navigation li.expand-menu ul {
height: initial;
display: block;
}
That's because you add the click-event several times. Every time detectMobile() is called you bind a click event to $('.navigation li'). So just move
$('.navigation li').on('click', function() {
console.log('open');
$(this).toggleClass('expand-menu');
})
outside of your detectMobile() function.

Javascript Toggle : Hide div on click of anywhere

I have two divs. When I click on 3 dots , then the div is appearing and on clicking the same 3 dots , same div is disappearing. But I want to hide the div, even if I click anywhere in the document.
There are two circles. When I click on one circle, then a div is shown and when I click on another circle, then the opened div is closing and related div is opening but when I click anywhere on the document, then none of the div are closing.
$("#discussion_declined , #discussion_pending").click(function() {
var relatedDiv = $(this).closest('.panel').find('.discussion_edit_div');
relatedDiv.toggle("fast");
$('.discussion_edit_div').not(relatedDiv).hide('fast');
});
.discussion_small_round_div {
width: 25px;
height: 25px;
border-radius: 50%;
position: relative;
background: #2d3446;
bottom: 9px;
left: 15px;
float: right;
}
.discussion_small_round_div:after {
content: '\2807';
font-size: 1.5em;
color: white;
position: absolute;
left: 9px;
top: 1px;
}
.discussion_edit_div {
background: #FFFFFF;
display: none;
position: absolute;
right: 35px;
border: thin #ced0d1 solid;
z-index: 1001;
width: 150px;
box-shadow: 0px 3px 3px #ccc;
}
ul li {
padding: 5px 15px;
list-style-type: none;
color: #838383;
}
ul li:hover {
background: #eeeded;
cursor: pointer;
}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<div class="panel discussion_panel_div no_background no_box_shadow" style="position: relative;">
<div class="panel-heading no_border_radius bg-dark set_padding_0">
<div class="discussion_small_round_div pull-right cursor_pointer" id="discussion_declined"></div>
</div>
<div class="discussion_edit_div">
<ul>
<li> <span class="glyphicon glyphicon-trash"></span> Replicate</li>
<li><span class="glyphicon glyphicon-trash"></span> Delete</li>
<li><span class="glyphicon glyphicon-ban-circle"></span> Deactivate</li>
</ul>
</div>
</div>
<div class="panel discussion_panel_div no_background no_box_shadow" style="position: relative;">
<div class="panel-heading no_border_radius bg-dark set_padding_0">
<div class="discussion_small_round_div pull-right cursor_pointer" id="discussion_pending"></div>
</div>
<div class="discussion_edit_div">
<ul>
<li> <span class="glyphicon glyphicon-trash"></span> Replicate</li>
<li><span class="glyphicon glyphicon-trash"></span> Delete</li>
<li><span class="glyphicon glyphicon-ban-circle"></span> Deactivate</li>
</ul>
</div>
</div>
Praveen's answer is nice but you can also achieve the same without tweaking your HTML.
Just add this to your jQuery:
$(window).click(function() {
//Hide the menus if visible
$('.discussion_edit_div').hide('fast');
});
$("#discussion_declined , #discussion_pending").click(function(e) {
e.stopPropagation();
var relatedDiv = $(this).closest('.panel').find('.discussion_edit_div');
relatedDiv.toggle("fast");
$('.discussion_edit_div').not(relatedDiv).hide('fast');
});
And your are good to go.
This achieves one more thing which is that once you have opened one ul, then you can directly toggle to another ul by clicking once. In Praveen's answer you have to click twice in order to open the other ul.
Check the link:https://jsfiddle.net/zfqqqr1c/1/
How Bootstrap handles this is interesting. They have a mask, and the only thing you can click is the mask or the items in the menu.
$(function () {
$(".mask").hide();
$("nav > ul > li > a").click(function () {
$(this).closest("li").addClass("open");
$(".mask").show();
return false;
});
$(".mask").click(function () {
$(this).hide();
$(".open").removeClass("open");
});
});
* {font-family: 'Segoe UI'; margin: 0; padding: 0; list-style: none; line-height: 1; box-sizing: border-box;}
body {background-color: #f5f5f5;}
a {text-decoration: none; color: inherit;}
.mask {position: fixed; top: 0; bottom: 0; right: 0; left: 0; z-index: 8;}
nav > ul > li {display: inline-block; position: relative; width: 30%;}
nav > ul > li a {display: block; padding: 5px; border: 1px solid #ccc;}
nav > ul ul {position: absolute; left: 0; right: 0; z-index: 9; display: none;}
nav > ul > li.open > ul {display: block;}
<script src="https://code.jquery.com/jquery-2.2.4.js"></script>
<div class="mask"></div>
<nav>
<ul>
<li>
Main Item 1
<ul>
<li>Sub Item 1</li>
<li>Sub Item 2</li>
<li>Sub Item 3</li>
<li>Sub Item 4</li>
<li>Sub Item 5</li>
</ul>
</li>
<li>
Main Item 2
<ul>
<li>Sub Item 1</li>
<li>Sub Item 2</li>
<li>Sub Item 3</li>
<li>Sub Item 4</li>
<li>Sub Item 5</li>
</ul>
</li>
<li>
Main Item 3
<ul>
<li>Sub Item 1</li>
<li>Sub Item 2</li>
<li>Sub Item 3</li>
<li>Sub Item 4</li>
<li>Sub Item 5</li>
</ul>
</li>
</ul>
</nav>

How can i make my jQuery code work on all elements

I have this accordion menu but it only works on the first ul. How do I get it to work on all ul like this? If you could explain what I'm doing wrong so I know in the future that would be great.
Also, how do I get it so that the link toggles between two classes, right and down each time it is clicked? It also has the class turq-font on it. I want the right to be removed and replaced with down when the link is clicked and the menu is showing. Heres my code:
$(function() {
$("#show-menu").click(function() {
$("#sub-menu-acc").toggleClass("active-menu", 1000);
});
});
.active-menu {
display: block !important;
}
.admin-area ul li {
margin: 6px 0px;
}
.admin-right-menu ul li a {
color: black;
text-decoration: none;
}
.admin-area ul {
list-style: none;
margin-bottom: 20px;
}
.admin-area ul li ul {
display: none;
padding-left: 20px;
margin-bottom: 0px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="admin-area">
<div class="admin-right-menu">
<ul>
<li>Stats >
<ul id="sub-menu-acc">
<li>Business Stats
</li>
<li>Affiliate stats
</li>
</ul>
</li>
<li>Reports >
<ul id="sub-menu-acc">
<li>Global
</li>
<li>Sales
</li>
<li>Sales trends
</li>
</ul>
</li>
</ul>
</div></div>
The issue is due to your use of repeated id attributes; they should be unique within a document. Convert your code to use classes instead.
Also note that you should use the this keyword to traverse the DOM to find the ul related to the clicked a element, and the addition of right down in a toggleClass() call. Try this:
$(function() {
$(".show-menu").click(function(e) {
e.preventDefault(); // stop the '#' of the clicked a appearing in the URL
$(this).toggleClass('right down').next(".sub-menu-acc").toggleClass("active-menu");
});
});
.active-menu {
display: block !important;
}
.admin-area ul li {
margin: 6px 0px;
}
.admin-right-menu ul li a {
color: black;
text-decoration: none;
}
.admin-area ul {
list-style: none;
margin-bottom: 20px;
}
.admin-area ul li ul {
display: none;
padding-left: 20px;
margin-bottom: 0px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="admin-area">
<ul>
<li>
Stats >
<ul class="sub-menu-acc">
<li>
Business Stats
</li>
<li>
Affiliate stats
</li>
</ul>
</li>
<li>
Reports >
<ul class="sub-menu-acc">
<li>
Global
</li>
<li>
Sales
</li>
<li>
Sales trends
</li>
</ul>
</li>
</ul>
</div>

Custom CSS Navigation dropdown

Currently on my site when I have too many links, the link falls down below the navigation. See my example: https://jsfiddle.net/cn6z13n1/
Is it possible instead to have a More Links list item at the far right which will have a dropdown populated with links?
.toolkit_nav {
background:#dfdfdf;
width:100%;
height:40px;
padding:0;
}
.toolkit_nav ul {
margin:0;
}
.toolkit_nav ul .page_item {
display:inline-block;
line-height:40px;
list-style-type:none;
margin:0px;
padding:0 20px;
}
.toolkit_nav ul .page_item:first-child {
margin-left:0;
padding-left:0;
}
.page_item:hover, .current_page_item {
background:grey;
}
.page_item a {
color:black;
font-size: 0.9em;
font-weight: 400;
text-decoration:none;
}
<nav class="toolkit_nav">
<div class="row">
<div class="medium-12 columns">
<ul>
<li class="page_item page-item-1035 current_page_item">Introduction</li>
<li class="page_item page-item-1039">Digital Landscapes</li>
<li class="page_item page-item-1039">Link 4</li>
<li class="page_item page-item-1039">Link 3</li>
<li class="page_item page-item-1039">Link 2</li>
<li class="page_item page-item-1039">Link 1</li>
<li class="page_item page-item-1039">Link 5</li>
</ul>
</div>
</div>
</nav>
You would need to do this in js i suggest something like this
get the width of the row (max width for nav)
loop through the li elements and sum up there width (+ remember to add the width of a "more" element here
when sum of width > width of nav element hide the elements
add js to your "more" button which shows the hidden elements
Following code is not tested but should give you an idea:
var maxWidth = $('#nav').width();
var moreWidth = $('#more').width(); // li "more" element
var sumWidth = moreWidth;
$('#nav li').each(function() {
sumWidth += $(this).width();
if(sumWidth > maxWidth) {
$(this).addClass('hide'); // add css for hide class
}
});
$('#more').on('click', function() {
$('#nav .hide').fadeIn(100);
// You will need more code here to place it correctly, maybe append the elements in an container
});
Here an example with your fiddle:
https://jsfiddle.net/cn6z13n1/3/
Note: this is just a rough draft, you might to calc paddings etc. to make this work rly good
Edit: updated example with $(window).resize() function
https://jsfiddle.net/cn6z13n1/6/
You'll need to change you HTML slightly but this will work.
.toolkit_nav {
background: #dfdfdf;
width: 100%;
height: 40px;
padding: 0;
}
.toolkit_nav ul {
margin: 0;
}
.toolkit_nav ul .page_item {
display: inline-block;
line-height: 40px;
list-style-type: none;
margin: 0px;
padding: 0 20px;
}
.toolkit_nav ul .page_item:first-child {
margin-left: 0;
padding-left: 0;
}
.page_item:hover,
.current_page_item {
background: grey;
}
.page_item a {
color: black;
font-size: 0.9em;
font-weight: 400;
text-decoration: none;
}
/* NEW STUFF */
.sub-nav,
.sub-nav li {
box-sizing: border-box;
}
.more {
position: relative;
}
.more>ul {
display: none;
position: absolute;
left: 0;
top: 100%;
padding: 0
}
.more:hover>ul {
display: block;
}
.more>ul>li {
display: block;
width: 100%;
clear: both;
text-align: center;
}
.toolkit_nav ul.sub-nav .page_item:first-child {
padding: 0 20px;
}
<nav class="toolkit_nav">
<div class="row">
<div class="medium-12 columns">
<ul>
<li class="page_item page-item-1035 current_page_item">Introduction
</li>
<li class="page_item page-item-1039">Digital Landscapes
</li>
<li class="page_item page-item-1039">Link 4
</li>
<li class="page_item page-item-1039">Link 3
</li>
<li class="page_item page-item-1039">Link 2
</li>
<li class="page_item page-item-1039 more">More...
<ul class="sub-nav">
<li class="page_item page-item-1039">Link 1
</li>
<li class="page_item page-item-1039">Link 5
</li>
</ul>
</li>
</ul>
</div>
</div>
</nav>

Accordion with multiple links

I'm taking this CSS-Tricks article and converting it to a UL > LI instead of a DT > DD approach. I just want the pink box to reveal the sub-links when clicked.
For some reason though I cannot get it working. I've created a jsFiddle of it here (click the pink box):
//Accordion
(function($) {
var allPanels = $('ul.sub-level').hide();
$('.click-me').click(function() {
allPanels.slideUp();
alert('slide up');
// Problem line
$(this).parent().next().slideDown();
return false;
});
})(jQuery);
ul { list-style: none; padding:0; margin:0; width: 400px; }
ul li { position:relative; background: #fafafa; margin-bottom:3px; height:20px; }
ul li > ul { margin-left: 30px; background: #e3e3e3; }
.click-me { display:block; width: 20px; height: 20px; position: absolute; top:0; right:0; background: #e4f; cursor: pointer;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li>Link somewhere</li>
<li>Link somewhere</li>
<li class="test">
Link somewhere
<!-- I want to reveal accordion using this span tag -->
<span class="click-me"></span>
<!-- /end -->
<ul class="sub-level">
<li>Link 1</li>
<li>Link 2</li>
<li>Link 3</li>
<li>Link 4</li>
</ul>
<li>Link somewhere</li>
</li>
</ul>
http://jsfiddle.net/ndczc728/1/
The problem line is this (I think):
// Problem line
$(this).parent().next().slideDown();
Anyone?
You don't need to use parent. Also you have to remove fixed height from li elements:
//Accordion
(function($) {
var allPanels = $('ul.sub-level').hide();
$('.click-me').click(function() {
allPanels.slideUp();
// Problem line
$(this).next().slideDown();
return false;
});
})(jQuery);
ul {
list-style: none;
padding: 0;
margin: 0;
width: 400px;
}
ul li {
position: relative;
background: #fafafa;
margin-bottom: 3px;
}
ul li > ul {
margin-left: 30px;
background: #e3e3e3;
}
.click-me {
display: block;
width: 20px;
height: 20px;
position: absolute;
top: 0;
right: 0;
background: #e4f;
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li>Link somewhere
</li>
<li>Link somewhere
</li>
<li class="test">
Link somewhere
<!-- I want to reveal accordion using this span tag -->
<span class="click-me"></span>
<!-- /end -->
<ul class="sub-level">
<li>Link 1
</li>
<li>Link 2
</li>
<li>Link 3
</li>
<li>Link 4
</li>
</ul>
<li>Link somewhere
</li>
</li>
</ul>

Categories