Javascript toggle menu -issue with sub-menues - javascript

I'm working on a responsive menu for a quite complex website. The horizontal menu collapses to a vertical one for smaller screens and I've used javascript to toggle the sub-menu items open/closed when clicked.The product section is the only sub-menu that has another sub-menu a level deeper and it's not quite working for it as only the third level items close again on click, but not the parent item.
Here's the code
<nav id="navigation">
<ul id="nav-list">
<li class="nav-list_item nav-about">About us
<div id="about-drop" class="dropdown">
<ul>
<li>....</li>
<li>....</li>
</ul>
</div>
</li>
<li class="nav-list_item nav-products">Products
<div id="prod-drop" class="dropdown">
<div id="subnav_products1" class='targetDiv'>
<div class="drop-section">
<h5 class="nav-title">Purpose</h5>
<ul>
<li>...</li>
<li>...</li>
</ul>
</div>
<div class="drop-section">
<h5 class="nav-title">Series</h5>
ul>
<li>...</li>
<li>...</li>
</ul>
</div>
</div>
</div>
</li>
</ul>
And the javascript :
if ($(window).width() <= 760) {
$('li.nav-list_item').click(function(){
$('li.nav-list_item').not(this).find('ul').hide();
$(this).find('ul').toggle();
});
}
I think it might be because when the parent item (products) is clicked the ul close as specified in the javascript but the nav-title items (Purpose/ Series) are still open and can't be closed. I've been trying to work this out but just can't get it to work that when the title items are being clicked the third level menu closes and when the parent item(Products) is clicked the title items close. Any suggestions?

First off, I do not know how to debug your code as what you provided is not a working example. Head over to Codepen and create a pen where we can reproduce the issues.
Apart from that it is possible to implement the navigation with css only using hidden radio buttons or active states.

$('li.nav-list_item a, .nav-title').on('click', function(e){
e.preventDefault();
var el = $(this);
el.parent().siblings().find('> .dropdown:visible, > ul:visible').toggle();
el.parent().find('> .dropdown, > ul').toggle();
});
#nav-list .nav-list_item {
display: block;
}
#nav-list .nav-list_item .dropdown{
display: none;
}
#nav-list .nav-list_item .dropdown .drop-section ul {
display:none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<nav id="navigation">
<ul id="nav-list">
<li class="nav-list_item nav-about">About us
<div id="about-drop" class="dropdown">
<ul>
<li>....</li>
<li>....</li>
</ul>
</div>
</li>
<li class="nav-list_item nav-products">Products
<div id="prod-drop" class="dropdown">
<div id="subnav_products1" class='targetDiv'>
<div class="drop-section">
<h5 class="nav-title">Purpose</h5>
<ul>
<li>...</li>
<li>...</li>
</ul>
</div>
<div class="drop-section">
<h5 class="nav-title">Series</h5>
<ul>
<li>...</li>
<li>...</li>
</ul>
</div>
</div>
</div>
</li>
</ul>
I added Fiddle for you. Also next time better add fiddle for other developer to help you more quickly.

Related

Add class to a div if another div has a class

