I am attempting to create a drop down menu which activates on click rather than on hover. So far I have the on click working with a little javascript, but whilst the sub menus show well and if another menu is clicked other submenus hide, I can't work out how to hide a sub menu if its parent is clicked.
EG in this JS fiddle I can click on "parent 1" to reveal its children and when I click on "parent 2" parent 1's children hide and Parent 2's children show. But if Parent 1's children show I want to be able to hide them by clicking on Parent 1 again, (or even better anywhere outside the children)
I have seen examples working where each parent and sub menu is given individual classes or ids. I want to avoid that as it needs to work in a cms.
Here's the basic code I have
The HTML:
<div>
<ul>
<li>Parent 1
<ul>
<li>Parent 1 » Child 1</li>
<li>Parent 1 » Child 1</li>
<li>Parent 1 » Child 1</li>
</ul>
</li>
<li>Parent 2
<ul>
<li>Parent 2 » Child 2</li>
<li>Parent 2 » Child 2</li>
<li>Parent 2 » Child 2</li>
</ul>
</li>
<li>Parent 3
<ul>
<li>Parent 3 » Child 3</li>
<li>Parent 3 » Child 3</li>
<li>Parent 3 » Child 3</li>
</ul>
</li>
</ul>
The javascript:
$(document).ready(function () {
$("li").click(function () {
$('li > ul').hide();
$(this).children("ul").toggle();
});
});
CSS is probably not necessary, but its on the fiddle if needed
Try this way.
$(document).ready(function () {
$("li").click(function () {
//Toggle the child but don't include them in the hide selector using .not()
$('li > ul').not($(this).children("ul").toggle()).hide();
});
});
Demo
check this fiddle
http://jsfiddle.net/Kritika/SZwTg/1/
$(document).ready(function () {
$("li").click(function () {
$('li > ul').not($(this).children("ul")).hide();
$(this).children("ul").toggle();
});
});
or
$(document).ready(function () {
$("li").click(function () {
var submenu=$(this).children("ul");
$('li > ul').not(submenu).hide();
submenu.toggle();
});
});
on click of "parent 1" it reveals its children and when you click on "parent 2" parent 1's children hide and Parent 2's children show. and if Parent 1's children show you wil be able to hide them by clicking on Parent 1 again.
Better to use slideToggle at the place of toggle:
$(document).ready(function () {
$("li").click(function () {
$('li > ul').not($(this).children("ul")).hide();
$(this).children("ul").slideToggle('slow');
});
});
Related
I followed the explanation below to create what I needed, but there is an additional requirement i am trying to fulfill.
highlight the navigation menu for the current page
My submenu items are anchor links on the same page as the main menu item. Example:
$(function() {
var url = window.location.href;
$(".imagingmenu a").each(function() {
if (url == (this.href)) {
$(this).closest("li").addClass("active");
$(this).closest("li").parent().parent().addClass("active");
}
});
});
.imagingmenu ul li.active a, .imagingmenu ul li a:hover {
font-weight:bold;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="imagingmenu">
<ul>
<li>Menu item 1
<li>Menu item 2
<ul>
<li>Submenu Item 1</li>
<li>Submenu Item 2</li>
<li>Submenu Item 3</li>
</ul>
</li>
</ul>
</div>
You can see the bolding works when you hover over the submenu items, but when they are clicked and active, I want just that submenu item to be bolded and the other not to be. However, when any of the submenu items are active, all of them in the list are bolded. How can I achieve what I'm looking for?
Thanks.
This is your problem: $(this).closest("li").parent().parent().addClass("active");
When you click on a "Submenu Item" such as "Submenu Item 2" your code adds the active class to that item, but it also adds the active class to the parent-of-the-parent of the <li> that was clicked.
The parent of the <li> is the enclosing <ul> and the parent of that is the <li>Menu item 2 so what you end up with is this (notice the places where the active class was added)
<ul>
<li>Menu item 1
<li class="active">Menu item 2
<ul>
<li>Submenu Item 1</li>
<li class="active">Submenu Item 2</li>
<li>Submenu Item 3</li>
</ul>
</li>
</ul>
The <li> for "Menu item 2" gets the active class so it is bold according to the CSS rule.imagingmenu ul li.active a
That is, the whole <li> including all its children — the inner <ul> and all its <li>s are bold.
Try commenting out that line as below (I also added some console.log()s so I could see what it was doing)
$(function() {
var url = window.location.href;
$(".imagingmenu a").each(function() {
console.log(`this.href=${this.href} compare to url ${url}`);
if (url == (this.href)) {
console.log('this is', $(this));
console.log('this.closest(li) is', $(this).closest('li'));
$(this).closest("li").addClass("active");
//$(this).closest("li").parent().parent().addClass("active");
}
});
});
You may also have a problem because adding the hash # target doesn't reload the page so it doesn't re-run your function.
In reality I, personally, would handle this completely differently — I'd add a click handler to the list items; the handler receives an event parameter, and you can use the event.target to add the "active" class to the one list item that was clicked.
I have a submenu like below:
<ul id="main-menu" class="" style="">
<li class="root-level has-sub">
Menu 1
<ul>
<li>Sub-menu 1</li>
<li>Sub-menu 2</li>
</ul>
</li>
<li>Menu 2</li>
<li class="root-level has-sub"> <!-- here -->
Menu 3
<ul>
<li class="root-level has-sub"> <!-- add class 'opened' here and -->
Sub-menu 3
<ul>
<li>Sub-sub-Menu 1</li> <!-- this -->
<li>Sub-sub-Menu 2</li> <!-- when user click this or -->
</ul>
</li>
</ul>
</li>
What I would like to have is, when I click to the child, it will add 'opened' class to parent and highlight the clicked element. My code only success on Menu 1 and failed on Menu 3.
Notice that, in Menu 3, there are 2 parents for Sub-sub-Menu 1 and Sub-sub-Menu 2. So my question is, if i click on Sub-sub-Menu 1 or Sub-sub-Menu 2 it will highlight and add 'opened' class to 2 parents li above.
Note: I try to implement unlimited level of menu
Here is my full code Fiddle
I think you should use a different selector(for the click event). Look for all li>a pairs, corresponding to the submenu items, inside your #main-menu list
$('#main-menu li>a').click(function (e) {
e.preventDefault();
$('.active').removeClass('active');
$('.opened').removeClass('opened');
$(this).parent('li').addClass('active').parents('.root-level').addClass('opened');
//------------------------------------------------------^-----------------------------
// selects all parents with the 'root-level' class
});
Modifying the css to:
#main-menu .active {
background-color:#df0000;
color:#fff;
}
DEMO
you simply use the not: attribute in your closest() method to exclude all classes root-level
$(function () {
$('ul#main-menu li ul li').click(function (e) {
e.preventDefault();
//we search for the first ancestor of this which is a li
$(this).closest('li:not(".root-level")').addClass('active').siblings().removeClass('active');
$('.active:first').closest('ul').addClass('opened');
});
});
check the link http://jsfiddle.net/GEj4z/11/
If I understood correctly what was desired was being able to produce a menu like behavior and it is because of that I would like to present an alternate solution:
Sample Fiddle
$('#main-menu').on('click','li:not(.root-level)',function(e){
$('.parent').removeClass('parent');
$('.selected').removeClass('selected');
$(this).parents('li.root-level').children('a').addClass('parent');
$(this).children('a').addClass('selected');
});
In this solution the parent menus are highlighted and the clicked item is marked as selected again I wanted to share my POV of this problem. I hope it helps.
Inside your click event use $(this).parents('li') to get the top level parent li of the clicked element. I hope this helps.
I found the solution! my jquery is:
$(function () {
$('ul#main-menu li ul li').click(function (e) {
e.preventDefault();
$(this).closest('li:not(".root-level")').addClass('active').siblings().removeClass('active');
$(this).parents('li').addClass('opened');
$(this).closest('li:has(".root-level")').removeClass('active');
});
});
Here is my full code JSFiddle
I am having some issues figure out how i can just remove a class ="active" from a just one of my lists.
I have a navigation bar:
<div class="container">
<ul class="nav">
<li class="active">Home</li>
<li>About</li>
<li>Contact</li>
</ul>
</div>
I also have a menu within Home:
<div class="container_2">
<ul>
<li class="left-main-list active">Subject 1</li>
<ul class="list-in-list">
<li>Sub subject 1</li>
<li>Sub subject 2</li>
</ul>
<li class="left-main-list>Subject 2</li>
<li class="left-main-list>Subject 3</li>
</ul>
</div>
While i browse my menu on the home page, i want to change the the active list items class to active when clicked, so i now have this jQuery code:
$(document).ready(function() {
$('li').click(function() {
$('li').removeClass('active');
$(this).addClass('active');
});
});
This works for my menu, the class change to the current one, but it also delete my navigation bars class, which i don't want. :)
I have tried something like:
$(document).ready(function() {
$('.left-main-list').click(function() {
$('.left-main-list li').removeClass('active');
$(this).addClass('active');
});
});
I've tried '.left-main-list li' & 'li.left-main-list' without any success.
Greatful for answer to this question, and i hope my question (this time) is more accurate than my previous ones. :)
/Bill
ps: Can a sub subject AND a main subject be active at the same time, and that sub subject's class of active, be removed if you for example click another sub subject, but the main item still have it's class of active?
While i browse my menu on the home page, i want to change the the
active list items class to active when clicked
You could just target the lis within the relevant div, similar to this:
$(document).ready(function() {
var $listItems = $('div.container_2 li');
$listItems.click(function() {
$listItems.removeClass('active');
$(this).addClass('active');
});
});
DEMO - target lis within .container_2 only
Can a sub subject AND a main subject be active at the same time, and
that sub subject's class of active, be removed if you for example
click another sub subject, but the main item still have it's class of
active?
Still targeting the container you could use jQuery's parent(), similar to this:
$(document).ready(function () {
$('div.container_2 li').click(function () {
var $this = $(this);
var $children = $this.parent().find('li');
$children.removeClass('active');
$this.addClass('active');
});
});
DEMO - Using parent() to allow active menu and sub-menu but not when main menu changes
I looked at the possibility of making this more dynamic to add activation of items going up the chain when switching between sub menus located within different main menu elements.
Fixing the HTML of the nested uls whereby your nested uls are inside lis instead of just inside the upper ul you can do a fully dynamic implementation.
Assume your HTML like this:
<div class="container">
<ul class="nav">
<li class="active">Home</li>
<li>About</li>
<li>Contact</li>
</ul>
</div>
<div class="container_2">
<ul>
<li class="left-main-list active">Subject 1
</li>
<li>
<ul class="list-in-list">
<li>Sub subject 1
</li>
<li>Sub subject 2
</li>
<li>
<ul class="list-in-list">
<li>Sub subject 1
</li>
<li>Sub subject 2
</li>
</ul>
</li>
</ul>
</li>
<li class="left-main-list">Subject 2
</li>
<li class="left-main-list">Subject 3
</li>
</ul>
</div>
Now, using the following script, you can also make parents of any sub menu items active when changing from a sub menu to another which is within another main menu item, similar to this:
$(document).ready(function () {
$('div.container_2 li>a').click(function () {
var $this = $(this);
var $relatedElements = $this.parents('ul').find('li');
if($this.hasClass('active')){
return;
}
$relatedElements.removeClass('active');
$this.parent('li').addClass('active');
var $parents = $this.parents('li');
$parents.each(function(){
$(this).not($this.parent()).prev().addClass('active');
});
});
});
DEMO - Chain-like activation
I think this should have all possible examples to get you started from here.
Hope this helps.
Try this:
$("li").click(function() {
$(this.parentNode).children("li").removeClass("active");
$(this).addClass("active");
});
This will affect only the siblings of the element you click on.
$('.left-main-list').click(function() {
$('.left-main-list').removeClass('active');
$(this).addClass('active');
});
I think what you're looking for is this:
$(document).ready(function() {
$('li').click(function() {
$('li.left-main-list').removeClass('active');
$(this).addClass('active');
});
});
How about
$('li').on ('click', function (){
$(this).addClass ('active').siblings ('li').removeClass ('active');
})
I plan to apply a custom show/hide effect on link, such that when a user hovers on a link, a different link appears in its place. I'm not so good in javascript and here is what I was trying:
<div id="nav">
<li id="a1">hover link 1</li>
<li id="a2">show link 1</li>
<li id="b1">hover link 2</li>
<li id="b2">show link 2</li>
<li id="c1">hover link 3</li>
<li id="c2">show link 3</li>
</div>
The javascript:
$("#nav a.li").hover(function () {
(this.id.charAt(0)+"1").hide();
});
Here is the fiddle
You missed $ and need to add # befor id your also need to change selector as you do not have anchor with class li
Change
(this.id.charAt(0)+"1").hide();
to
$('#' +this.id.charAt(0)+"1").hide();
Your code would be
Live Demo
$("#nav a li").hover(function () {
$('#'+ this.id.charAt(0)+"1").hide();
});
Edit If you want to remove the item being hovered then use $(this)
Live Demo
$("#nav a li").hover(function () {
$(this).hide();
});
I'm looking for a solution, it must work in IE also, that I can have the content hidden and then when you click one of the menu items it shows the content. However, the content doesn't hide until a user clicks on the next link...
Please check this link
http://jsfiddle.net/varada/YLX9x/
you can use jquery hide() and show() functions for that.
Let the id of div that is to be hidden be hidden_div, let menu item be menu_item, next button be next,
Import the jquery.js
and write the ready function as below..
$(document).ready(function() {
$('#menu_item').click(function() {
$('#hidden_div').show();
});
$('#next').click(function() {
$('#hidden_div').hide();
});
});
or if you mean the content be visible till he click the next link on the menu item, add a class name say, menu_class to the menu items and write the code
$('.menu_class').click(function() {
$('#hidden_div').hide();
});
instead of $('#next').click(function()
if you have a menu like
<ul>
<li class='menu_class'>item 1</li>
<li id='menu_item' >item 2</li>
<li class='menu_class'>item 3</li>
</ul>
and the div
<div id='hidde_div' style='display:none'>
content
</div>
then if you click item 2 the div will get displayed. and if you click item 1 or item 3 it will get hidden. make sure you are using the code $('.menu_class').click(function() {
html:
<li class="main">Web
<ul>
<li>Designing</li>
<li>Development</li>
</ul>
</li>
<li class="main">IT
<ul>
<li>Sales & Service</li>
<li>CCTV</li>
<li>DVR</li>
</ul>
</li>
<li class="main">ITES
<ul>
<li>BPO</li>
<li>Online Portal</li>
<li>Online Marketing</li>
</ul>
</li>
js:
$(document).ready(function(){
$('li ul:not(:first)').hide();
$('ul li').click(function(){
$(this).closest('.main').next().find('ul').show();
$(this).closest('ul').hide();
});
});
http://jsfiddle.net/7QheB/