35

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.

Flimzy
  • 68,325
  • 15
  • 126
  • 165
Dommicentl
  • 651
  • 1
  • 5
  • 11
  • 1
    , use this – cracker Aug 12 '14 at 12:50
  • http://stackoverflow.com/questions/4616694/what-is-event-bubbling-and-capturing – turtle Aug 12 '14 at 12:53
  • 1
    At least if you don't have control to the span, you could do `$('#test1).parent().trigger('click')` – Hemadeus Aug 12 '14 at 12:54
  • 1
    Possible duplicate of [Why the onclick element will trigger twice for label element](https://stackoverflow.com/questions/24501497/why-the-onclick-element-will-trigger-twice-for-label-element) – Martijn Apr 10 '18 at 07:24

11 Answers11

31

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

Bhushan Kawadkar
  • 27,908
  • 5
  • 34
  • 57
  • But I do want to propagate to the parent span because that is where the click event is (And I cannot control it). I just want it to fire the event only once so show 'boem' only once – Dommicentl Aug 12 '14 at 12:56
  • Is there any requirement to fire click event on page load? – Bhushan Kawadkar Aug 12 '14 at 12:57
  • Nope this is not a requirement – Dommicentl Aug 12 '14 at 12:59
  • If I prevent propagation I would expect that nothing is executed because the button itself does not have a onclick attribute? – Dommicentl Aug 12 '14 at 13:10
  • have you checked my updated answer demo link, is this what you are looking for? What is your requirement exactly? – Bhushan Kawadkar Aug 12 '14 at 13:11
  • The behaviour of your code is indeed the behaviour I need. Just seeking the why? So when a fire an onclick event on the button, jquery will find all handlers of this event for that button including the handlers of his parents. Next for every parent the same happens because of the propagation. Is this correct? So by stopping the propagation only all the handlers of the button are executed but this includes the handler of the span? – Dommicentl Aug 12 '14 at 13:18
  • Here in your case, we are preventing button's default onclick behaviour and not stopping propagation of click event. And when we click on button its click event propagate to its parent span which triggers its onclick function. – Bhushan Kawadkar Aug 12 '14 at 13:21
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/59187/discussion-between-vogabe-and-bhushan-kawadkar). – Dommicentl Aug 12 '14 at 13:35
  • Oke thanx for the clarification. If I would use the stop propagation instead of the preventDefault, my explaination of the behaviour in my previous comment is correct? – Dommicentl Aug 12 '14 at 13:36
  • `e.stoppropagation()` will stop the bubling of event towards parent element in DOM, for more info see [this](http://www.w3schools.com/jquery/event_stoppropagation.asp). And `.click()` will trigger click event on button element but it will not call the bind click function but default click behaviour for first time. hence showing alert in onclick of span. see for [this](http://api.jquery.com/click/) more information. – Bhushan Kawadkar Aug 13 '14 at 05:05
  • Also to know difference in stoppropagation and prevendefault see [this](http://stackoverflow.com/questions/5963669/whats-the-difference-between-event-stoppropagation-and-event-preventdefault) – Bhushan Kawadkar Aug 13 '14 at 05:05
  • Also use $(function(){ $('#test1').click(function(e){ e.stopImmediatePropagation(); }); }); – Tolgahan Özgür Jan 03 '18 at 09:32
23

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.

viveknaskar
  • 1,814
  • 1
  • 17
  • 31
10

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

A.T.
  • 21,626
  • 7
  • 42
  • 63
5

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

Jacob
  • 153
  • 5
  • 5
    But why does it trigger 2 times. I know that the trigger on the button also triggers the parents so in this case the span, but it is the only element with an onclick. So I would expect that this onclick will trigger only once? – Dommicentl Aug 12 '14 at 13:02
0

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.

Community
  • 1
  • 1
Scott L
  • 539
  • 1
  • 6
  • 13
0

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>
Deepu Sasidharan
  • 4,987
  • 8
  • 35
  • 89
0

This should also work:

$($('#test1').parent()).trigger('click');
jaakkoj
  • 121
  • 6
  • That was indeed the solution I used to solve the problem temporary. I asked this question to understand the why of this behaviour ;-). And maybe find a more elegant solution. – Dommicentl Aug 12 '14 at 13:34
0

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.

adprocas
  • 1,833
  • 1
  • 14
  • 29
0

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

});
0

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.

Sanaulla
  • 947
  • 9
  • 10
0

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

})
 
nano dev
  • 275
  • 3
  • 6