3
\$\begingroup\$

I have a requirement in which I need to set color of two or more rows of a table same if they have same value in cell one and I have to maintain this alternatively i.e. no 3 or 4 rows should have the same color unless there cell value is same.

I have written following code but I don't like it that much as it seems dirty.

function SetGroupingDetails(row, item, color, namedColor) {
 $(row)
 .css("background-color", color) //set different color for different groups
 .addClass(namedColor);
}
$("#tblExport tbody tr").each(function() {
 var item = $("td:first", this).text();
 var prev = $(this).prev();
 if (prev.length > 0) {
 var prevItem = prev.find('td:first').text();
 if (prevItem == item) {
 if (prev.hasClass('Green'))
 SetGroupingDetails(this, item, "#009933", "Green");
 else
 SetGroupingDetails(this, item, "#cc9900", "Orange");
 } else {
 if (prev.hasClass('Orange'))
 SetGroupingDetails(this, item, "#009933", "Green");
 else
 SetGroupingDetails(this, item, "#cc9900", "Orange");
 }
 } else
 SetGroupingDetails(this, item, "#009933", "Green");
});
#tblExport body {
 font: normal medium/1.4 sans-serif;
}
#tblExport {
 border-collapse: collapse;
 width: 100%;
}
#tblExport th,
td {
 padding: 0.25rem;
 text-align: left;
 border: 1px solid #ccc;
}
#tblExport th {
 background: #bfbfbf;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="tblExport">
 <thead>
 <tr>
 <th>
 Item No.
 </th>
 <th>
 Item Name
 </th>
 </tr>
 </thead>
 <tbody>
 <tr>
 <td>
 10178601
 </td>
 <td>
 X
 </td>
 </tr>
 <tr>
 <td>
 10178601
 </td>
 <td>
 X
 </td>
 <tr>
 <td>
 40062595
 </td>
 <td>
 Y
 </td>
 </tr>
 <tr>
 <td>
 40062595
 </td>
 <td>
 Y
 </td>
 </tr>
 <tr>
 <td>
 80214549
 </td>
 <td>
 Z
 </td>
 </tr>
 <tr>
 <td>
 80214549
 </td>
 <td>
 Z
 </td>
 </tr>
 </tbody>
</table>

Any suggestions?

Quill
12k5 gold badges41 silver badges93 bronze badges
asked Mar 1, 2016 at 18:35
\$\endgroup\$
0

3 Answers 3

2
\$\begingroup\$

As previously mentioned, #tblExport body should probably be #tblExport > tbody, and you should trim() text before comparing.

It is possible to reduce the five calls to SetGroupingDetails(). If you don't try to set a background-color manually, then it's a simple matter of adding either a "zebra-even" class or a "zebra-odd" class. Simply toggle between them whenever the text doesn't match its predecessor.

var c = 0;
$("#tblExport tbody tr").each(function() {
 var $item = $("td:first", this);
 var $prev = $(this).prev().find('td:first');
 if ($prev.length && $prev.text().trim() != $item.text().trim()) {
 c = 1 - c;
 }
 $(this).addClass(['zebra-even', 'zebra-odd'][c]);
});
#tblExport > tbody {
 font: normal medium/1.4 sans-serif;
}
#tblExport {
 border-collapse: collapse;
 width: 100%;
}
#tblExport th,
td {
 padding: 0.25rem;
 text-align: left;
 border: 1px solid #ccc;
}
#tblExport th {
 background: #bfbfbf;
}
#tblExport > tbody > tr.zebra-even {
 background-color: #093;
}
#tblExport > tbody > tr.zebra-odd {
 background-color: #c90;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="tblExport">
 <thead>
 <tr>
 <th>
 Item No.
 </th>
 <th>
 Item Name
 </th>
 </tr>
 </thead>
 <tbody>
 <tr>
 <td>
 10178601
 </td>
 <td>
 X
 </td>
 </tr>
 <tr>
 <td>
 10178601
 </td>
 <td>
 X
 </td>
 <tr>
 <td>
 40062595
 </td>
 <td>
 Y
 </td>
 </tr>
 <tr>
 <td>
 40062595
 </td>
 <td>
 Y
 </td>
 </tr>
 <tr>
 <td>
 80214549
 </td>
 <td>
 Z
 </td>
 </tr>
 <tr>
 <td>
 80214549
 </td>
 <td>
 Z
 </td>
 </tr>
 </tbody>
