jQuery Click fires twice when clicking on label

Jquery

Jquery Problem Overview


I am using jQuery to create custom radio buttons and i have a problem. When clicking on the label that associated with the radio the click events fires twice, if i click only on the radio itself it's working fine (well actually it's not the radio i am clicking but the div that wraps the whole input and label). Here is the code:

The HTML:

 <div id="box">
     <asp:RadioButtonList ID="RadioButtonList1" runat="server">
         <asp:ListItem>RADIO1</asp:ListItem>
         <asp:ListItem>RADIO2</asp:ListItem>
         <asp:ListItem>RADIO3</asp:ListItem>
     </asp:RadioButtonList>
</div>

jQuery:

<script type="text/javascript">
       $(function () {
            $('#box').find('input:radio').each(function (i) {

            var input = $(this);
            // get the associated label using the input's id
            var label = $('label[for=' + input.attr('id') + ']');
            // wrap the input + label in a div
            $('<div class="custom-radio"></div>').insertBefore(input).append(label, input);

            var wrapperDiv = input.parent();

            // find all inputs in this set using the shared name attribute
            var allInputs = $('input[name=' + input.attr('name') + ']');

            // necessary for browsers that don't support the :hover pseudo class on labels
            label.hover(

            function () {
                $(this).addClass('hover');
            }, function () {
                $(this).removeClass('hover checkedHover');
            });

            //bind custom event, trigger it, bind click,focus,blur events
            wrapperDiv.bind('updateState', function () {
                if ($(this)[0].children[1].checked) {
                    allInputs.each(function () {
                        var curDiv = $('div > label[for=' + $(this).attr('id') + ']').parent();
                        curDiv.removeClass('custom-radio-checked');
                        curDiv.addClass('custom-radio');
                    });
                    $(this).toggleClass('custom-radio custom-radio-checked');
                }
                else {
                    $(this).removeClass('custom-radio-checked checkedHover checkedFocus');
                }

            })
            .trigger('updateState')
            .click(function () { console.log('click'); })
            .focus(function () {
                label.addClass('focus');
            }).blur(function () {
                label.removeClass('focus checkedFocus');
            });
        }); 
       });
   </script>

Is there any solution for this behaviour?

Jquery Solutions


Solution 1 - Jquery

I tried adding the solution above by adding:

evt.stopPropagation();
evt.preventDefault();

but didn't work. However adding this:

evt.stopImmediatePropagation();

solved the problem! :)

Solution 2 - Jquery

Try adding:

evt.stopPropagation();
evt.preventDefault();

to the .bind() or .click(), whichever you're seeing. Also, add the parameter evt to the function, like function(evt) {...

Solution 3 - Jquery

Bind the click event to the input rather than the label. When the label is clicked - the event will still occur because, as Dustin mentioned, a click on the label triggers a click on the input. This will allow the label to hold its normal functionality.

$('input').click();

Instead of

$('label').click();

Solution 4 - Jquery

If you're trying to use an outer container as a click element you can also let the events bubble naturally and test for the expected element in your click handler. This scenario is useful if you're trying to style a unique click zone for a form.

<form>
<div id="outer">
    <label for="mycheckbox">My Checkbox</label>
    <input type="checkbox" name="mycheckbox" id="mycheckbox" value="on"/>
</div>
</form>
<script>
$('#outer').on('click', function(e){
    // this fires for #outer, label, and input
    if (e.target.tagName == 'INPUT'){
        // only interested in input
        console.log(this);
    }
});
</script>

Solution 5 - Jquery

To fix this the easy way, remove the "for" attribute on the label. A click on the label will also trigger a click on the associated element. (which in your case is firing your click event twice.)

Good luck

Solution 6 - Jquery

I usually use this synthax

.off('click').on('click', function () { console.log('click'); })

instead of

.click(function () { console.log('click'); })

Solution 7 - Jquery

I have tried by adding solution.

evt.stopPropagation();
evt.preventDefault();

but didn't work.

By adding

evt.stopImmediatePropagation();

solved the problem! :)

Solution 8 - Jquery

