3

I am writing a custom survey view, which replaces check boxes with "buttons" which are just regions rendered with CSS.

I am trying to trigger an event when a region is clicked. When the region outside of the text is clicked, the event is triggered, but when the text is clicked, nothing happens. I am very new to jQuery (started several days ago). Am I missing something completely obvious? Thanks

$('.checkbox-select').click(function () {
    var checked_length = $(this).has(".checked").length;
    if (checked_length == 0) {
        $(this).find('[type=checkbox]').addClass('checked');
        $(this).find('[type=checkbox]').prop('checked', true);
        $(this).find('label').css({
            "font-style": "italic"
        });
        $(this).css("background-color", "#6CCACD");
    } else {
        $(this).find('[type=checkbox]').removeClass('checked');
        $(this).find('[type=checkbox]').prop('checked', false);
        $(this).css("background-color", "#67517A");
        $(this).find('label').css({
            "font-style": ""
        });
    }
});

Here is the problem reproduced: http://jsfiddle.net/m8r4xp6b/

Ethan
  • 45
  • 6

3 Answers3

3

This is happening because your label is using the "for" attribute, and when you're clicking on the text it's causing the event to fire twice. Clicking on a label with a for attribute causes the checkbox to be checked or unchecked (or if it's a different input type for it to have focus).

The answers provided by XGreen and Deepak above should both work.

Here's an updated jfiddle where it's working without adding an event.preventdefault method or removing your for attribute. http://jsfiddle.net/m8r4xp6b/21/

$('.checkbox-select').click(function () {
    var litem = $(this);
    var chk = litem.find('[type=checkbox]');
    var lbl = litem.find('label');
    var checked = chk.is(':checked');
    if(!checked) {
      chk.addClass('checked');
      chk.prop('checked', true);
      lbl.css({"font-style": "italic"});
      litem.css("background-color", "#6CCACD");
    }
    else {
       chk.removeClass('checked');   
       chk.prop('checked', false);
       litem.css("background-color", "#67517A");
       lbl.css({"font-style": ""});
    }
});
2

Add e.preventDefault();

$('.checkbox-select').click(function (e) {    
  var checked_length = $(this).has(".checked").length;
    if( checked_length == 0 ) {
      $(this).find('[type=checkbox]').addClass('checked');
      $(this).find('[type=checkbox]').prop('checked', true);
      $(this).find('label').css({"font-style": "italic"});
      $(this).css("background-color", "#6CCACD");
    }
    else {
       $(this).find('[type=checkbox]').removeClass('checked');   
       $(this).find('[type=checkbox]').prop('checked', false);
       $(this).css("background-color", "#67517A");
       $(this).find('label').css({"font-style": ""});
    }
    e.preventDefault();
});

Also make your label non-seletable:

label {
    -webkit-user-select: none; /* webkit (safari, chrome) browsers */
    -moz-user-select: none; /* mozilla browsers */
    -khtml-user-select: none; /* webkit (konqueror) browsers */
    -ms-user-select: none; /* IE10+ */
}

Link to jsfiddle

Your click is happening twice due to a mechanism called Event Bubbling and Capturing. It means that if you fire an event of a parent it's children will also fire that even if they have that handler attached to them.

Read more about here if you like

Community
  • 1
  • 1
makeitmorehuman
  • 11,287
  • 3
  • 52
  • 76
  • Actually the click event was triggered twice. Why it was happening so? – Govan Jan 27 '15 at 13:55
  • The label is causing your input click event to fireup twice. If you preventDefault it will prevent that default bubbling behavior. Explained in the answer with reference links – makeitmorehuman Jan 27 '15 at 14:10
  • Thanks so much. This is the best answer for my specific case, as I am working with a form that renders from Django and I don't have much control over its structure. I really appreciate how responsive everyone was to a back-end type who is new to js! – Ethan Jan 27 '15 at 14:25
0

Just remove the label .

$('.checkbox-select').click(function() {
  var checked_length = $(this).has(".checked").length;
  if (checked_length == 0) {
    $(this).find('[type=checkbox]').addClass('checked');
    $(this).find('[type=checkbox]').prop('checked', true);
    $(this).find('label').css({
      "font-style": "italic"
    });
    $(this).css("background-color", "#6CCACD");
  } else {
    $(this).find('[type=checkbox]').removeClass('checked');
    $(this).find('[type=checkbox]').prop('checked', false);
    $(this).css("background-color", "#67517A");
    $(this).find('label').css({
      "font-style": ""
    });
  }
});
input[type=checkbox] {
  display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<li class="checkbox-select">
  
    <input id="id_0-tag_0" name="0-tag" type="checkbox" value="44" />
  
  Test Test
</li>
Deepak Kumar Padhy
  • 4,128
  • 6
  • 43
  • 79