3

I am trying to allow clicking on a div that contains a checkbox to cause that checkbox to be selected. Whenever the checkbox is selected, its parent div changes color. When unselected, the parent div's background color goes back to the original one.

Problem: The behavior when clicking on the checkbox's div is correct. However, when clicking on the checkbox directly, the behavior is opposite of what is desired. I suspect this is due to double clicking: The checkbox's own click handler fires, as well as the click handler for its parent div. I may be wrong here. How can I fix it?

JS

// Click checkbox when its container is clicked
$(".organizer_listing_checkbox_container_container").click(function(event) {
    if (event.target.type !== 'checkbox') {
      $(':checkbox', this).trigger('click');
    }
});

// Highlight row on selecting Checkbox
$(".organizer_listing_checkbox").click(function() {
    if($(this).attr('checked')) {
        $(this).parent().parent().parent().css('background-color', "#FAFAFA");
    } else {
        $(this).parent().parent().parent().css('background-color', "#FFF");
    }
});

HTML

<div class="organizer_listing">

    <div class="organizer_listing_checkbox_container_container">
        <div class="organizer_listing_checkbox_container" data-listing_id=1234>
            <input type="checkbox" class="organizer_listing_checkbox" />
        </div>
    </div>

</div>

EDIT: Swapped the background colors + e.stopPropagation()

// Click checkbox when its container is clicked
$(".organizer_listing_checkbox_container_container").click(function(event) {
    $(':checkbox', this).trigger('click');
});

// Highlight row on selecting Checkbox
$(".organizer_listing_checkbox").click(function(e) {
    e.stopPropagation();
    if($(this).attr('checked')) {
        $(this).parent().parent().parent().css('background-color', "#FAFAFA");
    } else {
        $(this).parent().parent().parent().css('background-color', "#FFF");
    }
});
Nyxynyx
  • 61,411
  • 155
  • 482
  • 830
  • Take a look at [this question](http://stackoverflow.com/q/8865928/552438) that was asked about ten minutes before yours, as well as its answers. Seems like it's the same issue. – Anthony Grist Jan 14 '12 at 22:53
  • Use `this.checked` instead of `$(this).attr('checked')`. For readability, you should use `$(this).closest('.organizer_listing')` instead of [3x parent()](http://stackoverflow.com/questions/8789362/parent-faster-alternative/8789398#8789398). Finally, you should replace `click` with `change`, because it's also possible to change the state via the keyboard. – Rob W Jan 14 '12 at 23:12

4 Answers4

2

You might want to try using a label and then use a change handler on the check box. Clicking on a label associated with a checkbox is functionally the same as clicking on the checkbox. By using a change handler, you process all the events where the value of the checkbox changes.

<style>
   .organizer_listing_checkbox_container {
       display: block;
   }
</style>

<script type="text/javascript">
   $(function() {
       $(".organizer_listing_checkbox").on('change',function() {
           if ($(this).attr('checked')) {
               $(this).parent().parent().parent().css('background-color', "#FAFAFA");
           } else {
               $(this).parent().parent().parent().css('background-color', "#FFF");
           }
       });
    });
</style>

<div class="organizer_listing">

    <div class="organizer_listing_checkbox_container_container">
        <label class="organizer_listing_checkbox_container" for="listing_checkbox_0" data-listing_id=1234>
            <input id="listing_checkbox_0" type="checkbox" class="organizer_listing_checkbox" />
        </label>
    </div>

</div>
tvanfosson
  • 524,688
  • 99
  • 697
  • 795
2

I kind of went crazy and rewrote most of the code (demo):

var update = function($el){
    // cycle through all elements
    $el.each(function(){
        var bkgd = $(this).prop('checked') ? "#FAFAFA" : "#FFF";
        $(this).closest('.organizer_listing_checkbox_container_container')
            .css('background-color', bkgd);
    });
};

// Click checkbox when its container is clicked
$(".organizer_listing_checkbox_container_container").click(function(event) {
    var check = $(':checkbox', this);
    check.prop('checked', !check.prop('checked') );
    update( check );
});

// Highlight row on selecting Checkbox
$(".organizer_listing_checkbox").click(function(e) {
    e.stopPropagation();
    update( $(this) );
});

// update on initialization
update( $(".organizer_listing_checkbox") );
Mottie
  • 84,355
  • 30
  • 126
  • 241
1

You have just to stop propagation:

// Highlight row on selecting Checkbox
$(".organizer_listing_checkbox").click(function(e) {
    e.stopPropagation();//so the click will not propagate to the div parent

    if($(this).attr('checked')) {
        $(this).parent().parent().parent().css('background-color', "#FFF");
    } else {
        $(this).parent().parent().parent().css('background-color', "#FAFAFA");
    }
});
albanx
  • 6,193
  • 9
  • 67
  • 97
1

Use the on() to bind events (jQuery 1.7+). The following method will:

  • Toggle colours on change of the checkbox (Use change instead of click to allow keyboard-initiated state changes).
  • Toggle the check state on clicking the <div>

Demo: http://jsfiddle.net/sPb9f/1/

// Click checkbox when its container is clicked
$('.organizer_listing').on('click', '.organizer_listing_checkbox_container_container', function(event) {
    if ($(event.target).hasClass('organizer_listing_checkbox')) {
        return; // Do nothing (checkbox)
    }
    $(':checkbox', this).each(function(){
        this.checked = !this.checked; // Swap check state
    }).trigger('change');
}).on('change', '.organizer_listing_checkbox', function(event) {
    // Highlight row on selecting Checkbox
    var $this = $(this),
        $main_listing = $this.closest('.organizer_listing');
    if (this.checked) {
        $main_listing.css('background-color', "red");
    } else {
        $main_listing.css('background-color', "yellow");
    }
});
Community
  • 1
  • 1
Rob W
  • 341,306
  • 83
  • 791
  • 678
  • @Nyxynyx I missed a line, see the updated fiddle (have a look at the [revision history](http://stackoverflow.com/posts/8866251/revisions) for the applied changes). – Rob W Jan 14 '12 at 23:47