0
votes

Here's what I want to do:

Style a table whose cells' background color vary from light, medium, and dark. Any given cell's background color is based on the number of its row and column. Cells in odd rows and odd columns are light; cells in odd rows and even columns OR even rows and odd columns are medium; cells in even rows and even columns are dark.

Here's what I want it to look like:

A table whose cells' background color vary from light, medium, and dark. The cells' background colors are based on the number of their row and column. Cells in odd rows and odd columns are light; cells in odd rows and even columns OR even rows and odd columns are medium; cells in even rows and even columns are dark.

Here's my algorithm:

A. For each Row, assign an index;
B. For each Column, assign an index;
C. For each Cell, {
    I. Get the index of this Cell's Row;
    II. Get the index of this Cell's Column;
    III. If (both indices are odd) {add class '.cell-odd-odd';}
    IV. Else If ((parent Row is odd && parent Column is even) ||
                (parent Row is even && parent Column is odd)) {
                    add class '.cell-odd-even';
                }
    V. Else If (both parents are even) {add class '.cell-even-even';}
    VI. Else {do nothing;}
    }

Now, how can I do this with CSS and JavaScript/jQuery?

EDIT: This is perhaps a better algorithm:

A. For each Row, assign an index;
B. For each Column, assign an index;
C. For each Cell, {
    I. Get the index of this Cell's Row;
    II. Get the index of this Cell's Column;
    III. If (parent Row is odd) {
             If (parent Column is odd) {add class '.cell-odd-odd';}
             Else {add class '.cell-odd-even';}
         } Else {
             If (parent Column is odd) {add class '.cell-odd-even';}
             Else {add class '.cell-even-even';}
         }
    }
4
Interesting: In the image above, the middle cell (R3C3) looks a bit lighter than all the other cells of its class, however this is an optical illusion due to the surrounding darker cells. Have no fear, all cells of odd-odd class are the same. I made it in Word. - chharvey

4 Answers

4
votes

Try this, although browser support might not be at 100% level:

tr:nth-child(odd) td:nth-child(odd)
{
    background:pink;
}

tr:nth-child(odd) td:nth-child(even)
{
    background:purple;
}

tr:nth-child(even) td:nth-child(odd)
{
    background:purple;
}

tr:nth-child(even) td:nth-child(even)
{
    background:brown;
}

Javascript version:

$("tr:odd td:odd").addClass("cell-odd-odd");
$("tr:odd td:even").addClass("cell-odd-even");
$("tr:even td:odd").addClass("cell-even-odd");
$("tr:even td:even").addClass("cell-even-even");
1
votes

You can use the :odd and :even selectors on jQuery to traverse your table's rows and cells like this:

var cssColorArr = ["#FCE9D8", "#F9D5B2", "#F7C08B"];
$("#yourTableId>tbody>tr:odd").each(function(i, elm){ 
   $(elm).style("background-color", cssColorAttr[0]);
   $(this).find("td:odd").style("background-color", cssColorAttr[1]);
   $(this).find("td:even").style("background-color", cssColorAttr[2]);
});
$("#yourTableId>tbody>tr:even").each(function(i, elm){ 
   $(elm).style("background-color", cssColorAttr[1]);
   $(this).find("td:odd").style("background-color", cssColorAttr[1]);
   $(this).find("td:even").style("background-color", cssColorAttr[2]);
});

I haven't tested it yet but I think you get the idea.

0
votes

I'm answering my own question here... after a few hours of trial and error, and reading others' responses, I think this is a good solution. Sorry if it sounds like I'm talking to myself in the second person.


Forget adding separate cell classes to cells. Since the style of each cell is dependent on location, you want the style to change if the td moves (despite the separate content and container paradigm). And, this CSS is much easier and much more maintainable.

.table-grid .row-odd  .column-odd  {/* light */}
.table-grid .row-odd  .column-even,
.table-grid .row-even .column-odd  {/* medium */}
.table-grid .row-even .column-even {/* dark */}

In jQuery, you have to make sure you "restart" counting every time you hit a new row. If you just used $('tr td:odd'), then it would construct an array containing all odd tds in all trs, which would continue across rows. What you want is it to select the odd tds for each tr.

The way of going about this is to use a for-loop on a wrapper object. The JS below loops through the $('tbody') object (an array containing tbodys). It then constructs a new jQuery object from each individual tbody, gets its children (trs) with the restrictions of odd and even, and then adds classes to those trs. This loop ensures the parity (oddness and evenness) "restarts" at each tbody. If you have multiple tbodys (either within one or separate tables), the first row will always be styled the same.

for (var i=0; i<$('.table-grid tbody').size(); i++) {
    var jQobj = $($('.table-grid tbody').toArray()[i]);
    jQobj.children('tr:even').addClass('row-odd');
    jQobj.children('tr:odd').addClass('row-even');
}

The JS loop below does the same thing: it selects odd and even tds for each tr, restarting the parity at each row. If you have multiple rows, the first cell always looks the same.

for (var i=0; i<$('.table-grid tr').size(); i++) {
    var jQobj = $($('.table-grid tr').toArray()[i]);
    jQobj.children('td:even').addClass('column-odd');
    jQobj.children('td:odd').addClass('column-even');
}

Aside: You're probably wondering, "Why are you adding 'odd' classes to tr:even and td:even?" Well, that's because the jQuery :even and :odd selectors are zero-based, which means :even selects elements with indices 0, 2, 4, etc, which means the first, third, fifth, etc, elements. If the CSS artist wants the first, third, fifth elements to have a class containing the word "odd" (which is reasonable, no?), then the JS programmer has to switch it.

0
votes

Heres how you do it using JQuery

$("td:odd",$("tr:odd")).addClass("cell-odd-odd");
$("td:even",$("tr:odd")).addClass("cell-odd-even");
$("td:odd",$("tr:even")).addClass("cell-odd-even");
$("td:even",$("tr:even")).addClass("cell-even-even");

note that this will cause reflow for each element, you might want to add the table to a document fragment, and perform the operation on that before adding it back into the page.