1

I have a table and I want each cell to have a red background if the cell is disabled, and blue if is enabled. So I have a inserted an invisible checkbox in each cell. When I have labels instead of a table, it works ok (see example here), but it´s not working with a table.

HTML:

  <table id="hours">
    <tbody>
      <tr>
        <td id="tdh00"><input type="checkbox" id="h00"></td>
        <td id="tdh01"><input type="checkbox" id="h01"></td>
      </tr>
    </tbody>
  </table>

CSS:

input[type=checkbox] { visibility: hidden; }
#hours input[type=checkbox]:checked  + #tdh00 { background-color: #265BFA; }
#hours input[type=checkbox]:not(:checked) + #tdh00 { background-color: #FA2421; }
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Alberto
  • 704
  • 2
  • 12
  • 26
  • You html and css both are invalid. And form is not part of table. So table is sibling of input element. you can perform things on table when checkbox is selected. [check this fiddle](http://jsfiddle.net/crazyrohila/hTxZS/) – crazyrohila Apr 16 '13 at 10:41
  • Can you provide a visual to illustrate what you are after? Also, are you sure that a `table` is appropriate markup? It may well be simpler to achieve what you want by altering the markup. – CherryFlavourPez Apr 16 '13 at 10:43
  • @crazyrohila - a `tr` can only contain `td` and/or `th` elements. – CherryFlavourPez Apr 16 '13 at 10:45
  • @CherryFlavourPez Thanks, I was thinking to write that, but was not so sure. I started my life after divs, so table not much of experience. :) – crazyrohila Apr 16 '13 at 10:48
  • @CherryFlavourPez I want something like this: http://html-color-codes.info/ I need a table of 24 hours and 7 days, and you enable the hours you are not busy. Red hours you are busy, blue hours you are not. JS solutions are valid :) – Alberto Apr 16 '13 at 10:49

2 Answers2

1

Try like below this is the solution with JQuery :

Fiddle : http://jsfiddle.net/RYh7U/138/

HTML :

<table id="hours" border="1">
 <tbody>
    <tr><td id="tdh00"><input type="checkbox" id="h00"></td><td id="tdh01"><input type="checkbox" id="h01"></td></tr>
    </tbody>
</table>
</body>

CSS :

input[type=checkbox] { visibility: hidden; }

JQuery :

$("#hours td").each(function(e){ 
    var ele = $(this).children('input[type=checkbox]');
    var flag = ele.prop('checked');
    if(flag)
    {
        ele.prop('checked', false);
        $(this).css("background", "#265BFA");
    }
    else
    {
        ele.prop('checked', true);
        $(this).css("background", "#FA2421");
    }
});

$("#hours td").click(function(e){ 
    var ele = $(this).children('input[type=checkbox]');
    var flag = ele.prop('checked');
    if(flag)
    {
        ele.prop('checked', false);
        $(this).css("background", "#265BFA");
    }
    else
    {
        ele.prop('checked', true);
        $(this).css("background", "#FA2421");
    }
});
Pandian
  • 8,848
  • 2
  • 23
  • 33
  • The problem with this as it stands is that only the `click` event is given, so on initial page load the background of each cell will not be changed to the correct colour. – CherryFlavourPez Apr 16 '13 at 11:07
  • That's quite a lot of repetition, and as you're using the click event it's not very accessible. For a different approach, take a look at my new answer. You don't really want to be manipulating the CSS directly in your JS, but should just use it to toggle a class. – CherryFlavourPez Apr 16 '13 at 11:32
0

With your markup as it stands, this is not going to work. You are using the + (sibling) selector, but your table cells are not siblings of your checkboxes. In the example you gave, the markup is:

<div class="slideOne">  
    <input type="checkbox" value="None" id="slideOne" name="check" />
    <label for="slideOne"></label>
</div>

Yours is:

<td id="tdh00"><input type="checkbox" id="h00"></td>

So, you are attempting to style the parent based on the state of one its child elements, which is not currently possible with CSS alone.

EDIT

Check out this working example. That fiddle adds the label back in (which will help with accessibility), and positions it in such a way that it visually does what you're after. The markup needs to be:

<table id="hours">
    <tbody>
      <tr>
        <td id="tdh00">
            <div>
                <input type="checkbox" id="h00">
                <label for="h00">Label</label>
            </div>
        </td>
        <td id="tdh01">
             <div>
                <input type="checkbox" id="h01">
                <label for="h01">Label</label>
              </div>
        </td>
      </tr>
    </tbody>
  </table>

And the CSS:

table {
    width: 450px;
    margin: 0 auto;    
}
td {
    border: 1px solid #333;
    padding: 0;
}

td > div { position: relative; }

input[type=checkbox] { visibility: hidden; }

label {
    display: block;
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: red;
    text-indent: -999em;
}

input[type=checkbox]:checked  + label { background-color: #265BFA; }

The extra div in each table cell is necessary, because Firefox can't handle positioning things relative to td elements.

Browser support is good, but only IE9+ is supported because we're using the :checked pseudo-class. You'll get better support with a JavaScript-based solution, but I'd argue that this is a great candidate for progressive enhancement.

EDIT 2

If support for old IE is a requirement, then you'll need to resort to JavaScript. Here's an example using jQuery.

The JavaScript just adds a class of active to the table cell: the bulk of the work is still done with CSS.

$("#hours input").on('change', function(){
    var checkbox = $(this),
        tableCell = checkbox.parents('td');

    checkbox.is(':checked') ?
        tableCell.removeClass('active') :
        tableCell.addClass('active');
}).change();

The HTML remains the same, and the CSS differs only slightly with these lines replacing the :checked pseudo-class:

td { background-color: #265BFA; }
.active { background-color: red; }
CherryFlavourPez
  • 7,529
  • 5
  • 45
  • 47
  • I don´t require a non-JS solution. I thought it was easier... but i think i was wrong. Any example to do this with JS? – Alberto Apr 16 '13 at 10:50
  • Finally worked EDIT 2 after wrapping in a $("document").ready(function. Also I replaced .on('change', function() to .change(function – Alberto Apr 16 '13 at 12:28
  • What version of jQuery are you working with? As of 1.7, `change` just calls `on`, prior to that it was calling `bind`: http://stackoverflow.com/questions/9995638/what-is-best-way-to-perform-jquery-change. So, I believe the best solution is my original. – CherryFlavourPez Apr 16 '13 at 12:31
  • I'd also messed up the links in my answer. The jQuery version is here: http://jsfiddle.net/cherryflavourpez/jSbKJ/ – CherryFlavourPez Apr 16 '13 at 12:35
  • http://code.jquery.com/jquery-latest.js With .on down´t work (the event doesn´t get fired). And with .change, only works if the checkbox is visible... Did you managed to get your code work? – Alberto Apr 16 '13 at 12:36
  • That fiddle works for me, using the above code, in Chrome, Firefox and IE(10). – CherryFlavourPez Apr 16 '13 at 12:46
  • I saw the source code of jsfiddle.net/cherryflavourpez/jSbKJ, and it wraps the code in a $(window).load(function(){. I´ve done the same, and it works. Without the .load doesn´t work. Thank you very much :) – Alberto Apr 16 '13 at 12:48
  • Good answer, but I suggest using toggleClass rather than removeClass/addClass. – xtempore May 18 '15 at 23:38