Best answer is hidden inside comments:

> you should actually bind to change even on the radio button since the > text of a label is clickable -- they don't always click the radio > button itself. – chovy Dec 12 '13 at 1:45

This fiddle illustrates that all the other solutions – stopPropagation, stopImmediatePropagation, preventDefault, return false – either change nothing or destroy the checkbox/radio functionality). It also illustrates that this is a vanilla JavaScript problem, not a jQuery problem.

EDIT: Another working solution that I just found in another thread is to bind the onclick to the input rather than the label. Updated fiddle.

Solution 9 - Jquery

The problem with e.preventDefault(); is it stops the label click from checking the radio button.

A better solution would be to simply add a "is checked" quick check like so:

$("label").click(function(e){
  var rbtn = $(this).find("input");
  if(rbtn.is(':checked')){
  **All the code you want to have happen on click**
  }
)};

Solution 10 - Jquery

My problem is a bit different, as the evt.stopPropagation();evt.preventDefault(); doesn't work for me, I just add return false; in the end, then it works.

$("#addressDiv").on("click", ".goEditAddress", function(event) {
	alert("halo");
	return false;
});

Solution 11 - Jquery

In my case the problem was that i had the click event in a function and the function was executed twice.... every execution of the function creates a new click event. -facepalm-

after moving the click event outside the function, everything worked as expected! :)

Solution 12 - Jquery

Try put your input tag outside trigger element, because label tag emulates click, so you will have always more than one call.

Solution 13 - Jquery

I had the same issue because I had nested my radio inside the label like this with the handler attached to radio_div. Removing the nested label fixed the issue.

<div id="radio_div">
    <label>
       <input type="radio" class="community_radio" name="community_radio" value="existing">
           Add To Existing Community
    </label>
</div>

Solution 14 - Jquery

The label triggers the radio/checkbox to be checked.

if ($(event.target).is('label')){
    event.preventDefault();
}

It prevent especially the label to trigger this behavior.

Solution 15 - Jquery

The click on the label with a for="some-id" attribute triggers a new click, but only if the target exists and is an input. I was not able to solve it perfectly with e.preventDefault() or stuff like that so I did it like this:

For example, if you have this structure and want an event on clicking .some-class

<div class="some-class">
    <input type=checkbox" id="the-input-id" />
    <label for="the-input-id">Label</label>
</div>

What did work was:

$(document)
    .on('click', '.some-class', function(e) {
        if(
            $(e.target).is('label[for]')
            &&
            $('input#' + $(e.target).attr('for')).length
        ) {
            // This will trigger a new click so we are out of here
            return;
        }

        // else do your thing here, it will not get called twice
    })
;

Solution 16 - Jquery

$(document).on('click','.class',function() {
    alert('abc')
})

In my case it fired 2 times because I included this code 2 times like assets/js/test.js 2 times.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestiontoneView Question on Stackoverflow
Solution 1 - JqueryN3daView Answer on Stackoverflow
Solution 2 - JqueryJordanView Answer on Stackoverflow
Solution 3 - JquerydougmacknzView Answer on Stackoverflow
Solution 4 - JquerytobiusView Answer on Stackoverflow
Solution 5 - JqueryDustinView Answer on Stackoverflow
Solution 6 - JqueryDaliborView Answer on Stackoverflow
Solution 7 - JqueryJanki MoradiyaView Answer on Stackoverflow
Solution 8 - JqueryWoodrowShigeruView Answer on Stackoverflow
Solution 9 - JqueryyoshyoshView Answer on Stackoverflow
Solution 10 - JquerySam YCView Answer on Stackoverflow
Solution 11 - JqueryFalcoBView Answer on Stackoverflow
Solution 12 - JqueryBenjaminView Answer on Stackoverflow
Solution 13 - Jqueryshaw2thefloorView Answer on Stackoverflow
Solution 14 - JqueryKevin.BView Answer on Stackoverflow
Solution 15 - JqueryJulesezaarView Answer on Stackoverflow
Solution 16 - JqueryAbdul MujeebView Answer on Stackoverflow