I have a jQuery code that: onlick on #icon toggles parents class, and onclick on body changes changes the class back if clicked before.
What I need is to have the same thing happen when clicked on #item5 or #item4 like its clicked on #icon.
<div id="header_wrap">
<div id="logo"></div>
<div class="contact" id="ccontainer">
<div id="form"></div>
<div id="icon"><span id="getintouch">GET IN TOUCH</span></div>
</div>
<div id="menu_wrap">
<ul id="menu">
<li id="item1">Home</li>
<li id="item2">About us</li>
<li id="item3">What we do</li>
<li id="item4">Portfolio</li>
<li id="item5">Contact us</li>
</ul>
</div>
</div>
jQuery code....I tried writing my own to add the functionality but I can't seem to get it working.. very little experience with js/jq.
$('#icon').on('click', function(e){
$(this).parent()
.toggleClass('contact')
.toggleClass('contactexpand');
});
$('body').on('click', function(e){
$('#ccontainer')
.removeClass('contactexpand')
.addClass('contact');
});
$('#ccontainer').on('click', function(e){
e.stopPropagation();
});
You have to call event.stopPropagation from the click handler to keep it from "bubbling" up the DOM (i.e., to keep it from activating the click event on all ancestor elements).
$(document).ready(function(){
$('#icon, ul li').on('click', function(event){
event.stopPropagation();
$('#icon').parent()
.toggleClass('contact')
.toggleClass('contactexpand');
});
$('body').on('click', function(e){
$('#ccontainer')
.removeClass('contactexpand')
.addClass('contact');
});
});
Change the js to:
$('#icon, #ul > li').on('click', function(e){
$("#ccontainer")
or $(this).parent() *not entirely sure what you wanted to get*
.toggleClass('contact')
.toggleClass('contactexpand');
});
$('body:not(#icon, #ul > li)').on('click', function(e){
$('#ccontainer')
.removeClass('contactexpand')
.addClass('contact');
});
$('#ccontainer').on('click', function(e){
e.stopPropagation();
});
The #ul > li refers to all #item(number)s
Related
I have the following header that will toggle between pages:
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-collapse collapse">
<form method="post">
<ul class="nav navbar-nav">
<li class="active">Active Tags</li>
<li>Archived Tags</li>
</ul>
</form>
</div>
</div>
</nav>
and the following jQuery to toggle the active li on click:
$('.navbar li').click(function(e) {
$('.navbar li.active').removeClass('active');
var $this = $(this);
if (!$this.hasClass('active')) {
$this.addClass('active');
}
e.preventDefault();
});
Moving between pages works only when e.preventDefault(); is commented out but the active class toggle won't work without this line... will I have to change my href's to sometype of onclick jQuery function or php $_POST of a hidden form to move between pages while retaining the toggle between active li's? Am new to javascript/html/php so as much detail and reasoning as possible is quite encouraged and encouraging.
Yes, you are right, e.preventDefault() will just toggle active class on li and restrict anchor to perform its operation.
While, changing it to e.stopPropagation() will allow both operation to perform at their own, without notifying regarding their event to parent handler.
Prevents the event from bubbling up the DOM tree, preventing any
parent handlers from being notified of the event.
Therefore, you can change it to:
$('.navbar li').click(function(e) {
e.stopPropagation();
$('.navbar li.active').removeClass('active');
var $this = $(this);
if (!$this.hasClass('active')) {
$this.addClass('active');
}
});
DEMO
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 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);
});
I'm not sure if this is actually an event bubbling issue. event.stopPropagation() doesn't solve the problem. The scenario is:
Click element class 'clickMe' (as many clicks as you want)
Then click li element. The click event will be executed based on numbers of click on 'clickMe' class.
Below is the snippet of the code:
html:
<div class="clickMe">Click Me 1</div>
<div class="clickMe">Click Me 2</div>
<div class="clickMe">Click Me 3</div>
<ul id="test">
<li>Test A</li>
<li>Test B</li>
<li>Test C</li>
</ul>
js:
$(function() {
$('.clickMe').live('click', function(e){
//e.stopPropagation()
$('li', $('#test')).live('click',function(e){
//e.stopPropagation()
alert('ouch')
})
})
});
Thanks in advance for any help or explanation about this issue.
You're adding another click handler to the <li> elements whenever a "click" happens on one of the "clikMe" <div> elements. The jQuery code maintains all of those handlers, so after you've clicked "clickMe" a few times, there are several handlers and they'll all be called.
The .live() method is not the best way to delegate event handling. Use .on() if you're using a new version of jQuery, or at least .delegate().
For every click on clickMe you are attaching an event to #test that is your li element
live attaches an event handler for all elements which match the selector, now and in the future.
Separate both and use on
$('.clickMe').on('click', function(e) {
//e.stopPropagation()
})
$('li', $('#test')).on('click', function(e) {
//e.stopPropagation()
alert('ouch');
});
Fiddle:
http://jsfiddle.net/iambriansreed/aEkNa/
jQuery:
$(function() {
var clickme_clicks = 0, clickme_timeout = setTimeout(function(){},0) ;
$('.clickMe').on('click', function(e){
clickme_clicks++;
clearTimeout( clickme_timeout );
clickme_timeout = setTimeout(function(){ clickme_clicks = 0; },1000);
});
$('li a', $('#test')).on('click',function(e){
e.preventDefault();
//if(clickme_clicks == 0) return;
alert('clicks: ' + clickme_clicks );
})
});
Here's the JS I've tried:
$('#footer').find('.browse li').click(function(e){
$(this).find('a').click();
});
Here's the HTML in question:
<div id="footer" class="span-24"><div class="footer-box"><div class="footer-holder">
<div class="browse">
<ul>
<li>123</li>
<li>123</li>
<li>123</li>
<li>123</li>
</ul>
</div>
</div></div></div>
How can I make the <a> click if the <li> is clicked?
PS. This is due to a css design (the LI has a bunch of padding and a background that can't be put on the A)
Your call to .click() just triggers anything bound to the a's click event. I think what you want is something like this:
$('#footer').find('.browse li').click(function(){
window.location = $(this).find('a').attr('href');
}
Are you just missing a click event for the a? Example:
$('.browse li').click(function(e){
$(this).find('a').click();
});
$('a').click(function(){
alert("a clicked");
return false;
});
see this fiddle: http://jsfiddle.net/LRMqD/3/
On the other hand, if you are just trying to redirect to the href try this code:
$('.browse li').click(function(e){
window.location.href = $(this).find('a').attr('href');
});
Please do not attach an event handler to every single element.
Use delegate instead:
$('#footer').find('.browse li').delegate('a', 'click', function(e){
var elt = e.target;
console.log('clicked a number '+elt.id);
});
to make <a> click, you need to do a trigger.
http://api.jquery.com/trigger/
$('#footer').find('.browse li').click(function(e){
$(this).find('a').trigger('click');
});