40

I have the following HTML content:

<span onclick="alert('Boem')">
    <button id="test1">test</button>
</span>

When I call the following JavaScript code:

$('#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/

I do not know the contents of the onclick listener of the span. This is also generated by the third-party tool. I want the click trigger to execute this onclick like it does now, but only once.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Dommicentl
  • 721
  • 1
  • 5
  • 12
  • 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

12 Answers12

38

It is calling twice because the button is inside a span and span has onclick="alert('Boem')", hence when you trigger click on the button then it shows an alert and the same click event propagates to span and shows the alert once again.

You need to stop default behaviour of button using below code:

$(function(){
    $('#test1').click(function(e){e.preventDefault();}).click();
});

Demo

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Bhushan Kawadkar
  • 28,279
  • 5
  • 35
  • 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
35

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
  • 2,136
  • 1
  • 20
  • 35
12

To stop event propagation, use: stopPropagation

$( "#test1" ).on( "click", function(ev) {
    ev.stopPropagation();
});

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

Please note the order events are assigned in DOM.

Demo

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
A.T.
  • 24,694
  • 8
  • 47
  • 65
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
1

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
  • 1,329
  • 14
  • 13
0

This question 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 code abstracted out of the HTML:

http://jsfiddle.net/v4100zke/3/

$('#test1').click(function() {
    alert('Boem')
});
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Scott L
  • 549
  • 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
  • 5,193
  • 10
  • 40
  • 97
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,863
  • 1
  • 14
  • 31
0

Note that you have used jQuery's click method. It will emit both the 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 alerts twice.

Check this demo to figure it out.

As for how to deal with it, just use stopPropagation as in previous answers.

$('#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()})

});
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
0

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 is to programmatically 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>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
  • (Despite its weird form, this answer was probably ***not*** plagiarised, [ChatGPT](https://meta.stackoverflow.com/questions/421831/temporary-policy-chatgpt-is-banned) or otherwise.) – Peter Mortensen Jun 21 '23 at 15:02
0

In my case don't have a nested button, but I had the same problem. I solved adding 'return false;' at the end of the event.

$('#test1').click(function() {
    alert('Boem');
    return false;
});
Michel H
  • 1
  • 1