I did a lot of searching and read dozens of questions and answers on this topic and wrote the following code but it won't work for some reason. I'm looking for help troubleshooting this.
This is what I want to happen:
When the user hovers over a menu item, a dropdown appears.
Then the entire header (currently has the ID #header) gets a new class (.header-new-class)
I found that when they hover over a menu item (li), the site automatically adds the class "open" to the menu item (the menu item already has the class .menu-item)
So my logic is, when the menu item has the class "open", it adds the class "header-new-class" to the div with the ID #header
This is a very cleaned up version of the HTML:
<div ID="header">
<div>
<div>
<div>
<div>
<div>
<nav>
<nav>
<div>
<div>
<ul>
<li class="menu-item open">
</li>
</ul>
</div>
</div>
</nav>
</nav>
</div>
</div>
</div>
</div>
</div>
</div>
This is the code I wrote:
$(document).ready(function(jQuery) {
if ($('.menu-item').hasClass('open')) {
$('#header').addClass('header-new-class');
}
});
It's not working. What am I doing wrong?
Thanks in advance.
if you want to add a class on the header when the mouse is on the menu item, do it like this,
if you also want to remove the class then use the commented code below.
if you have questions, feel free to ask
$(document).ready(function(){
$('.menu-item').on('mouseover',function(){
/*$('.menu-item').removeClass('open');
$(this).addClass("open");*/
if($(this).hasClass('open')){
$('#header').addClass('yourNewClass');
}else{
$('#header').removeClass('yourNewClass');
}
});
/*$('.menu-item').on('mouseleave',function(){
$('.menu-item').removeClass('open');
$('#header').removeClass('yourNewClass');
});*/
});
.yourNewClass .menu-item.open {color: red;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div ID="header">
<div>
<div>
<div>
<div>
<div>
<nav>
<nav>
<div>
<div>
<ul>
<li class="menu-item open">
item 1
</li>
<li class="menu-item">
item 2
</li>
<li class="menu-item">
item 3
</li>
</ul>
</div>
</div>
</nav>
</nav>
</div>
</div>
</div>
</div>
</div>
</div>
You can use same event many times. So, this is achievable with normal .hover.
$(document).ready(function(){
$('.menu-item').hover(function(){
$('#header').addClass('header-new-class');
},function(){
/* function to remove class when hovering is over */
})
If you absolutely need to check if the class open is present you can do it inside the hover function.
You can also use mouseenter and mouseleave
$(document).on({
mouseenter: function () {
//stuff to do on mouse enter
},
mouseleave: function () {
//stuff to do on mouse leave
}
}, ".selector");
Why you are set class for hover via jquery. CSS have functionality of :hover which give the same effect that you want.
#header:hover{
background-color : lightBlue;
}
.menu-item:hover{
color: blue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div ID="header">
<div>
<div>
<div>
<div>
<div>
<nav>
<nav>
<div>
<div>
<ul>
<li class="menu-item">
Sample Link 1
</li>
<li class="menu-item">
Sample Link 2
</li>
<li class="menu-item">
Sample Link 3
</li>
</ul>
</div>
</div>
</nav>
</nav>
</div>
</div>
</div>
</div>
</div>
</div>

open one level deep sub-menu, only, on each click using jquery OR javascript

The issue I am having is:
when I click on "menu2", it is showing me sub-menu and all options of sub-menu.
Expected result:
click on "menu2" should open "sub-menu2" only and NO "sub-menu2" options.
click on ""sub-menu2" should open all it's children.
I see there are some question on related to this one but I did not find any question similar to mine.
If you can suggest a way to do this in pure JS/ES that would be great. Currently I am using jQuery.
$('.container > ul > li').on('click', function(){
$('ul',this).toggle(200);
})
div.container > ul ul{
display:none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<ul>
<li>menu1
<ul>
<li>testA</li>
<li>testB</li>
<li>testC</li>
</ul>
</li>
<li>menu2
<ul>
<li>
sub-menu2
<ul>
<li>issue1</li>
<li>issue2</li>
<li>issue3</li>
</u1>
</li>
</ul>
</li>
</ul>
</div>
YOu just need to use your selector a bit different way, and its done, if need something else, pls let me know
$('.container li').on('click', function(e) {
var ckeckChildVisiblity = $(this).find('>ul').is(':visible');
if (!ckeckChildVisiblity) {
$(this).find('>ul').slideDown();
return false;
} else {
$(this).find('>ul').slideUp();
return false;
}
})
div.container > ul ul{
display:none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<ul>
<li>menu1
<ul>
<li>testA</li>
<li>testB</li>
<li>testC</li>
</ul>
</li>
<li>menu2
<ul>
<li>
sub-menu2
<ul>
<li>issue1</li>
<li>issue2</li>
<li>issue3</li>
</u1>
</li>
</ul>
</li>
</ul>
</div>
This can be done using toggling immediate children and stop event propagation.
$('.container li').on('click', function(event){
$(this).children("ul").toggle(200)
event.stopPropagation()
})
.menu ul {
display:none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<ul>
<li class ="menu">menu1
<ul>
<li>testA</li>
<li>testB</li>
<li>testC</li>
</ul>
</li>
<li class ="menu">menu2
<ul>
<li>
sub-menu2
<ul>
<li>issue1</li>
<li>issue2</li>
<li>issue3</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>

jQuery, toggle menu item

I have the following nav menu.
If I click h1, t1, t2, t3 need to toggle (hide or show), other things stay as it is.
If I click h3, t6, t7, t8 need to toggle, other things stay.
Basically, h1, h2, h3 is the header and rest is children.
$(document).ready(function() {
/* In mobile menu, heading click, toggle sub */
$('.slicknav_nav li.heading').click(function() {
//$(this).find('ul').slideToggle();
$('.slicknav_nav li:not(.heading)').toggle();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li class="heading">h1</li>
<li class="first">t1</li>
<li class="">t2</li>
<li class="">t3</li>
<li class="heading">h2</li>
<li class="first">t4</li>
<li class="">t5</li>
<li class="heading">h3</li>
<li class="first">t6</li>
<li class="">t7</li>
<li class="">t8</li>
</ul>
I have made some code. Obviously, it toggles other peer as well. Is it a way to only toggle the current item's "children"?
You can use nextUntil of jQuery method like below.
$(this).nextUntil(".heading").toggle();
Example:
$(document).ready(function() {
/* In mobile menu, heading click, toggle sub */
$('.slicknav_nav li.heading').click(function() {
$(this).nextUntil(".heading").toggle();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="slicknav_nav">
<li class="heading">h1</li>
<li class="first">t1</li>
<li class="">t2</li>
<li class="">t3</li>
<li class="heading">h2</li>
<li class="first">t4</li>
<li class="">t5</li>
<li class="heading">h3</li>
<li class="first">t6</li>
<li class="">t7</li>
<li class="">t8</li>
</ul>
One thought would be to wrap each heading group in a div, then wrap the children in another div inside that one. Could do something like this for layout:
<ul>
<div class="headingContainer">
<li class="heading">h1</li>
<div class="childContainer">
<li class="first">t1</li>
<li class="">t2</li>
<li class="">t3</li>
</div>
</div>
<div class="headingContainer">
<li class="heading">h2</li>
<div class="childContainer">
<li class="first">t4</li>
<li class="">t5</li>
</div>
</div>
<div class="headingContainer">
<li class="heading">h3</li>
<div class="childContainer">
<li class="first">t6</li>
<li class="">t7</li>
<li class="">t8</li>
</div>
</div>
</ul>
Then, in your jQuery, you could use the .siblings() selector to select the sibling div in the dom. Run toggleClass("heading") on the selection and that should do the trick if I'm understanding this correctly.

Mobile navigation with sliding dropdown menu

i'm trying to create a seperate mobile navigation for a website i'm creating. this is the basic html layout right now
<nav class="mobile-navigation">
<ul class="header-mobile">
<li>
<i class="fa fa-bars" aria-hidden="true"></i>
</li>
<li>
<img src="{$WEB_ROOT}/templates/{$template}/img/logo/logo.svg" alt="logo">
</li>
<li>
<ul>
<li><span class="icon icon-nav-account"></span></li>
<li>
<a href="{$WEB_ROOT}/cart.php?a=view">
<span class="icon icon-cart"></span>
<span class="notification-amount">{$cartitemcount}</span>
</a>
</li>
</ul>
</li>
</ul>
</nav>
<div class="row">
<ul class="nav-mobile">
<li>About us</li>
<li>Services</li>
<li>Domains</li>
<li>Support</li>
</ul>
</div>
with a simple script to toggle the menu
$('.fa-bars').click(function(evt) {
$('.nav-mobile').slideToggle('down');
});
Now i'm trying to create something where if a list item is chosen, the dropdown is displayed like the images below.
first list -->
second list with selected item
anyone an idea how i achieve this?
First of all you should change your arrow's direction and position. or create two of them one on left and one on right then when user clicks on a li toggle class clicked or something else to that li element(if you want others to collapse you should remove clicked class). Then in css
li > ul{
display:none;
}
li .left-arrow{
display:none;
}
li.clicked > .left-arrow{
display:inline;
}
li.clicked > ul{
display: block;
}
should do the trick

Show first div on page load and hide others and then show the rest on click of the menu items

I am working on a menu where on click of the navigation items, the div will be shown, but by default, the first div should be shown and rest hidden. They should be seen only on click of other navigation items.
Below is my code that I have tried so far.
The HTML:
<ul id="menu">
<li class="page_item current_page_item justClick">a</li>
<li class="page_item page-item-2 justClick">b</li>
<li class="page_item page-item-2 justClick">c</li>
<li class="page_item page-item-2 justClick">d</li>
<li class="page_item page-item-2 justClick">e</li>
<li class="page_item page-item-2 justClick">f</li>
<li class="page_item page-item-2 justClick">g</li>
<li class="page_item page-item-2 justClick">h</li>
<li class="page_item page-item-2 justClick">i</li>
</ul>
<div class="content">
</div>
<div class="content1">
cccc1
</div>
<div class="content2">
cccc2
</div>
<div class="content3">
cccc3
</div>
<div class="content4">
cccc4
</div>
<div class="content5">
cccc5
</div>
<div class="content6">
cccc6
</div>
<div class="content7">
cccc7
</div>
<div class="content8">
cccc8
</div>
<div class="content9">
cccc9
</div>
The Script:
$('.justClick').bind('click', function() {
$('div.content').html($('div.content' + ($(this).index()+1)).html());
});
The CSS:
.content {
background-color: red;
}
The JSFiddle link:
http://jsfiddle.net/6uzU6/
I am getting to achieve the onclick functionality on the click of navigation items on click of them, but all the div's are visible.
What I want, is that all the div's except first div (with the class .content) should be hidden and when you click on the navigation items, it should show up.
Try this:
$('div').not(".content,.content1").hide();
$('.justClick').bind('click', function() {
$('div').not(".content").hide();
$('div.content').html($('div.content' + ($(this).index()+1)).html());
});
DEMO
It seems like there is something missing in your code because there is no relation between the links and div you want to show. you will require more attributes on to maintain a relations between them.
A better approach would be apply a common class to all div like 'content-block' and class equal to use following code.
$(".content-block:not(:first)").hide();
and show respective div on click on link
$("#menu li").click(function(e){
$(".content-block").eq($(this).index()).show();
});
you can use other parameters as well to relate them instead of index.
Give attribute to div runat="server" and Id="dv1"
using property display block and none u can show or hide it

Categories

Resources