Why is the onClick event triggered twice? - javascript

I have the following html:
<span onclick="alert('Boem')">
<button id="test1">test</button>
</span>
When I call the following javascript:
$('#test1').trigger('click');
The onclick event is triggered twice, while I expect it to just trigger once. Because JQuery should look up in the DOM tree and find only one onclick.
I do not have control of the span, it is generated in a third party tool. I do have control over the button and his parameters.
You can find a JSFiddle example here:
http://jsfiddle.net/Voga/v4100zke/
Update
I do not know the contents of the onclick listener of the span. This is also generated by the 3rd party tool. I want the click trigger to execute this onclick like it does now, but only once.

It is calling twice because button is inside a span and span has onclick="alert('Boem')", hence when you trigger click on button then it shows alert and same click event propagate to span and shows alert once again.
you need to stop default behaviour of button using below code :
$(function(){
$('#test1').click(function(e){e.preventDefault();}).click();
});
Demo

I was also getting a similar issue where I had to download a pdf which was downloading twice. I used jQuery's stopImmediatePropagation method.
$( "#test1" ).on("click", function(e) {
e.stopImmediatePropagation();
});
$('#test1').trigger('click');
stopImmediatePropagation will prevent any parent handlers and also any other handlers from executing. Refer here for more details.

to stop event propagation use :stopPropagation
$( "#test1" ).on( "click", function(ev) {
ev.stopPropagation();
});
$('#test1').trigger('click');
Please note, in order events are assigned in DOM.
DEMO

Bubbling. The click event on the child also happens on the parent (span).

This thread will help answer the 'why' of it.
A better way would be to just assign a click handler to the element so as to keep your Javascript abstracted out of the HTML:
http://jsfiddle.net/v4100zke/3/
$('#test1').click(function() {
alert('Boem')
});
Hope that helps.

This should also work:
$($('#test1').parent()).trigger('click');

Here button click is triggered. Since the button is inside the span and onclick event is defined for span the two alert are happened.
One is by the button
and
other by its parent(parent have onclick event and button click is triggered).
To avoid two alert, use this
<span>
<button onclick="alert('Boem')" id="test1">test</button>
</span>

I had the same problem. Mine was the fact that I was using .trigger('.element') and there were two elements with that element class.
So, I got more specific, and used .trigger('.parent .element') to ensure only one click event happened on a single element, instead of one click event on two elements.

Note that you have used jQuery's click method, it will emit both dom's mouse click event and jquery's click event. Then both jquery's click Event and dom's mouse click event are propagated to the span element and its onclick listener is triggered twice hence it alert twice
check this demo
to figure it out
as for how to deal with it, just use stopPropagation as answers above
$('#test1').click(function() {
// comment this line and run, 'parent' will be alerted TWICE!!! since both mouseEvent and jQuery.Event trigger the onclick listener
$('#children').click(function(e) {e.stopPropagation()})
});

I also face this problem on Modal
Solved by the following tricks -
$('#saveButton').off('click').on('click', { modal: modal }, save)
Here off('click') prevents the save method fires multiple times.

I have tried all the above given advice, but unfortunately non of the above works for me.
"myBtn" is individual div in my case, so using flag and setTimeout I have achieved my desired result. Please advice.
I have tried :
.off()
.unbind()
e.stopImmediatePropagation()
e.preventDefault();
Below is the working code for me, I know its not a good practice, But for now I dont have any solution. Please advice
var isClicked = false;
$("#myBtn").on("click",function(e){
if(!isClicked){
isClicked = true;
console.log("button clicked");
setTimeout(function(){
isClicked = false;
},3000);
}
})

Why is the onClick event triggered twice?
This happens because of bubbling. This is because, as javascript.info says: "events “bubble” from the inner element up through parents like a bubble in the water".
How do I solve it?
If your third party tool generates your <span></span> element with the onclick attribute included, this probably means that your tool wants you to treat your span directly as your button, without the necessity of creating an additional one as you're doing with your <button></button> element.
Here, to fix this error, the best way it's to programatically click the SAME element that contains the handler to avoid propagation:
$('#test1').trigger('click');
/* Now, you can take #test1 and make it look and function as a button */
#test1 {
padding: 10px 20px;
color: white;
background-color: #0078d7;
font-size: 2rem;
font-family: Helvetica;
}
#test1:hover {
cursor: pointer;
background-color: blue;
transition: all 0.25s;
}
<!-- Script to include jQuery v3.3.1 -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span id="test1" onclick="alert('Boem')">test</span>

