I want an event to be fired when the li of outer list is clicked. I've written a function for it but the event is being fired even when I click the inner list li. Please help.
I have the following HTML structure :
<ul class="nav nav-pills nav-stacked" id="outer-menu">
<li id="R1">Sample Reports
<ul class="nav nav-pills nav-stacked" id="inner-menu">
<li>Employee salary report</li>
<li>Car sales Report</li>
<li>Business client report</li>
</ul>
</li>
</ul>
And jquery :
$(document).ready(function() {
$('#outer-menu a').on('click',function(){
alert("this clicked");
});
});
You can use the following for restricting the matched set to direct children only:
$('#outer-menu > li > a').on('click',function() {
...
});
Try like
$('#outer-menu li a').on('click',function(){
alert("this clicked");
});
Or even try like
$('#outer-menu #R1 a').on('click',function(){
alert("this clicked");
});
You need to target only the direct childrens, and you can also stop event propagation/bubbling(here you used a alert on click event, but if you use an animation later, you will need to stop the animation propagation), so you can use the following code:
$(document).ready(function(){
$('#outer-menu > li > a').on('click',function(){
alert("this clicked");
}).stop(true, true);
});
Related
HTML code
<ul id='orgCat'>
<li parent-id="0" li-id="16">Anthropology Department</li>
<li parent-id="16" li-id="18">Anthropology Faculty Collections</li>
<li parent-id="16" li-id="23">Shared Collections</li>
<li parent-id="0" li-id="19">Center for Research on Vermont</li>
<li parent-id="19" li-id="24">Collections for Testing</li>
<li parent-id="24" li-id="25">Geology Department</li>
</ul>
Jquery
jQuery(function($){
var $ul = $('ul');
$ul.find('li[parent-id]').each(function () {
$ul.find('li[parent-id=' + $(this).attr('li-id') + ']').wrapAll('<ul />').parent().appendTo(this)
});
});
//to get li-id on double click
$('#orgCat li').dblclick(function(){
alert($(this).attr('li-id'));
})
Problem is
When double click on 'li' element its showing parents 'li-id' also but it should return only current list 'li-id'. Jsfiddle
You need to use e.stopPropagation to stop event bubbling.
$('#orgCat li').dblclick(function(e){
e.stopPropagation();
alert($(this).attr('li-id'));
});
Check this link for more information.
Right now, I'm trying to build a vertical menu that will have a drop down sub menu below it.
Below is my HTML and the jQuery function I am using:
$(function() {
$('#menusomething > li').click(function(e) {
e.stopPropagation();
var $el = $('ul', this);
$('#menusomething > li > ul').not($el).slideUp();
$el.stop(true, true).slideToggle(400);
});
$('#menusomething > li > ul > li').click(function(e) {
e.stopImmediatePropagation();
});
});
<div id="navmenu">
<ul id="menusomething" style="padding-left:30px">
<li>HOME</li>
<li>ABOUT</li>
<li>CHAPTERS</li>
<ul class="submenu">
<li>Dallas</li>
<li>Los Angeles</li>
<li>New York</li>
<li>Northern California</li>
<li>Orange County</li>
<li>Phoenix</li>
<li>San Diego</li>
<li>Washington DC</li>
</ul>
<li>MEMBER SERVICES</li>
Figured out the answer for anyone who sees this. First had to move the closing li tag from chapters to the end of .submenu Then used this and now it works as wanted.
$(function() {
$('#menusomething li > .submenu').parent().click(function() {
var submenu = $(this).children('.submenu');
if ( $(submenu).is(':hidden') ) {
$(submenu).slideDown(400);
} else {
$(submenu).slideUp(400);
}
});
});
The following code does what I believe you desire: Have a <ul> element that is the nextElementSibling of the first level <li> element slide open and closed when it is clicked. As you mentioned in comments that you desired, it now starts closed due to adding style="display: none;" to the <ul>.
Note: From a user interface perspective, the <li> entries which don't have sub-menus, or are otherwise links, should not have the text enclosed in <a> tags. With the <a> tags the user will think they are clickable, when a click does nothing. This is confusing to a user. It appears that you may have some be sub-menus and some be direct links. If possible, there should be some visual difference between the two types to hint to the user as to what will happen when they click.
Along with other issues, your HTML has nothing that will match either the '#menusomething > li > ul' or the '#menusomething > li > ul > li' selectors. Specifically, you have no <UL> elements that are children of <LI> elements.
$(function() {
$('#menusomething > li').click(function(e) {
e.stopPropagation();
var nextSib = this.nextElementSibling;
if(nextSib && nextSib.nodeName === 'UL') {
//If we get here the nextSib exists and is a <UL> that immediately follows
// the <LI> which was clicked.
$(nextSib).slideToggle(400);
}
});
$('#menusomething > ul > li').click(function(e) {
console.log('Clicked on chapter: ' + this.textContent);
e.stopImmediatePropagation();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<div id="navmenu">
<ul id="menusomething" style="padding-left:30px">
<li>HOME</li>
<li>ABOUT</li>
<li>CHAPTERS</li>
<ul class="submenu" style="display: none;">
<li>Dallas</li>
<li>Los Angeles</li>
<li>New York</li>
<li>Northern California</li>
<li>Orange County</li>
<li>Phoenix</li>
<li>San Diego</li>
<li>Washington DC</li>
</ul>
<li>MEMBER SERVICES</li>
</ul>
</div>
I have searched a lot for adding active class to the parent menu using javascript.
I found many more examples but not a single one is working for me, below is my code
HTML
<div id="menu1" class="hmenu">
<ul>
<li>Item1
<ul>
<li>SubItem1
<ul>
<li>SubSubItem1</li>
<li>SubSubItem2</li>
</ul>
</li>
<li>SubItem2 </li>
<li>SubItem3
<ul>
<li>SubSubItem1</li>
<li>SubSubItem2</li>
</ul>
</li>
</ul>
</li>
<li>Item2</li>
<li>Item3
<ul>
<li>SubItem1
<ul>
<li>SubSubItem1</li>
<li>SubSubItem2</li>
</ul>
</li>
</ul>
</li>
</ul>
<br style="clear: left" />
</div>
My requirement is when i click on SubItem1 then both Item1 and SubItem1 should be active.
And when i click on SubSubItem1 then SubSubItem1 ,SubItem1 and Item1 should be active.
Means when click on any link then its all parent link and the same link should be active.
I have tried with this javascript code :
$(document).ready(function () {
$('.hmenu ul li ul').find('li').click(function () {
//removing the previous selected menu state
$('.hmenu').find('li.active').removeClass('active');
//adding the state for this parent menu
$(this).parents('li').addClass('active');
});
});
Actually i don't have any experience with javascript coding and unable to figure out the problem in my code.
Can anyone suggest me for the same.
The issue comes from .find('li').click().
As you use nestsed <li>, this will cause the event to be fired two times when you click on a child <li>. This causes problems. Can not you add the click() to <a> elements?
$(document).ready(function () {
$('.hmenu a').click(function () {
//removing the previous selected menu state
$('.hmenu').find('li.active').removeClass('active');
//adding the state for this parent menu
$(this).parents("li").addClass('active');
});
});
It works just fine: https://jsfiddle.net/6put8tdx/
Note that your page will be bumped to the top while clicking to a tab because of # anchor. If you want to prevent this, you may pass the event to the function .click(function (event) {...} and add event.preventDefault inside.
If you need the click target to be the LI element (as opposed to Delgan's answer)
you can use .not() over the targeted LI's parents to prevent messing with the bubbling event targets:
$(document).ready(function () {
$('.hmenu').find('li').click(function(event) {
event.preventDefault(); // Prevent page jumps due to anchors
var $par = $(event.target).parents("li"); // get list of parents
$(".hmenu .active").not( $par ).removeClass("active"); // not them
$(this).addClass('active'); // let the event propagation do the work
});
});
$(document).ready(function () {
$('.hmenu').find('li').click(function(event) {
event.preventDefault();
var $par = $(event.target).parents("li");
$(".hmenu .active").not($par).removeClass("active");
$(this).addClass('active');
});
});
.active > a{
background: gold;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="menu1" class="hmenu">
<ul>
<li>Item1
<ul>
<li>SubItem1
<ul>
<li>SubSubItem1</li>
<li>SubSubItem2</li>
</ul>
</li>
<li>SubItem2 </li>
<li>SubItem3
<ul>
<li>SubSubItem1</li>
<li>SubSubItem2</li>
</ul>
</li>
</ul>
</li>
<li>Item2</li>
<li>Item3
<ul>
<li>SubItem1
<ul>
<li>SubSubItem1</li>
<li>SubSubItem2</li>
</ul>
</li>
</ul>
</li>
</ul>
<br style="clear: left" />
</div>
To better understand the above
The following example works out-of-the-box, and the clicked one and all it's LI parents get the "active" class.
Why? Cause the event target is li, means any li of .hmenu - so that click is attached to any of them, and clicking the subsub LI the event will propagate to the LI parents - triggering the same click behavior (this add class)!
$(".hmenu").on("click", "li", function(){
$(this).addClass("active"); // Wow! Event propagation rulez!!
});
But we need to remove existing .active and here it gets messy...
$(".hmenu").on("click", "li", function(){
$(".active").removeClass("active"); // triggered on every event bubble :(
$(this).addClass("active"); // leaving only the main parent with active class
});
That's caused by the concurrency that happens while the event bubbles and triggers the same actions for the parent elements.
One way to prevent that concurrency would be using a setTimeout of 1ms:
$(".hmenu").on("click", "li", function(){
$(".active").removeClass("active");
setTimeout(function(){ // Let the previous finish the bubbling mess
$(this).addClass("active"); // Yey! all fine! Every LI has the active class
}, 1);
});
But here the timeout of 1ms can lead to visual "blinking" issues.
Try this:
$(function () {
$("li a")
.on("click", function () {
$(this).toggleClass("active");
$(this).closest("ul").parent().children("li a").toggleClass("active")
.parent().parent().parent().children("li a").toggleClass("active");
});
});
fiddle
Traverse from the clicked element. And use toggleClass() to avoid the mundane checking if hasclass removeClass ...
I'm trying to change the 'active' class for the clicked list item but I'm missing something. Here is what my HTML and jquery look like:
HTML
<ul class="additional-menu">
<li class="active"> Link1</li>
<li>Link2</li>
<li>Link3</li>
</ul>
jQuery
$("#link2").click(function(){
if ($(this).find('#additional-menu li').hasClass('active')) {
//console.log("Active class seen");
$(this).find('#additional-menu li').removeClass('active');
$(this).addClass('active');
}
});
Any idea what I'm missing? I'm not even detecting the active class at this point...
You could minimize your code to just
$('.additional-menu').on('click','li', function(){
$(this).addClass('active').siblings().removeClass('active');
});
Demo at http://jsfiddle.net/DvHBp/
There are many problems in the code
//from what i can understand you need to change the active class to the clicked li element not just the link2 element
$("#link2").click(function(){
// additional-menu is not an id it is a class and it is not a descendant of the li element
if ($(this).find('#additional-menu li').hasClass('active')) {
//console.log("Active class seen");
$(this).find('#additional-menu li').removeClass('active');
//if you are using a if statement then addClass should be outside the if block
$(this).addClass('active');
}
});
try
jQuery(function(){
var $lis = $('.additional-menu > li').click(function(){
$lis.removeClass('active');
$(this).addClass('active')
});
})
find() get the descendants of each element in the current set of matched elements, filtered by a selector, jQuery object, or element.
You should use
$(this).parent().siblings('#additional-menu li')
because in your html structure #link2 a tag has no descendant of #additional-menu li
You can make something very generic:
<ul class="additional-menu">
<li class="active"> Link1</li>
<li>Link2</li>
<li>Link3</li>
</ul>
And using this JavaScript:
$(function(){
$('.additional-menu > li').click(function(){
$('.additional-menu > li').removeClass('active');
$(this).addClass('active');
});
});
Try this solution :
HTML:
<ul class="additional-menu">
<li><a id="link1" href="link1"> Link1</a></li>
<li>Link2</li>
<li>Link3</li>
</ul>
CSS:
.active{
background-color : red;
}
jQuery:
//on first time load set the home menu item active
$(".additional-menu a#link1").addClass("active");
//on click remove active class from all li's and add it to the clicked li
$("a").click(function(){
$("a").removeClass("active");
$(this).addClass("active");
});
Demo
I have the following code structure:
<ul class='menu'>
<li>
Main Menu
<ul class='hide'>
<li>SubMenu1</li>
<li>SubMenu2</li>
</ul>
</li>
<li>
Main2
<ul class='hide'>
<li>Sub1</li>
</ul>
</li>
</ul>
Is there a way for me to have a jQuery click event on Main Menu and Main2 in a generic way that will remove the class 'hide' of the correct children each time?
Here is another way, which uses event delegation and only runs when the li element and not its children was clicked:
$('ul.menu').on('click', 'ul.menu > li', function(e) {
if(e.target === this) {
$(this).children('ul').toggleClass('hide');
}
});
DEMO
$("ul.menu > li").on("click", function () {
$(this).children("ul").removeClass("hide");
});
Example: http://jsfiddle.net/dpkBL/
Dont always do what the crowd tells you, at least think about it for a while!
I bet people will recommend you to use a selector such as ul.menu > li, but please remember that this will not only trigger a click event when you click on the text "Main Menu", but also when you click on any of the other content inside the matching li.
If you'd like to implement a show/hide toggle you are far better off wrapping the text "Main Menu" inside it's on element, and then use something as the below to alter what you may want to alter.
$(<main menu text selector>).siblings (<siblings selector>);
Still want/have to follow the crowd?
If this is the case I'd recommend you to at least do it with a little twist to prevent what I previously described.
(edit: revised version after reading the jquery documentation for elements)
$('ul.menu > li').click (function(e){
if (e.target === this) {
$(this).children ('.hide').removeClass ('hide');
}
});
$("ul.menu > li").click (function () {
$(this).find ('.hide').removeClass ('hide');
});
$("ul.menu > li > *").click (function () {
return false; // prevent event from bubbling up
});
Sample implementation of recommended version
The below will bind a click-event-listener to .menu-toggle, when the event is fired the siblings (ie. the tags who are in the same scope as the clicked .menu-toggle) matching .hide will have their class="hide" removed.
Javascript
$(".menu-toggle").click (function () {
$(this).siblings ('.hide').removeClass ('hide');
});
HTML
<ul class='menu'>
<li>
<span class="menu-toggle">Main Menu</span>
<ul class='hide'>
<li>SubMenu1</li>
<li>SubMenu2</li>
</ul>
</li>
<li>
<span class="menu-toggle">Main2</span>
<ul class='hide'>
<li>Sub1</li>
</ul>
</li> </ul>
Take a look at the child selectors. I think that is what you want.
$('.menu > li').click(function () {
$(this).children('ul').removeClass('hidden');
});