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 );
})
});
Related
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 ...
can anyone please help?
I have a HTML code like this.
<ul class="nav navbar-nav navbar-left">
<li>
<img src="img/topbararrowback.png" alt="">
</li>
<li id="hide_filter">
Hide Filter
</li>
</ul>
I try to add a .click event on li having id hide_filter.
What I have done is-
$("#hide_filter").click(function()
{
alert('message');
});
And -
$(".navbar-left li").click(function() {
alert(this.id); // id of clicked li by directly accessing DOMElement property
alert($(this).attr('id')); // jQuery's .attr() method, same but more verbose
alert($(this).html()); // gets innerHTML of clicked li
alert($(this).text()); // gets text contents of clicked li
});
And -
$('ul.selectedItems li#hide_filter').click(function()
{
//$("p").hide();
alert('message');
});
And -
$('#hide_filter')[0].click(function()
{
//$("p").hide();
alert('message');
});
But nothing works for me.
Thanks in advance for helping..
Actually It works :)
$("#hide_filter").click(function()
{
alert('message');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<ul class="nav navbar-nav navbar-left">
<li>
<img src="img/topbararrowback.png" alt="">
</li>
<li id="hide_filter">
Hide Filter
</li>
</ul>
Assuming you have added the jquery library, You need to attach the event when DOM is loaded.i.e. on DOM ready event:
$(function(){//document ready function
$("#hide_filter").click(function(){
alert('message');
});
});
Working Demo
Maybe your code is not eval.
Try put your code in body tag with function wrap like this
$(function(){ //document ready function
$("#hide_filter").on("click",function(){
console.log('message');
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
Remove .selectedItems selector from your 3rd option
$('ul li#hide_filter').click(function()
{
//$("p").hide();
alert('message');
});
Remove index 0 from your 4th option
$('#hide_filter').click(function()
{
//$("p").hide();
alert('message');
});
Otherwise your 4 options are correct and will work fine. Kindly make sure you have written these codes inside ready event.
$(document).ready(function(){
$("#hide_filter").click(function()
{
alert('message');
});
});
Maybe there is a problem with jquery libraries. Are they in conflict with other javascripts?
This is my first foray into using Javascript with HTML. I'm trying to add click events to the list items in an ordered list, but something about the way I'm doing it isn't working. Can somebody shed some light on this for me?
I create a function in my head that should delegate all click events on the list items of a specified list to a given function, and in that given function I try to raise a simple alert with the text of the list item. Eventually I want to do more, but I'm just trying to get the simple click events to work first.
<html>
<head>
<script type="text/javascript">
// Attach an event handler to the 'topfriends' list to handle click events.
function attachEventHandlerToList() {
document.getElementById("#top4list").delegate("li", "click", function(clickEvent) {
alert(this.innerHTML());
});
}
</script>
</head>
<body>
<div id="topfriends">
<h3>Top 4 Most Friendable Friends</h3>
<ol id="top4list" onload="attachEventHandlerToList()">
<li>Brady</li>
<li>Graham</li>
<li>Josh</li>
<li>Sean</li>
</ol>
</div>
</body>
Let's do something like this
<ul id="parent-list">
<li id="a">Item A</li>
<li id="b">Item B</li>
<li id="c">Item C</li>
<li id="d">Item D</li>
<li id="e">Item E</li>
<li id="f">Item F</li>
</ul>
Now write the javascript for this
<script type="text/javascript">
// locate your element and add the Click Event Listener
document.getElementById("parent-list").addEventListener("click",function(e) {
// e.target is our targetted element.
// try doing console.log(e.target.nodeName), it will result LI
if(e.target && e.target.nodeName == "LI") {
console.log(e.target.id + " was clicked");
}
});
</script>
Please refer to this write-up on Javascript Event Delegates
http://davidwalsh.name/event-delegate
Also, below link is the fiddle that I created
http://jsfiddle.net/REtHT/
hope this helps !
delegate() is a deprecated jQuery method, and no such method exists in plain JS.
To attach an event handler in JS you'd use addEventListener, and for older versions of IE you'll need attachEvent as well, that's why it's a little tricky with cross browser event handlers.
onclick, onmouseenter etc. will work in all browsers, but it's consider a better practice to use addEventListener / attachEvent.
Also, you have to run the script after the elements are added to the DOM, otherwise they are not available. The usual way is to insert the script after the elements, or use a DOM ready event handler.
<html>
<head>
<title>test</title>
</head>
<body>
<div id="topfriends">
<h3>Top 4 Most Friendable Friends</h3>
<ol id="top4list">
<li>Brady</li>
<li>Graham</li>
<li>Josh</li>
<li>Sean</li>
</ol>
</div>
<script type="text/javascript">
var lis = document.getElementById("top4list").getElementsByTagName('li');
for (var i=0; i<lis.length; i++) {
lis[i].addEventListener('click', doStuff, false);
}
function doStuff() {
alert( this.innerHTML );
}
</script>
</body>
FIDDLE
Try this. It will work with child Node and Parent Node also.
var visitorList = document.getElementById("visitor");
visitorList.addEventListener("click", function (e) {
var visitorId;
if (e.target && e.target.nodeName == "LI") {
visitorId = e.target.id;
console.log(e.target.id);
}
if(e.target && e.target.nodeName == "H1") {
visitorId = e.srcElement.parentElement.id;
console.log(e.srcElement.parentElement.id);
}
//console.log(visitorId);
});
<ul id="visitor">
<li id="a" style="background: #CCCCCC; padding: 10px;"><h1 style="background: #437ba9;">Visitor A</h1></li>
<li id="b"><h1>Visitor B</h1></li>
<li id="c"><h1>Visitor C</h1></li>
<li id="d"><h1>Visitor D</h1></li>
<li id="e"><h1>Visitor E</h1></li>
<li id="f"><h1>Visitor F</h1></li>
</ul>
You can also do it by using querySelectorAll
<ul class="stuffList">
<li>Stuff 1</li>
<li>Stuff 2</li>
<li>Stuff 3</li>
<li>Stuff 4</li>
<li>Stuff 5</li>
</ul>
<script type="text/javascript">
document.querySelectorAll('ul.stuffList li').forEach((item) => {
item.addEventListener('click', (e) => {
console.log(e.target)
})
});
</script>
Hello why not doing it easier by replacing onLoad directy by onClick
<script type="text/javascript">
function olClicked(){
alert(this.innerHTML());
}
</script>
<ol id="top4list" onClick="olClicked()">
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
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');
});