can someone explain how this stopPropagation works? - javascript

I was trying to setup this "when you click outside of the element, close it" type of thing using some code I found on Stackoverflow:
$(document).click(function() {
$('.list-to-hide').hide();
});
$('.show-list-button').click(function(event) {
event.stopPropagation();
});
Could someone explain the later part with stopPropagation? I don't understand why it's needed.
Thanks!
Matt

Imagine this:
<div>
DIV
<span>
Span
</span>
<div>
and:
$('div').click(function() { alert('div clicked'); });
$('span').click(function() { alert('span clicked'); });
Check out what happens when you click each one
When you click the span, it happens to also trigger the div because your also clicking the div.
Now if we wanted to alert the span only we need to stop the div click from triggering when we click on the span so we do this:
$('div').click(function() { alert('div clicked'); });
$('span').click(function(e) { alert('span clicked'); e.stopPropagation(); });
See what happens now

Your example code is missing a vital part:
$(document).click(function() {
$('.list-to-hide').hide();
});
$('.show-list-button').click(function(event) {
event.stopPropagation();
$('.list-to-hide').show();
});
Without the event.stopPropagation(), it would show the list, and then hide it because the .show-list-button is inside the $(document) so both click handlers would fire. event.stopPropagation() basically says only apply this click event to THIS CHILD NODE and don't tell the parent containers anything because I don't want them to react.
Think about it this way - you rent a taxi for $100. The driver gives his company $80. event.stopPropagation() is like telling him to keep all $100 because the company doesn't need to know anything about the ride.

event.stopPropagation(); prevents the event from bubbling up the DOM. Without this line, clicking on .show-list-button the click handler for document will fire also. With it, the document click will not fire.

Have you read this ?
http://api.jquery.com/event.stopPropagation/
It prevents the event from bubbling up the DOM tree, preventing any parent handlers from being notified of the event.
Example
Kill the bubbling on the click event.
$("p").click(function(event){
event.stopPropagation();
// do something
});

Related

how prevent the parent click event on change a checkbox

I have a checkbox inside a parent container which has a click event, whenever I try to click the checkbox parent click works first and following by the change event, I am using e.stopPropagation(); on both the parent and child events, but still, it's not working
// make the .parent react
function grandParent(){
alert('Grand Parent: You hit me, my child or my grand child, now deal with me!');
}
// make the .parent react
$('.parent').on('click', function(e){
e.stopPropagation()
alert('Parent : Don\'t you dare hitting me or my child, again!');
});
// make the child cry, when we hit him.
$('.child').on('click', function(e){
e.stopPropagation();
alert('Child : waaaaaa waaaa waa huh huh waaa waaaa!');
});
$('.hello').on('change', function(e){
e.stopPropagation();
alert('checkbox clicked');
});
Fiddle example
You have to bind the click event on the checkbox and not the change event: http://jsfiddle.net/ohc8jt6w/
Sequence of the event matters , where the click event occurs first and Change event the next ,So in your case you need to change the type of event handling to Click click here to see the sequence / priority of events happening after clicking on check box
$('.hello').on('click change', function(e){
e.stopPropagation();
alert('checkbox '+e.type);
});
This happens because e.stopPropagation(); is on change event and .child has click event. You can do this like in #rikpg example, but if you need change event, you should just add new one click event to checkbox that only has stopPropagation
http://jsfiddle.net/wppv2152/2/

Stopping click event using mousedown only works when triggering an alert

I'm trying to prevent the defined onclick events of the children of an element being run by returning false from the mousedown event on the container like so:
submit_container.mousedown(function(event){
return false;
});
If I write my code like this, it doesn't work. However, if I add an alert first, the click events are in fact stopped:
submit_container.mousedown(function(event){
alert('Alert');
return false;
});
The same issue was alluded to here, but sadly none of the answers address this.
EDIT: JSfiddle example. I want the behaviour of the second link, but without having to trigger an alert
The mousedown is working for the container class . Your problem is that a href has a click event attached to it not mouse down. So you should be using onclick on the container or the href as event Propagation will occur and bubble up to the parent . You can still stop this from happening .
Example.
submit_container.click(function(event){
event.stopPropagation();
event.preventDefault();
return false;
});
Hope this helps
Are you using jQuery? Try with a "preventDefault" method:
submit_container.mousedown(function(event){
event.preventDefault();
return false;
});

JQuery detecting click interactions on nested elements causing huge loop

