stopPropagation() of a different event - javascript

How can I listen to a change event on a checkbox without triggering a click event on its container?
<label><input type="checkbox"> Hello world</label>
I want to trigger an action on the checkbox's change event, but I don't want it to bubble up to a click event on the label.
(function ($) {
$('input').change(function (v) {
v.stopPropagation();
});
$('label').click(function () {
alert('You should not see this message if you click the checkbox itself!');
});
})(jQuery);
http://jsfiddle.net/r49PA/
Any ideas? Thanks!

The issue is that two events are triggered when you click the checkbox -- a change and a click. You're only catching the change, so the click isn't ever being told to stop propagation. You need to either add a second handler on the checkbox for click events, or combine one handler to catch both types, like this:
$('input').on('change, click', function (v) {
v.stopPropagation();
});
Here's a jsFiddle demonstrating a combined handler: http://jsfiddle.net/r49PA/4/

You can stop propagation on click event instead of change event since you bind click event for the parent label:
$('input').click(function (v) {
v.stopPropagation();
});
Updated Fiddle

With plain javascript you can do something like this:
var stopPropagation = false;
selector.addEventListener('mousedown', function(event) {
// simulating hold event
setTimeout(function() {
stopPropagation = true;
// do whatever you want on the `hold` event
})
}
selector.addEventListener('click', function(event) {
if (stopPropagation) { event.stopPropagation(); return false; }
// regular event code continues here...
}
Since mousedown and click events are overlapping, we want the click event to not be triggered when we are trying to get the hold state. This little helper flag variable stopPropagation does the trick.

Related

How to add click event listener only after click event listener has been triggered?

I am trying to achieve the following functionality:
Once user has clicked on a button, I want to add click event listener to window element to alert a message (say).
Consider the below snippet for this purpose:
<button id="b1">click</button>
<script>
document.querySelector("#b1").addEventListener('click', () => {
window.addEventListener("click", () => {
alert("hello");
});
})
</script>
But, unfortunately, the above code also alerts message when the user initially clicks on button (which I don't want).
Any idea on how I can achieve the functionality?
It would be better to add the window click event listener and have a flag to determine if the alert should appear.
The problem with the method you are using is every time a user clicks the button you add a new event listener to the window. This will then stack up and fire multiple times for each click of the document.
To stop the button click from passing through to the document and also triggering the window event listener you can use the event stopPropagation() method as demonstrated below.
let hasButtonBeenClicked = false;
window.addEventListener("click", () => {
if(hasButtonBeenClicked) {
alert("hello");
hasButtonBeenClicked = false;
}
});
document.querySelector("#b1").addEventListener('click', (e) => {
e.stopPropagation()
hasButtonBeenClicked = true;
})
<button id="b1">click</button>

jquery: stop infinite recursion?

How do I stop the infinite recursion here so that a mousedown event can be triggered just once? should it be in a separate method?
$(document).on('mouseover',function (e) {
$(e.target).mousedown(function(e){
e.stopPropagation();
console.log('clicked');
$(e.target).trigger('mousedown'); //use hello(e); instead?
return;
})
});
$(document).on('mousedown', 'a', function(e){
hello(e);
});
function hello(e){
console.log('got it');
}
This seems to trigger a never ending loop. Basically I need to bind a mousedown handler on the currently element under the mouse, which will fire a mousedown event that another handler will be able to handle.
The reason I am doing this is because the mouseover works on dynamically generated element so when this happens I need to bind a handler again as the on handler is not able to catch the newly generated element.
You are making it complicated. Imagine everytime a user move his mouse an event will be added dynamically?
Why not design your element with class names and use it in your mousedown event? This way a sure call to mousedown will trigger always.
$(".className").mousedown(function(e){
console.log('clicked');
return;
})
--The reason I am doing this is because the mouseover works on dynamically generated element so when this happens I need to bind a handler again as the on handler is not able to catch the newly generated element.
If you say so then, add a className to your dynamically generated element to have your mousedown event bind to it.
try like this:
$(document).on('mouseover',function (e) {
$(e.target).trigger('mousedown'); //use hello(e); instead?
return;
});
$(document).on('mousedown','a', function(e){
hello(e);
});
function hello(e){
alert('got it');
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
hello

Attaching click event listener in onclick immediately calls that event listener

I am attaching a click event listener to the document after the user clicks on a specific element on the page. However, this event listener is immediately called after the onclick function is called which is undesirable. It seems to be using the same click event for both onclick and the just added document click listener.
How can I ensure the event listener I add to the document does not get called until the next click occurs?
document.getElementById('someID').onclick = function(e) {
document.addEventListener('click', myDocClickListener);
return false; //handled click
}
function myDocClickListener(e) {
//...
//should only be called for future clicks not the one that just occurred in the above function
}
This is happening because of event bubbling. You need to stop the bubbling in your handler:
document.getElementById('someID').onclick = function(e) {
e.stopPropagation();
document.addEventListener('click', myDocClickListener);
return false; //handled click
};
You will probably also need to keep track of whether you have attached the handler yet, so you don't end up attaching it twice if someID is clicked twice.
And unless this handler is on an a element, you don't really need to return false.
JLRishe's answer is correct, but if you don't want to do stopPropagation for some reason, you can add event listener in the next event loop:
document.getElementById('someID').onclick = function(e) {
setTimeout(
() => document.addEventListener(
'click',
myDocClickListener
),
0
);
return false; // only needed for <a>
};

Trigger click on child but prevent event propagation to parent

How do I trigger click on a child element without letting the click event bubble upto the parent & thereby create a infinite trigger loop of click event.
For example I have like this:
<li>
<a> ... </a>
</li>
I want to trigger a click event on a whenever li is clicked, but to prevent infinite trigger loop, I should avoid event propagation upto parent. How do I do that ?
Something like this?
$('li').on('click','a', function(e) {
e.stopPropagation();
// your code here...
});
By using .stopPropagation() on the anchor you can stop the bubbling. You should be able to use something like:
$('a').click(function (e) {
e.stopPropagation();
console.log('link');
});
$('li').click(function () {
$('a').click();
});
jsFiddle example
You do not state exactly the behavior you want from the click on the link, but if you simply want to stop the click being handled at all, use preventDefault() on the event argument of click:
$('li').on('click','a', function(e) {
e.preventDefault();
});
If you just want to stop the parent seeing the event use stopPropagation() instead:
$('li').on('click','a', function(e) {
e.stopPropagation();
});
The other option is return false, which does the same as both preventDefault() and stopPropagation()
$('li').on('click','a', function(e) {
return false;
});
use event.stopPropagation()() in the event callback.
$('selector').click(function(event){
event.stopPropagation()();
})
Parse the tag name on the parent click handler. (You could also look at class name or ID, among other event filters.) If desirable child tag is detected, then stop the propagation and return true so that this event runs. If desirable child tag is not detected, then prevent default event and return false. Thus, clicking on LI will trigger the click on A without a runaway event loop, and clicking on A will proceed properly without a runaway event loop either. Note also that you can't just fire the .click() event on the tag. You need to send it deeper into the native DOM element, using [0].click(), as I have shown below.
$('LI').click(function(e){
var sTag = e.target.tagName.toUpperCase();
if (sTag == 'A') {
console.log('DEBUG: A click');
e.stopImmediatePropagation();
return true;
} else {
console.log('DEBUG: ' + sTag + ' click');
e.preventDefault();
// the following won't work without the [0]
$(this).find('A')[0].click();
return false;
});

child click event firing parent mouseover event

I have tree structure in which mouse over on node name displays (UL) list. Each item in the list has a click event attached to it. The issue Im facing is when I click on any child item in list, it fires the mouseover event attached to parent span. Can you guys please help how to solve this issue?
<span id="treeNodeText">
<ul><li id="firstItem">First Item</li></ul>
</span>
My code is like this:
I have conman event attach method:
attachEvents(domId,eventType,callBackFunction,otherParams)
In attachEvent function I attach events to dom ids and assign appropriate call back functions
The mouseover event is fired before you click. So, apart with a delay, you can't prevent its handling.
Here's one way to deal with that :
var timer;
document.getElementById("treeNodeText").addEventListener('mouseover', function(){
clearTimeout(timer);
timer = setTimeout(function(){
// handle mouseover
}, 400); // tune that delay (depending on the sizes of elements, for example)
});
document.getElementById("firstItem").addEventListener('click', function(){
clearTimeout(timer); // prevents the mouseover event from being handled
// handle click
};
In JavaScript, events bubble up the DOM. Please read more about it: event order and propagation or preventDefault/stopPropagation.
In short, you can pervent event bubbling by
function callBackFunction(event){
event.stopPropagation()
}
or
function callBackFunction(event){
return false
}
return false also has the effect of preventing the default behavior, so it's technically equivalent to:
function callBackFunction(event){
event.stopPropagation()
event.preventDefault()
}
function myfunction(e){
e.stopPropagation()
e.preventDefault()
}
this will Help

Categories