Related

Triggering button click in jQuery not working

Using dot.js I'm adding a button to a specific web page that, when clicked, should add some text to a text field and then trigger another button to also be clicked. I simulate this by adding a click handler to my button which has this code:
var button = $('.some-class').find('button')[0];
console.log(button); // element I expect
button.click();
However, this doesn't work and I'm not sure why. If instead of .click() I perform .remove(), the button is removed from the page. If I use the console to execute the same code, the button does get clicked. This tells me I do have the right element, but there is something wrong with the click() event specifically.
Can someone explain why this isn't working in either Safari or Chrome? I've tried a lot of different things, but I'm new to jQuery so I'm probably missing some detail in how that works.
We went to the bottom of this in the chat. What probably caused the problem was another event-handler attached to (possibly) body, that undid the click.
So the solution was to stop the event from propagating:
event.stopPropagation();
While assigning the click event handler to the button you should use jquery on
This should ensure that whenever a new button with added with same selector (as in when event was assigned), event handled will be assigned to that button
Some examples here
The problem is the click() function is from jquery and you're attempting to fire the click function from the DOM object.
Try
$(button).click();
Here's a plunk.
http://plnkr.co/edit/2pcgVt
You can use the following statement.
var button = $('.some-class').find('button')[0].trigger('click');
try jquery's trigger() function:
$(button).trigger('click');
see jsfiddle: https://jsfiddle.net/665hjqwk/

Bootstrap - Icon toggle with jquery

I got a little problem trying to toggle an icon of Bootstrap. When i run code it does what expected the first time you click on the icon it toggle's, but when i click again it doesn't change. Here its my code and any help will be appreciated!
<a><i class="icon-plus"></i></a>
<script>
$(".icon-minus").click(function(){
$(this).removeClass("icon-minus").addClass("icon-plus");
});
$(".icon-plus").click(function(){
$(this).removeClass("icon-plus").addClass("icon-minus");
});
</script>
Update 1:
This icon is for a collapsible menu and the code of that can be found here :)
jsBin demo
$(".icon-minus, .icon-plus").click(function(){
$(this).toggleClass("icon-minus icon-plus");
});
Or this if you dynamically create your elements:
$("#parent_el_NOT_dyn_gen").on('click','.icon-minus, .icon-plus',function(){
$(this).toggleClass("icon-minus icon-plus");
});
The jQuery's selector selects DOM elements then applys the click handler to them. It's not re-evaluating the selector after you change the classes on the element.
You probably want the delegate() / on() method from jQuery to dynamically change the the handler that's fired when the item is clicked. Delegate works with event bubbling and will handle the click and evaluate if the source of the click matches the selector (at the time of the click) as opposed to the .click() which attaches the handler directly, once (at the time of page-load or whenever the code was ran).
Another solution is to change the handler somehow, either by evaluating what class is on the existing element or using toggleClass() which will check for a class then invert it.
$(".icon-minus, .icon-plus").click(function() {
var $this = $(this);
if ($this.hasClass("icon-plus")) {
$this.removeClass("icon-plus").addClass("icon-minus");
return;
}
if ($this.hasClass("icon-minus")) {
$this.removeClass("icon-minus").addClass("icon-plus");
return;
}
});
This method will be slightly faster than using on() / delegate() because it's handled at the root handler and not bubbled & checked afterwards. It's also not susceptible to any breaks in the event bubbling. (ie. event.stopPropagation())
Simple solution worked for Bootstrap 3.
$('[data-toggle="collapse"]').click(function(e) {
$(e.target).find('.icon-minus-sign, .icon-plus-sign').toggleClass("icon-minus-sign icon-plus-sign");
});

Multiple OnClick JQuery events firing

