lapingultah
lapingultah

Reputation: 316

CSS odd & even on dynamic table

I'm using the following piece of jQuery applied to an input field to narrow a list of items shown in a table (a real table, with tr and td layout):

$(function(){
    $("#search").keyup(function() {
        var value = this.value.toLowerCase();

        $(".table").find("tr").each(function(index) {
            if (index === 0) return;
            var id = $(this).find("td").text().toLowerCase();
            $(this).toggle(id.indexOf(value) !== -1);
        });
    });
});

It works perfectly otherwise, but as the .table has .table tr:nth-child(odd) and (even) targeted styling for the initial layout, the odd & even rows get messed up when the list narrowing search filter applies.

So far I've been unlucky with removeClass and addClass when the rows change dynamically, am I missing something essential..?

A JSFiddle example can be check at https://jsfiddle.net/4cf8a01L/3/

Upvotes: 2

Views: 2804

Answers (2)

phoa
phoa

Reputation: 261

kinda of a hacky way to do it - https://jsfiddle.net/6rk09jb0/1/

add odd and even class

.table tr:nth-child(odd),
.table tr.odd.odd {
  background-color: #fff;
}
.table tr:nth-child(even),
.table tr.even.even {
  background-color: #c0c0c0;
}

apply odd and even when filtering

$("#search").keyup(function() {
  var value = this.value.toLowerCase();

  var count = 0;

  $(".table").find("tr").each(function(index) {
    if (index === 0) return;
    var id = $(this).find("td").text().toLowerCase();
    var test = id.indexOf(value) !== -1;
    var className = '';
    if (test) {
      count += 1;
      className = count % 2 ? 'odd' : 'even';
    }
    $(this).toggle(test).attr('class', className);
  });
});

Upvotes: 3

Rory McCrossan
Rory McCrossan

Reputation: 337580

Unfortunately :nth-child takes in to account all child elements, regardless of their visibility. To fix this you could use jQuery to apply your row stripes on visible rows on load of the page and also when the filter is changed, like this:

$("#search").keyup(function() {
  var value = this.value.toLowerCase();
  var $table = $('table');

  $table.find("tbody tr").each(function(index) {
    var id = $(this).find("td").text().toLowerCase().trim();
    $(this).toggle(id.indexOf(value) !== -1);
  });

  stripeRows($table);
});

function stripeRows($table) {
  $table.find('tr:visible:odd').css('background', '#FFFFFF');
  $table.find('tr:visible:even').css('background', '#C0C0C0');
}
stripeRows($('table'));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" id="search" autofocus>
<table class="table">
  <thead>
    <tr>
      <th>title 1</th>
      <th>title 2</th>
      <th>title 3</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>data</td>
      <td>goes</td>
      <td>here</td>
    </tr>
    <tr>
      <td>and</td>
      <td>then</td>
      <td>here</td>
    </tr>
    <tr>
      <td>rows</td>
      <td>repeat</td>
      <td>this way</td>
    </tr>
    <tr>
      <td>consisting</td>
      <td>of hundres</td>
      <td>of rows</td>
    </tr>
    <tr>
      <td>cell</td>
      <td>cell</td>
      <td>cell</td>
    </tr>
    <tr>
      <td>content</td>
      <td>content</td>
      <td>content</td>
    </tr>
  </tbody>
</table>

Note that the above only searches for tr within the tbody, instead of explicitly excluding the row at index 0.

Alternatively you can use the CSS you are now, but you need to remove() or detach() the tr when filtering, and then also have a system of putting them back in the correct place, either through sorting or explicitly setting their location.

While the CSS of this solution will be simpler, the logic required will be far more complex.

Upvotes: 1

Related Questions