HattrickNZ
HattrickNZ

Reputation: 4663

Table formatting in html using jQuery

I have a basic table with values that I am trying to control the formatting. I have achieved this in this example http://jsfiddle.net/hVJ4b/ for KPI2 of Service 1.

$('#work_table td.r2c1').each(function(){
    var test = $(this).html(); // this works
    var target = $('#work_table td.r2c5').html()
    var target2 = $('#work_table td.r2c5').html() - 5;
    //alert("test: " + test);
    //alert("target: " + target);
    //alert("target2: " + target2);
   if ($(this).html() >= target) { //if >= to target then green
        //alert($(this).value())
       $(this).css('background-color',green);
   } else if ($(this).html() < target && $(this).html() >= target2  ) { //if < to target then orange
        $(this).css('background-color',orange);
   } else { //if < to target then red
        $(this).css('background-color',red);
   } 
});

    $('#work_table td.r2c2').each(function(){
    var test = $(this).html(); // this works
    var target = $('#work_table td.r2c5').html()
    var target2 = $('#work_table td.r2c5').html() - 5;
    //alert("test: " + test);
    //alert("target: " + target);
    //alert("target2: " + target2);
   if ($(this).html() >= target) { //if >= to target then green
        //alert($(this).value())
       $(this).css('background-color',green);
   } else if ($(this).html() < target && $(this).html() >= target2  ) { //if < to target then orange
        $(this).css('background-color',orange);
   } else { //if < to target then red
        $(this).css('background-color',red);
   } 
});

    $('#work_table td.r2c3').each(function(){
    var test = $(this).html(); // this works
    var target = $('#work_table td.r2c5').html()
    var target2 = $('#work_table td.r2c5').html() - 5;
    //alert("test: " + test);
    //alert("target: " + target);
    //alert("target2: " + target2);
   if ($(this).html() >= target) { //if >= to target then green
        //alert($(this).value())
       $(this).css('background-color',green);
   } else if ($(this).html() < target && $(this).html() >= target2  ) { //if < to target then orange
        $(this).css('background-color',orange);
   } else { //if < to target then red
        $(this).css('background-color',red);
   } 
});

    $('#work_table td.r2c4').each(function(){
    var test = $(this).html(); // this works
    var target = $('#work_table td.r2c5').html()
    var target2 = $('#work_table td.r2c5').html() - 5;
    //alert("test: " + test);
    //alert("target: " + target);
    //alert("target2: " + target2);
   if ($(this).html() >= target) { //if >= to target then green
        //alert($(this).value())
       $(this).css('background-color',green);
   } else if ($(this).html() < target && $(this).html() >= target2  ) { //if < to target then orange
        $(this).css('background-color',orange);
   } else { //if < to target then red
        $(this).css('background-color',red);
   } 
});

Now I can just easily copy and paste my JQuery to apply it to the other rows/KPIs. But i am looking for a better way of doing this without copying and pasting, as I don't think this is good practice.

Can anyone offer advise on this please?

Note: My initial approach to this could be completely wrong. I also want it to be flexible for any changes/additions to the table at a later date...

Upvotes: 0

Views: 155

Answers (3)

Code Maverick
Code Maverick

Reputation: 20415

Here is how I would go about it. I wouldn't worry about classes at all. You know the positions of the cells, so you can just loop through each row and then each cell in that row and color as you go.

See working jsFiddle demo


JQUERY

var red = "#ff0000", green = "#00ff00", orange = "#ff7f00";

$(function () 
{
    $('#work_table tr').each(function (rowIndex)
    { 
        if (rowIndex > 0) // skip header row
        {
            var $row = $(this),
                $cells = $row.find('td'),
                count = $cells.length,
                target = parseFloat($cells[count - 2].innerText),
                target2 = target - 5.0;

            $cells.each(function (cellIndex)
            {
                var min = count - 6, 
                    max = count - 3;

                if (cellIndex >= min && cellIndex <= max) // only date cells
                {
                    var $cell = $(this),
                        value = parseFloat(this.innerText),
                        color = value >= target 
                                    ? green : value < target && value >= target2 
                                        ? orange : red;

                    $cell.css('background-color', color);
                }
            });
        }
    });
});



HTML

