Dommicentl
Dommicentl

Reputation: 751

Why is the onClick event triggered twice?

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.

Upvotes: 42

Views: 128867

Answers (13)

R&#233;mi
R&#233;mi

Reputation: 1

In my case I add event listener on a parent div which trigger click event. In this event listener I need to trigger click event on hidden input. So the second click call the first and I got 2 calls. To avoid this behavior I dd event listener on the input to stop propagation event.

item.addEventListener('click', (event) => {

      event.stopPropagation();
      event.preventDefault();

      var checkbox = item.querySelector('input[type="checkbox"]');
      if (checkbox) {

        checkbox.click();
        item.classList.toggle('is-selected');
      }
    });

    item.querySelector('input').addEventListener('click', function (event) {

      // Avoid that the click on checkbox trigger parent event.
      event.stopPropagation();
    })
  });

Upvotes: 0

Michel H
Michel H

Reputation: 1

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

Upvotes: 0

Bhushan Kawadkar
Bhushan Kawadkar

Reputation: 28523

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

Upvotes: 40

A.T.
A.T.

Reputation: 26382

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

Upvotes: 13

Scott L
Scott L

Reputation: 549

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

Upvotes: 0

shawn peng
shawn peng

Reputation: 9

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

});

Upvotes: 0

Mat&#237;as Fuentes
Mat&#237;as Fuentes

Reputation: 1

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>

Upvotes: 0

viveknaskar
viveknaskar

Reputation: 2225

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.

Upvotes: 36

Sanaulla
Sanaulla

Reputation: 1659

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.

Upvotes: 1

adprocas
adprocas

Reputation: 1913

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.

Upvotes: 0

Deepu Sasidharan
Deepu Sasidharan

Reputation: 5309

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>

Upvotes: 0

jaakkoj
jaakkoj

Reputation: 131

This should also work:

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

Upvotes: 0

Jacob
Jacob

Reputation: 164

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

Upvotes: 6

Related Questions