1

I am trying to get my td to change color if the user clicks the td itself or the checkbox.

Right now if the user clicks the td the css will change and the checkbox will check/uncheck.

But if the checkbox is clicked, nothing changes. additionally if the page is refreshed the checkboxes are checked, but the CSS is gone.

What am I doing wrong?

JSFiddle

<table>
<tr><td><input type="checkbox" name="my-group[]" value="1">A</td></tr>
<tr><td><input type="checkbox" name="my-group[]" value="2">B</td></tr>
<tr><td><input type="checkbox" name="my-group[]" value="3">C</td></tr>
<tr><td><input type="checkbox" name="my-group[]" value="4">D</td></tr>
</table>

<script>
var chosen = {'background-color': '#9F1313', 'color': '#fff'};
var unchosen = {'background-color': 'transparent', 'color': '#000'};

$('td').click(function (event) {
    if (!$(event.target).is('input')) {
        $('input:checkbox', this).prop('checked', function (i, value) {
            highlight(this, $(this).closest('td'));
            return !value;
        });
    }
});

function highlight(cb, cell) {
    if (cb.checked) {
        $(cell).css(unchosen);
    } else {
        $(cell).css(chosen);
    }
}
</script>
1

3 Answers 3

1

The issue is due to the event bubbling from the checkbox to the parent td, however you can both avoid the problem completely, make the code more semantic, have better support, and simpler by using a label and then just toggling a CSS class on the parent td based on the checked state of the checkbox. Try this:

$('.table-responsive :checkbox').on('change', function() {
  $(this).closest('td').toggleClass('chosen', this.checked);
});
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.0/jquery.min.js"></script>
<style>
  label {
    display: block;
    font-weight: normal;
    margin: 0;
  }
  
  td {
    background-color: transparent;
    color: #000;
  }
  
  td.chosen {
    background-color: #9F1313;
    color: #fff;
  }
</style>
<div class="table-responsive">
  <div class="container">
    <table class="table table-striped table-hover table-condensed">
      <tr>
        <td><label><input type="checkbox" name="my-group[]" value="1"> A</label></td>
      </tr>
      <tr>
        <td><label><input type="checkbox" name="my-group[]" value="2"> B</label></td>
      </tr>
      <tr>
        <td><label><input type="checkbox" name="my-group[]" value="3"> C</label></td>
      </tr>
      <tr>
        <td><label><input type="checkbox" name="my-group[]" value="4"> D</label></td>
      </tr>
    </table>
  </div>
</div>

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you! This makes a lot more sense.
0

This is my suggestion this will bind event in both TD and checkbox while also prevent from double triggering.

$('td').on('click',function(event){ 
     var td  = $(this);
     var checkBox = $(this).find('input:checkbox');

     if($(event.target).is('input')){                 // checks if event target is checkbox
        event.stopPropagation();                      // prevents triggering click event on TD too
     } else {
        checkBox.trigger('click');                    // if its TD, triggers checkbox click event
        return;                                       // and stop the code
     }

     if(checkBox.is(':checked')){                     // checks if checkbox is checked!
        td.css('background-color','red');
     } else {
        td.css('background-color','transparent');
     }

 }); 

You can see it in action here : https://codepen.io/FaridNaderi/pen/PjVXrm

Hope it helps at least.

Comments

0

The issue is from the event bubbling add event.stopImmediatePropagation(); to your click event.

$('td').click(function(event) {
event.stopImmediatePropagation();
if (!$(event.target).is('input')) {
$('input:checkbox', this).prop('checked', function(i, value) {
  highlight(this, $(this).closest('td'));
  return !value;
});
}
});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.