<table id="work_table" border="2">
    <tr>
        <th>Service</th>
        <th>Measure</th>
        <th>Date1</th>
        <th>Date2</th>
        <th>Date3</th>
        <th>Date4</th>
        <th>Target</th>
        <th>Trend</th>
    </tr>
    <tr>
        <td rowspan="4">Service1</td>
        <td>KPI1</td>
        <td>93.9</td>
        <td>99.0</td>
        <td>98.9</td>
        <td>99.0</td>
        <td>99.0</td>
        <td>Value_Trend</td>
    </tr>
    <tr>
        <td>KPI2</td>
        <td>91.4</td>
        <td>94.2</td>
        <td>75.9</td>
        <td>47.2.</td>
        <td>99.0</td>
        <td>Value_Trend</td>
    </tr>
    <tr>
        <td>KPI3</td>
        <td>91.0</td>
        <td>92.1</td>
        <td>83.9</td>
        <td>84.9</td>
        <td>95.0</td>
        <td>Value_Trend</td>
    </tr>
    <tr>
        <td>KPI4</td>
        <td>95.7</td>
        <td>94.6</td>
        <td>87.4</td>
        <td>88.3</td>
        <td>92.4</td>
        <td>Value_Trend</td>
    </tr>
    <tr>
        <td rowspan="3">Service2</td>
        <td>KPI1</td>
        <td>45.0</td>
        <td>95.3</td>
        <td>76.4</td>
        <td>34.5</td>
        <td>90.0</td>
        <td>Value_Trend</td>
    </tr>
    <tr>
        <td>KPI2</td>
        <td>91.0</td>
        <td>92.1</td>
        <td>83.9</td>
        <td>84.9</td>
        <td>95.0</td>
        <td>Value_Trend</td>
    </tr>
    <tr>
        <td>KPI3</td>
        <td>97.0</td>
        <td>96.1</td>
        <td>85.9</td>
        <td>84.9</td>
        <td>93.0</td>
        <td>Value_Trend</td>
    </tr>
    <tr>
        <td rowspan="5">Service3</td>
        <td>KPI1</td>
        <td>97.0</td>
        <td>93.1</td>
        <td>86.9</td>
        <td>82.9</td>
        <td>94.0</td>
        <td>Value_Trend</td>
    </tr>
    <tr>
        <td>KPI2</td>
        <td>50.2</td>
        <td>76.3</td>
        <td>69.4</td>
        <td>84.5</td>
        <td>95.0</td>
        <td>Value_Trend</td>
    </tr>
    <tr>
        <td>KPI3</td>
        <td>12.0</td>
        <td>93.1</td>
        <td>87.9</td>
        <td>86.9</td>
        <td>97.0</td>
        <td>Value_Trend</td>
    </tr>
    <tr>
        <td>KPI4</td>
        <td>91.0</td>
        <td>92.1</td>
        <td>83.9</td>
        <td>84.9</td>
        <td>95.0</td>
        <td>Value_Trend</td>
    </tr>
    <tr>
        <td>KPI5</td>
        <td>99.0</td>
        <td>99.1</td>
        <td>89.2</td>
        <td>89.3</td>
        <td>99.0</td>
        <td>Value_Trend</td>
    </tr>
</table>



RESULTS

Results

Upvotes: 0

Code Maverick
Code Maverick

Reputation: 20415

If you are copy/pasting the same code into each one, just combine them all using:

var $worktable = $('#work_table'),
    $cells = $worktable.find('td');

$cells.filter('.r2c1, .r2c2, .r2c3, .r2c4').each(function ()
{
    // your code here.
});



When you plug in your code it would look something like this: See working jsFiddle demo.

I cleaned it up a bit for readability's sake. I removed the commented out parts. You can always add that stuff back in. I also optimized it slightly using cached vars where I could.

Here's the jQuery I used:

var red = "#ff0000",
    green = "#00ff00",
    orange = "#ff7f00";

$(function () 
{
    var $worktable = $('#work_table'),
        $cells = $worktable.find('td');

    $cells.filter('.r2').each(function () 
    {
        var $this = $(this),
            test = parseFloat($this.html());

        if (test >= 3)
            $this.css('background-color', '#f0f');
    });

    $cells.filter('.r2c1, .r2c2, .r2c3, .r2c4').each(function ()
    { 
        var $this = $(this),
            test = parseFloat($this.html()),
            target = parseFloat($cells.filter('.r2c5').html()),
            target2 = parseFloat(target - 5),
            color = test >= target 
                    ? green 
                    : test < target && test >= target2 
                        ? orange 
                        : red;

        $this.css('background-color', color);
    });
});

Upvotes: 1

Alexander Ryan Baggett
Alexander Ryan Baggett

Reputation: 2397

Why don't you consider writing a generic function that takes a variable called rowname and then you just pass in the row you got via jquery outside of the function.

 var x = $('#work_table td.r2');
 rowcolor (x);

function rowcolor (rowname)
{
    $(rowname).each(function(){//this is r2 for an example             want to get it to work for > values 
    //var test = $(this).html(); // this works
    var test = $(this).val(); // this does not work
    //alert("test: " + test);
    if ($(this).html() >= 3) {
        //alert($(this).value())
       $(this).css('background-color','#f0f');
    }
});


}

What the guy above me said works just fine. Mine is more javascript style.

Upvotes: 0

Related Questions