I have a page with div and a button on it. I have added onClick event to both of them. Now when I click the button on the div the onClick of the div is also being executed. Is there any way that I can avoid this?
Thank You,
Try this, pass the event as parameter to your onclick event and call
event.stopPropagation();
event.preventDefault();
Your onclick event assignment should be:
$(button).click(function(event) {
// script here
event.stopPropagation();
event.preventDefault();
});
In your click handler you might want to use "stopPropagation" for example:
$("button").click(function(e) {
// handle this event
// ...
// don't pass this event up to parent handlers
e.stopPropagation();
} );
There's also a related function that you might want to read about called "preventDefault" which tells the browser not to do what it normally does automatically (e.g. submit a page when a submit button is clicked)
See also:
https://developer.mozilla.org/en/DOM/event.stopPropagation
http://api.jquery.com/event.stopPropagation/
What's the effect of adding 'return false' to a click event listener?
http://fuelyourcoding.com/jquery-events-stop-misusing-return-false/
in the listener for the link element, you can put e.stopPropagation(), which should fix it (if you're using event bubbling).
If you aren't using jQuery, make sure you set the useCapture parameter of addEventListener() to False info - MDN; you want to be sure you know which direction your events are moving through the DOM (you want them to bubble).
You need to prevent the button onClick event from bubbling to the Div. So basically at the end of your onClick function for the button, once you have done all you logic, you need to call event.stopPropagation()
If none of the above work, try out:
$("button").click(function(e) {
e.stopImmediatePropagation();
});

how to select the rest of a div?

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();
});

Performing an action on Parent/Child elements independently

I have HTML similar to the following in my page
<div id="someDiv">
<img src="foo.gif" class="someImg" />
</div>
The wrapper div is set up such that when it is clicked, it's background-color changes using the following jQuery code.
$("div").click(function(event){
$(this).css("background-color", "blue");
});
I also have some jQuery associated with my img that will do some other function (for the sake of argument I am going to display and alert box) like so:
$("img[class=someImg]").click(function(event){
alert("Image clicked");
});
The issue I have come across is that when I click on the img, the event associated with the div is also triggered. I'm pretty sure that this is due to the way that jQuery (or indeed JavaScript) is handling the two DOM elements - clicking the img would require you to also technically click the div, thus triggering both events.
Two questions then really:
Is my understanding of the
DOM/JavaScript flawed in some way or
is this actually how things are
occurring?
Are there any jQuery methods that
would allow me to perform actions on
a child element without invoking
those associated with its parent?
That is known as event bubbling, you can prevent it with stopPropagation():
$("img[class=someImg]").click(function(event){
alert("Image clicked");
event.stopPropagation();
});
.
Is my understanding of the DOM/JavaScript flawed in some way or
is this actually how things are
occurring?
That is because of what is known event bubbling.
Are there any jQuery methods that would allow me to perform actions
on a child element without invoking
those associated with its parent?
Yes, you need stopPropagation()
No, this is by design. Events bubble up through the entire dom, if you put another handler on body, it would fire too
Yes :) JQuery normalizes the event object, so adding event.stopPropagation() in your img click handler will give you the behavior you expect on all browsers
The problem you just facing is called "event bubbling". That means, if you click on a nested
element, that click event will "bubble up" the DOM tree.
If other elements also are bound to an click event, their listeners will fire aswell.
Solution to prevent this is called:
stopPropagation()
which is used within your event handler
$("img[class=someImg]").click(function(event){
event.stopPropagation();
alert("Image clicked");
});
This is what's called event bubbling, and you can stop it to get the behavior you want with .stopPropagation() (or return false; if you want to stop the event completely, including handlers on the same level), like this:
$("img[class=someImg]").click(function(event){
alert("Image clicked");
event.stopPropagation();
});
You can view a demo here, comment it out and click run again to see the difference.
The short version is that when most event types happen, they happen on the immediate element, then bubble up the DOM, occurring on each parent as they go. This is not jQuery specific at all, native JavaScript does this. If you're more curious, I'd read the linked article, it has a great explanation of what's going on.

Categories

Resources