</table>

answered Mar 2, 2016 at 8:57
\$\endgroup\$
1
\$\begingroup\$

If you are doing $.addClass(namedColor), then why are you setting the background-color explicitly? Just define CSS rules for the two classes that will set the background color. Also, CSS class names should be neutral about the visual effect they produce, so zebra-even and zebra-odd would be better names than Green and Orange.

Your #tblExport body rule makes no sense. Did you mean #tblExport > tbody?

You should trim() the text before comparing. Otherwise, the whitespace would become significant.

You could reduce some of the redundancy in the calls to SetGroupingDetails(). However, since this task is fundamentally a grouping problem, you should have some kind of groupBy() function in your code. You could write such a function, but it would be smarter to use a library such as or .

_($("#tblExport > tbody > tr"))
 .groupBy(function(row) {
 return $(row).find('td:first').text().trim();
 })
 .values()
 .chunk(2)
 .forEach(function(rowGroupPair) {
 $(rowGroupPair[0]).addClass('zebra-even');
 if (rowGroupPair.length > 1) {
 $(rowGroupPair[1]).addClass('zebra-odd');
 }
 });
#tblExport > tbody {
 font: normal medium/1.4 sans-serif;
}
#tblExport {
 border-collapse: collapse;
 width: 100%;
}
#tblExport th,
td {
 padding: 0.25rem;
 text-align: left;
 border: 1px solid #ccc;
}
#tblExport th {
 background: #bfbfbf;
}
#tblExport > tbody > tr.zebra-even {
 background-color: #093;
}
#tblExport > tbody > tr.zebra-odd {
 background-color: #c90;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.5.1/lodash.min.js"></script>
<table id="tblExport">
 <thead>
 <tr>
 <th>
 Item No.
 </th>
 <th>
 Item Name
 </th>
 </tr>
 </thead>
 <tbody>
 <tr>
 <td>
 10178601
 </td>
 <td>
 X
 </td>
 </tr>
 <tr>
 <td>
 10178601
 </td>
 <td>
 X
 </td>
 <tr>
 <td>
 40062595
 </td>
 <td>
 Y
 </td>
 </tr>
 <tr>
 <td>
 40062595
 </td>
 <td>
 Y
 </td>
 </tr>
 <tr>
 <td>
 80214549
 </td>
 <td>
 Z
 </td>
 </tr>
 <tr>
 <td>
 80214549
 </td>
 <td>
 Z
 </td>
 </tr>
 </tbody>
</table>

answered Mar 1, 2016 at 19:58
\$\endgroup\$
1
  • \$\begingroup\$ thanks but I would not like to add dependency. Can you suggest something on grouping. I have changed class names to be generic and used them rather than adding color. Just simplification of usage of SetGroupingDetails is where m stuck. \$\endgroup\$ Commented Mar 2, 2016 at 8:36
0
\$\begingroup\$

You pass "item" as second parameter to your function ...

function SetGroupingDetails(row, item, color, namedColor) {

... but within your function-body it isn't used.

 $(row)
 .css("background-color", color) //set different color for different groups
 .addClass(namedColor);
}

You should get rid of that.

answered Mar 2, 2016 at 9:48
\$\endgroup\$
2
  • \$\begingroup\$ I forget to remove it. Shrinked the actual function and item was being used in that. \$\endgroup\$ Commented Mar 2, 2016 at 12:32
  • \$\begingroup\$ ;) Cool job your script, nevertheless. \$\endgroup\$ Commented Mar 2, 2016 at 12:35

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.