Attempting to add a click event to a button that is nested between multiple elements (ul, div.col, li, div.panel, div.panel-body). I am able to access it with the below code, however as if I click on the page more than a few times the console.logs begin to loop and execute thousands of times.
I am nearly positive it is the nesting of the functions causing this. But I do not have a thorough enough background in JQuery to be able to tell exactly what the browser is doing.
Here is my JQuery code:
$('#displayList #col1').click(function(){
console.log('clicked col');
$('li').click(function(){
var id = $(this).attr('id');
console.log(id);
$('div.panel').click(function(){
console.log('clicked panel');
$('div.panel-body').click(function(){
console.log('clicked panel body');
$('button').click(function(){
console.log('clicked button');
return;
});
return;
});
return;
});
return;
});
return;
});
Could one of you wonderful JQuery gurus explain what is causing this bug and point me in a better path for checking if the button has been clicked or if it hasnt(just the panel was clicked).
Also, does anyone know a good and preferably free debugging program that I can use to step through JQuery code execution by execution?
Thank you so much for your knowledge
You are binding an event handler inside another event handler. So whenever the later event occurs, new handlers are added, Eventually causing multiple handlers for same event on same element.
Your code should look something like
$('#displayList #col1').click(function(){
console.log('clicked col');
});
$('li').click(function(){
var id = $(this).attr('id');
console.log(id);
});
$('div.panel').click(function(){
console.log('clicked panel');
});
$('div.panel-body').click(function(){
console.log('clicked panel body');
});
$('button').click(function(){
// The following will be executed when the button is clicked
console.log('clicked button');
});
Assume you have the following markup:
<div id="container>
<div id="parent">
<button>Click Me!</button>
</div>
</div>
And the event handlers:
$("#container").click(function(){
console.log("container got a click!");
});
$("#parent").click(function(){
console.log("parent got a click!");
});
$("#parent button").click(function(){
console.log("button got a click!");
});
Now if you click the button output will be
//button got a click!
//parent got a click!
//container got a click!
When you click an element, all of it's ancestors will also receive a click event by default, and the corresponding event handler will be called, if any - This is called event bubbling.
If you don't need any specific functionality then you don't need a handler so bubling won't hurt.
However, You can prevent this behaviour by calling the stopPropagation() method of event object inside the event handler:
$("#parent button").click(function(e){
e.stopPropagation();
console.log("button got a click!");
});
output will be
//button got a click!
There is one more event propagation method in some browsers (Only event bubbling model is supported by all the major browsers), you can read about it in detail #quirksmore: Event order
As DFTR mentioned in comments,
Visual studio allows break points in javascript code, when launching an application within internet explorer. Another debugging tool is firebug, which is a pretty neat firefox extension
Might help you.
if you need to bind event to button, you should use descendant selector
$('#displayList #col1 li div.panel div.panel-body button').click(function() {
console.log('clicked button');
});

Prevent child's onclick after mouseup on parent?

I have a parent element with mouse up and mouse down events attached on it, and a child element with a click event attached.
Is there any way to prevent the click event from happening in the child, after the mouseup event has been triggered in the parent?
An example, on the JSfiddle here, the goal is to make the inner square not turn to green if I click on it.
Ideally I would like to do it without modifying the $('#inner').on('click', function(){}). I already know that I can set a boolean on mouseup and check it on click but i'm trying to find a way to do it without modifying the click event.
Using jquery(or any other library) is option and I don't really have any restrictions other than not modifying the click method.
EDIT
Thanks #adeneo for the suggestion, that looks promising but it made me realize I missed a big part of the problem. Inside mouseup there will be a conditional check to see if the click should be prevented or not. If I remove the event can I somehow add it back after the click has been avoided? In a setTimeout for example. I'm not sure how(or if it's possible) to get the reference to the removed click function and then re-add the handler.
Hopefully this new fiddle here helps me to explain it a little bit better!
$('#inner').on('mouseup', function(e) {
$(this).unbind("click");
$(this).css({'background': 'black'});
});
Did you try like this?
Try e.stopImmediatePropagation(); in your inner code.
Just replace your code with the below code and check. To stop the click event of the inner div you can use preventDefault() or stopPropagation(). Please check below
$('#inner').on('click', function(e) {
$(this).stopPropagation();
// or
// $(this).preventDefault();
alert('inner click');
});
$('#outer').on('mousedown', function(e) {
$(this).css({'background': 'green'});
});
$('#outer').on('mouseup', function(e) {
$(this).css({'background': 'yellow'});
});
I'm pretty sure that this is the answer you're looking for :
$($(this)).children().click(function (event) { // Preveu la propagació del click als fills
// event.stopPropagation();
});

Is it possible to have jQuery.click trigger on the top element only?

I'm trying to make a site where the user can click on any element to edit it's CSS. I use the following to add the click function to all <li>, <div> and <ul>.
$('li,div,ul').click(function () {
alert(this.id);
});
The problem is if I click on a <li> element, then I get the alert for that and any element underneath it. (all the containers).
Is it possible to have only the top element trigger when clicked?
You want to stop event propagation, you do this in jQuery by calling the stopPropagation method on the event object.
$('li,div,ul').click(function (e) {
e.stopPropagation();
alert(this.id);
});
I believe you'd want to use stopPropagation(); inside the click function.
It sounds to me like you're looking for .stopPropagation(). Calling stopPropagation will prevent the event from "bubbling" up to parent containers.

Categories