简体   繁体   中英

Why is the onClick event triggered twice?

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.

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>

这也应该有效:

$($('#test1').parent()).trigger('click');

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 :

  1. .off()
  2. .unbind()
  3. e.stopImmediatePropagation()
  4. 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);
        }

})
 

I know I'm really late by answering this question and I'm sorry for that, but I had a similar problem recently and I managed to figure it out why, and I wanted to share it with all the future people which may come across with the same problem.

Why is the onClick event triggered twice?

This happens because in jQuery clicks are being propagated from the child element all the way up through each element to the parent element which holds the onClick handler.

I don't know exactly the reason why the developers of jQuery decided to propagate clicks honestly. If they wanted to somehow notify to an outerelement that an innerelement of them got clicked, they could have implemented the same functionality that the addEventListener() function has, but they didn't. I can't think of a reason why they would have done it, but that's how it is.

So, if you click on #test1 , but your onClick handler is on its span parent like this case, then a click will be triggered in both elements. And yes, even if you click on a child element like #test1 of an element which holds an onClick handler like the span parent, the handler will fire anyways.

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 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>

However, if your lack of control over your span also means that you "cannot select it through JavaScript", then the problem lies on that false premise. Because you can:

 // AFTER your <span></span> element got rendered by your third party tool: $('#test1').parent().attr('id', 'test1-container'); $('#test1-container').trigger('click');
 #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 onclick="alert('Boem')"> <button id="test1">test</button> </span>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM