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?

\$\endgroup\$
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>

| improve this answer | |
\$\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>

| improve this answer | |
\$\endgroup\$
  • \$\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\$ – Nikhil Gupta Mar 2 '16 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.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ I forget to remove it. Shrinked the actual function and item was being used in that. \$\endgroup\$ – Nikhil Gupta Mar 2 '16 at 12:32
  • \$\begingroup\$ ;) Cool job your script, nevertheless. \$\endgroup\$ – michael.zech Mar 2 '16 at 12:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.