I have an element #foo and it has click event on it. Element #foo is in element #bar which also has click event on it.
<div id="bar">
<div id="foo" />
</div>
When #foo is clicked, #bar event gets called and #foo event gets ignored. That's now what I want.
I'm looking for a way to remove all click events from #foo element except my just set event and all events that are on parents for #foo.
Edit: Here is jsFiddle demo. I want 2nd event to get called before 1st event.
Edit #2: Here is my code with your suggestions. Doesn't work.
If you have a click event on foo and you dont want it to bubble you could do the following:
$("#foo").on('click', function(e){
e.preventDefault();
e.stopPropagation(); //this line will stop the click bubbling up the tree.
});
Use stopPropagation function, see an example:
$("#foo").click(function(e) {
e.stopPropagation();
})
try this
$('#foo').click(function(e){
e.preventDefault();
e.stopPropagation();
$('#bar').trigger('click');
});
Related
Consider the following code as an example:
<div id="parent">
<div id="child">info goes here</div>
</div>
//javascript
function something{
//do something;}
//initial attempt
document.getElementById('parent').addEventListener('click',something);
//event capture
document.getElementById('parent').addEventListener('click',something,true);
When I click on the parent element I would like it to do something, and when I click the child I want it to do nothing. The problem is that when I click in the child element it is triggering 'something'.
I thought that it may be event bubbling, such that if I clicked on the child element, the event would bubble up from there to the parent. So then I was thinking about an event capture, but that also causes this problem.
Any advice or suggestions on how to accomplish this would be greatly appreciated.
Instead, check if the element originating the event Event.target - was indeed the desired element.
PS: Don't confuse with Event.currentTarget which (in contrast) is always the Element who has the Event handler attached.
function something (evt){
if (evt.target !== this) return; // Do nothing
// else...
console.log(`#${this.id} clicked`);
}
const el_parent = document.getElementById('parent');
el_parent.addEventListener('click', something);
// Example why you should not use `Event.stopPropagation()`...
document.body.addEventListener('click', () => console.log("BODY is notified!"));
<div id="parent">
PARENT ELEMENT
<div id="child">CHILD ELEMENT</div>
</div>
Don't use Event.stopPropagation()
Event.stopPropagation() would be an idea, but a bad one, since we should avoid an application to (at some layer) prevent an event to bubble - and eventually notify other elements that such an event happened. Imagine your body listens for click events to close custom select dropdowns... If you have elements wandering around your app, and that use Event.stopPropagation() - clicking on such element an opened dropdown will not close - resulting in broken UI. And this was just a simple example.
Use event.stopPropagation to stop event bubbling:
function something() {
console.log("something");
}
document.getElementById('parent').addEventListener('click', something);
document.getElementById('child').addEventListener('click', e => e.stopPropagation());
<div id="parent">
Parent info goes here!
<div id="child">Child info goes here!</div>
</div>
It is event bubbling. Just because you are handling the click event on the child, does not mean it stops bubbling to the parent.
There are two approaches to this. The first one is to stop the event from propagating like this:
document.getElementById('child').addEventListener('click',(e) => { e.stopPropagation(); something() },true);
The second is to check the event target and only run something when the deepest element that caused the click event is the child element:
document.getElementById('child').addEventListener('click',(e) => { e.target.id == "child" ? something() : nothing() },true);
I want to let a div show and disappaer with jquery and css.
The code does not work:
HTML
<html>
<head>
</head>
<body>
<div class="box" id="b1">
click to show content
<div class="content">
here is content here is content here is content
<div class="button" id="b2">remove content</div>
</div
</body>
</html>
jQuery
$(document).ready(function() {
$('#b1').click(function() {
$('.content').css({
"display": "block"
});
});
$('#b2').click(function() {
$('.content').css({
"display": "none"
});
});
});
Demo: http://jsfiddle.net/jTgRF/41/
The problem is that you don't stop the event from propagating.
When you click the button it actually hide the element at first, but the event propagate up to the parent element, at which you catch the click and show it again. It goes so fast it looks like nothing is happening, but actually when you click on #b2, the elements get hidden, the event then bubble up to the parent #b1, to which you have attached click-event listener to show the content.
Therefor, you need to use .stopPropagation() on #b2.
$(document).ready(function(){
$('#b1').click(function(){
$('.content').show();
});
$('#b2').on("click", function(e){
$('.content').hide();
e.stopPropagation();
});
});
What you need to do is to pass the click event to the call-backfunction (declared e in my example) and then call stopPropagation() on it to make sure that it doesn't bubble up to the parent element.
Here is a working example: http://jsfiddle.net/jTgRF/64/
Note I use .show() and .hide(), which is exactly the same as what you do with .css(), but is more readable in my opinion.
Edit:
As noted by Venu in his answer, the content will show if you click on the black-area as well, not just the "show content"-text. The easiest way to solve that would be to just move the id="b1" attribute from the div with class content and put it on the a-element instead.
See my updated fiddle: http://jsfiddle.net/jTgRF/65/
since, you are attaching an event for an element which is not available in dom, event wont get attached to the element. Use live
$('#b2').live('click', function(){
$('.content').css({"display":"none"});
});
Attach an event handler for all elements which match the current selector, now and in the future.
EDIT
1)Use on instead of live as Live is deprecated.
2) There is one more issue with your css. you have set height to 150px for box class. so if you click on black area also, event gets fired.
So move the b2 element outside b1, this would solve the event propagation to the parent-element also.
You need to change the button click handler to
$('#b2').click(function(e){
e.stopPropagation();
$('.content').css({"display":"none"});
});
You need to add event.stopPropagation() Or click event will be propagated to the parent div and .content will be hidden immediately again.
Demo: http://jsfiddle.net/joycse06/jTgRF/56/
You should use jQuery .show() and .hide() to show/hide elements.
Venu's anwser works but live() is depracated.
You should use on() instead :
jQuery .on function for future elements, as .live is deprecated
Code
$(document).ready(function(){
$('#b1').click(function(){
$('.content').css({"display":"block"});
});
$(document).on('click', '#b2', function(){
$('.content').css({"display":"none"});
});
});
Hope this helps
i got a problem
<div id='parent'>
<div id='child'>
</div>
</div>
what i want is when the child is clicked addClass,and when the rest of parent is clicked removeClass,so when i try to do
$('#child').click(function(){
$(this).addClass();
})
$('#parent').click(function(){
$('#child').removeClass();
})
its not working i think its because the child is actually inside the parent,so when the child is clicked the parent clicked right?
so how can i do that?
try this:
$('#child').click(function(evt){
evt.stopPropagation();
$(this).addClass("myClass");
});
You could use event.stopPropagation to prevents the event from bubbling up the DOM tree, preventing any parent handlers from being notified of the event.
$('#child').click(function(e){
e.stopPropagation();
$(this).addClass();
});
Several users have already suggested a good solution - here's an explanation of why it works:
When you click an HTML element (actually a DOM object...), the click event "bubbles" all the way up to the root element. For example, a click in #child also triggers a click in #parent, as you expected.
To stop this behavior, you need to call .stopPropagation() on the click event - that will tell the browser that you do not want the event to propagate, but keep it "local". Basically, when you've handled it here, you're done with it and don't want to see it again.
Conveniently, jQuery event handlers take the event as the first argument, so if you assign any function with the signature function (e) { ... }, you can stop event propagation by e.stopPropagation(); as others have suggested. In your case, you want
$('#child').click(function(e){
$(this).addClass();
e.stopPropagation();
});
$('#parent').click(function(){
$('#child').removeClass();
});
Suppose I have:
<div id="outer" onclick="thingsHappen()">
<div id="inner"></div>
</div>
When I click on outer or inner div, thingsHappen() is executed. That is obvious.
Now I have got a need to define a different method for the inner div.
For example
$("#inner").click(function() {
doThings();
});
When I click on inner both thingsHappen() and doThings() executes.
How do I execute doThings() when I click on inner div without executing thingsHappen()?
I tried to unbind click method from #inner, but it did not work.
PS. I cannot change the structure of HTML.
Stop the propagation of the event:
$("#inner").click(function(e) {
doThings();
e.stopPropagation();
});
Example: http://jsfiddle.net/QNt76/
JavaScript events bubble up the DOM tree unless you stop them from propagating. This is what was causing the parent event handler to get notified.
You want Event.stopPropagation():
$("#inner").click(function(e) {
doThings();
e.stopPropagation();
});
Events pertaining to a child element bubble up to parent elements in the DOM unless propagation is stopped like so:
$("#inner").click(function(event) {
doThings();
event.stopPropagation();
});
Here is a good read on capturing/bubbling and Javascript events. http://www.quirksmode.org/js/events_order.html
$("#inner").click(function(e) {
e.stopPropagation();
doThings();
});
What you are trying to do is stop the event (click) from "bubbling" up. In this case, you would want to stop the propagation of the event in the bubbling phase. If you are using jquery, you can use this function:
HTML
<div id="outer" onclick="thingsHappenOuter()">
<div id="inner">
</div>
</div>
JS
$("#inner").click(function(event) {
event.stopPropagation();
// do something
});
SEE: http://api.jquery.com/event.stopPropagation/ for more information.
You have to stop the propagation to the Document Tree:
$("#inner").click(function(event) {
doThings();
event.stopPropagation();
});
See: http://api.jquery.com/event.stopPropagation/
Prevents the event from bubbling up the DOM tree, preventing any parent handlers from being notified of the event.
Let's says I have the following code :
<div class="body">
Click me and it will work.
<div class="head">Click me and nothing will happen.</div>
</div>
I want to display the "it works" when you click inside the .body div but not inside the .head div. How can I do this?
With this code, the log appears even if you click on head:
<script>
$('.body').click(function(){console.log('it works !');});
</script>
$('.body').click(function(e){
if($(e.target).hasClass('body'))
console.log('it works !');
});
Event bubbling is causing your troubles. Essentially, the event handler for your 'head' class would capture the click and then bubble that event up to your 'body' handler because there are nested.
Here is an excellent primer on event bubbling, how it works, and how to control event bubbling.
Here is working jsFiddle example for you to test.
Its called event bubbling. When you click on "head" div you also click on "body" div.
You need to add:
$('.head').click(function(event){event.stopPropagation()});
to prevent event bubbling.
This is the general solution:
$('.body').click(function(e){
if(e.target === this) {
console.log('it works !');
}
});
Solved similar question on stackoverflow:
Select only parent, exclude everything else while click()