jQuery click event handler is called twice for a checkbox

I have a problem with the following code in an ASPX page:

<script type="text/javascript">
$(document).ready(function() {
    $('.test').click(function() {
        alert("click")
    })
});
</script>

<asp:CheckBox runat="server" Text="Checkbox XYZ" CssClass="test" ID="cb1" />

In the browser (FF3.5 / IE8) I have the following problem:
  • if I click the checkbox (the small square), it works as expected
  • if I click the checkbox’s text (“Checkbox XYZ”), then the click event is fired twice, and the alert is shown twice.

I guess this has to do with the way the checkbox is rendered to HTML, which is like this:

<span class="test">
 <input id="ctl00_c1_cb1" type="checkbox" name="ctl00$c1$cb1" checked="checked"/>
 <label for="ctl00_c1_cb1">Checkbox XYZ</label>
</span>

How do I correctly setup the click event handler to prevent it from being called twice?

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

I have just experienced the same thing, but am not sure that event bubbling is causing my issue. I have a custom tree control, and when an item is opened, I use $(id).click() to attach a handler to all elements of a certain kind.

I suspect that this means that existing items elsewhere that already have the event, may then have it added again. I found that unbinding everything then re-binding solved my problem, thus:

$('img.load_expand').unbind("click").click(function()
{
  // handler
});

Method 2

I think it’s because a <label> with a for attribute raises the click event of <input type="radio"> or <input type="checkbox"> element that is associated for when clicked.

So in your jQuery code, you set up a click event handler for both the <label> and the <input> inside <span class="test">. When clicking on the <label>, the click event handler that you set up on the label will execute, then the click event handler set up on the <input> will execute when the label raises the click event on the <input>.

Method 3

$(document).ready(function() {
    $('.test').click(function(event) {
                    event.stopImmediatePropagation();
                    alert("Click");
                    })
                 }
              );

I was able to get my code working by stopping the event Propagation. It did not affect the status change of the checkbox.

Method 4

Well after reading my question again, I found a way how to solve it.

Just add “input” to the jQuery selector:

<script type="text/javascript">
$(document).ready(function() {
        $('.test input').click(function() {
                alert("click")
        })
});
</script>

Method 5

Just use .mouseup rather than .click

Method 6

What you are seeing is event bubbling. The click event is first handled by the label and is then passed on to the checkbox. You get one alert for each. To prevent event bubbling you need to return false in your click handler.

$(document).ready(function() {
        $('.test').click(function() {
                alert("Click");
                return false;
        })
});

However while this prevents event bubbling it also has the undesirable side effect of preventing the checkbox from changing state. So you’ll need to code around that.

Method 7

Solved: this to work with Firefox 3.6.12 and IE8.

$(function(){
        $("form input:checkbox").unbind("click")
        .click(function(){
            val = $(this).val();
            alert(val);
        })
    }

The trick is to unbind("click"). before bind it to .click(fn); this will disabled the same event to fire twice.

Note that event “change” will not tricker at first time checkbox has been checked. So I use “click” instead.

Method 8

I ran into the same issue with a click event, and found this article. In essence, if you have more than one jQuery document-ready functions inside the
<body></body>
tags, you can get multiple events. The fix is, of course, to not do that, or to unbind the click event and rebind it, as noted above. Sometimes, with multiple javascript libraries, it can be hard to avoid multiple document.ready()’s, so the unbind is a good workaround.

<code>
$('#my-div-id').unbind("click").click(function()
  {
    alert('only click once!');
  }
</code>

Method 9

I know the question is far closed now, but I just have faced the same problem and I want to add the solution I found, may come in handy for similar problems on the future.

When you add ASP code like:

<asp:CheckBox runat="server" Text="Checkbox XYZ" CssClass="test" ID="cb1" />

the problem is that <asp:CheckBox ...> is not an html control, it’s just something ASP made up from the twisted mind of some psycho invented, so the browser will receive something else.

The browser will receive something like:

<span class="test">
    <input id="garbageforYourId_cb1" type="checkbox" name="garbage$moregarbage$cb1"/>
    <label for="evenMoreGarbage_cb1">Checkbox XYZ</label>
</span>

One of many possible solutions:

The browser receive a span which content an input “checkbox” and a label for it with your text. Therefore my solution for this would be something like:

$('.test > :checkbox').click(function() {
    if ($(this).attr("checked")) {
        alert("checked!!!");
    } else {
        alert("non checked!!!");
    }
});

What happened up there? This selector $('.test > :checkbox') means: find the elements with the class “test” and bring any checkbox that it contains.

Method 10

The function runs twice. Once from the inside and then it gets called again from inside itself. Simple add a return statement at the end.

<script type="text/javascript">
$(document).ready(function() {
    $('.test').click(function() {
        alert("click");
        return false;
    })
});
</script>

<asp:CheckBox runat="server" Text="Checkbox XYZ" CssClass="test" ID="cb1" />

This worked perfectly for me.

Method 11

I had the same problem with the selector. And end up using off() function.

$('body').off('click').on('click', '<your selector>', function(){
    // Your code                
});


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x