Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Change background color of table cells according to their header

I am dynamically constructing a calendar(html table) in javascript. I want to have the Saturday and Sunday columns with a gray background color.

When I'm adding the other cells to the calendar, I want to check for the cells column header, check it's inner html text/class/id and color the cell if it's on a weekend.

This is where I add the column headers with the starting letters of the days :

<th bgcolor='#c1c1c1' width=20>S</th>" 
<th width=20>M</th>" 
<th width=20>T</th>" 
<th width=20>W</th>" 
<th width=20>T</th>" 
<th width=20>F</th>" 
<th bgcolor='#c1c1c1' width=20>S</th>" 

I tried this code, but it's not working properly...

var table = document.getElementById("calendarTable");
var rows = table.getElementsByTagName("tr");
for (var z = 0; z < rows.length-1; z++) {
    for (var y = 0; y < rows[z].cells.length; y++) {
        if(rows[z].cells[y].headers=="S")
            rows[z].cells[y].style.backgroundColor = "#c1c1c1";
    }
}

So what I would like to achieve is just a little code snippet, that goes through a whole table element, and checks every cells header for it's innerhtml content or id and changes it's background color accordingly.

Later Edit :

Screenshot of the table :

enter image description here

The thing is, that the table is constructed according to the month we are currently in, and we don't necessarily know the index of Saturday or Sunday. (in the picture, the 1st of December lands on Monday, so this is a pretty lucky situation)

The Saturdays and Sundays are not fixed in the table. The calendar starts with the 1st of the current month and then gets the day for it. I know it's a little odd, but this is how it was designed by somebody else, and I have to work with it.

The blue bars are marking a time interval, but that thing is already working.

The code where I'm constructing the whole table would be really long to make it understandable.

like image 802
Laureant Avatar asked Feb 12 '23 10:02

Laureant


2 Answers

I definitely wouldn't encourage you to use JavaScript for the styling. Instead, use as much CSS as you possibly can to keep performance high and script-dependency low.

I'll assume your table structure looks like the following. I tried my best to recreate from your screenshot:

<table data-start-day="sun">
    <thead>
        <tr>
            <th>Year</th>
        </tr>
        <tr>
            <th rowspan="2">Month</th>
            <th>1</th><!-- fill in --><th>31</th>
        </tr>
        <tr>
            <th>S</th><th>M</th><!-- fill in -->
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>Employee</td>
            <td></td><!-- x days in month -->
        </tr>
        <tr>
            <td>Exceptions</td>
            <td></td><!-- x days in month -->
        </tr>
    </tbody>
</table>

Next we'll use a series of compound selectors that are supported in IE 9 and up. Note the primary power is through the use of :nth-of-type, with which we can target the Sat/Sun columns no matter where they fall on the calendar itself:

table[data-start-day=sat] thead tr:last-child th:nth-of-type(7n-13),
table[data-start-day=sat] thead tr:last-child th:nth-of-type(7n-12),
table[data-start-day=sat] tbody tr:nth-of-type(2n) :nth-of-type(7n-12):not(:first-child),
table[data-start-day=sat] tbody tr:nth-of-type(2n) :nth-of-type(7n-11):not(:first-child),
table[data-start-day=fri] thead tr:last-child th:nth-of-type(7n-12),
table[data-start-day=fri] thead tr:last-child th:nth-of-type(7n-11),
table[data-start-day=fri] tbody tr:nth-of-type(2n) :nth-of-type(7n-11):not(:first-child),
table[data-start-day=fri] tbody tr:nth-of-type(2n) :nth-of-type(7n-10):not(:first-child),
table[data-start-day=thu] thead tr:last-child th:nth-of-type(7n-11),
table[data-start-day=thu] thead tr:last-child th:nth-of-type(7n-10),
table[data-start-day=thu] tbody tr:nth-of-type(2n) :nth-of-type(7n-10):not(:first-child),
table[data-start-day=thu] tbody tr:nth-of-type(2n) :nth-of-type(7n-9):not(:first-child),
table[data-start-day=wed] thead tr:last-child th:nth-of-type(7n-10),
table[data-start-day=wed] thead tr:last-child th:nth-of-type(7n-9),
table[data-start-day=wed] tbody tr:nth-of-type(2n) :nth-of-type(7n-9):not(:first-child),
table[data-start-day=wed] tbody tr:nth-of-type(2n) :nth-of-type(7n-8):not(:first-child),
table[data-start-day=tue] thead tr:last-child th:nth-of-type(7n-9),
table[data-start-day=tue] thead tr:last-child th:nth-of-type(7n-8),
table[data-start-day=tue] tbody tr:nth-of-type(2n) :nth-of-type(7n-8):not(:first-child),
table[data-start-day=tue] tbody tr:nth-of-type(2n) :nth-of-type(7n-7):not(:first-child),
table[data-start-day=mon] thead tr:last-child th:nth-of-type(7n-8),
table[data-start-day=mon] thead tr:last-child th:nth-of-type(7n-7),
table[data-start-day=mon] tbody tr:nth-of-type(2n) :nth-of-type(7n-7):not(:first-child),
table[data-start-day=mon] tbody tr:nth-of-type(2n) :nth-of-type(7n-6):not(:first-child),
table[data-start-day=sun] thead tr:last-child th:nth-of-type(7n-7),
table[data-start-day=sun] thead tr:last-child th:nth-of-type(7n-6),
table[data-start-day=sun] tbody tr:nth-of-type(2n) :nth-of-type(7n-6):not(:first-child),
table[data-start-day=sun] tbody tr:nth-of-type(2n) :nth-of-type(7n-5):not(:first-child){
    background:#CCC;
}

The results match your desired output:

enter image description here

Fiddle: http://jsfiddle.net/80fajvd6/4/

like image 168
Sampson Avatar answered Feb 13 '23 22:02

Sampson


try this:

for (var z = 1; z < rows.length; z++) {
       rows[z].cells[0].style.backgroundColor = "#c1c1c1"; // Sunday
       rows[z].cells[6].style.backgroundColor = "#c1c1c1"; // Saturday
}

Example

Note your loop was finishing a row early and should start from 1 (as 0 will be your header row)

UPDATE

Given your edit I have mocked up a similar table and think the following js should solve your problem:

for (var z = 3; z < rows.length; z++) {
    for (var a = 1; a < rows[z].cells.length; a++) {
        if (rows[2].cells[a - 1].innerHTML == "S") {
            rows[z].cells[a].style.backgroundColor = "#c1c1c1";
        }
    }
}

I have added comments to the fiddle example

This code is slightly better on performance as you wouldn't need to loop through as many cells:

var table = document.getElementById("calendarTable");
var rows = table.getElementsByTagName("tr");
var cellIndexes = [];

for (var a = 0; a < rows[2].cells.length; a++) {
    if (rows[2].cells[a].innerHTML == "S") {
        cellIndexes.push(a + 1); 
    }
}

for (var z = 3; z < rows.length; z++) {
    for (var i = 0; i < cellIndexes.length; i++) {
        rows[z].cells[cellIndexes[i]].style.backgroundColor = "#c1c1c1";
    }
}

Example

like image 24
Pete Avatar answered Feb 13 '23 22:02

Pete