3

edit: Question has been incorrectly flagged as duplicate, I have tried the proposed solution of the other question but was unable to get it to work. This question has now been answered and the solution posted here works perfectly

I'm having an issue with alternating row colours on a table after using some javascript to hide the filtered rows.

I'm using

tr:nth-child(even)
tr:nth-child(odd)

to alternate the colours of the rows of the table, just to make it easier to track across the rows for the user.

There is a search box at the top of each column that applies the filter function I'm using to filter the table beneath. It changes the the rows that don't match the search boxes content to style.display = "none". The issue with this is that after some rows have been hidden, the remaining rows don't always alternate colours.

this is the filter function i have been using

function Filter(n) {
    var input, filter, table, tr, td, i, txtValue;
    input = document.getElementById("searchbox" + n);
    filter = input.value.toUpperCase();
    table = document.getElementById("mytable");
    tr = table.getElementsByTagName("tr");
    for (i = 0; i < tr.length; i++) {
        td = tr[i].getElementsByTagName("td")[n];
        if (td) {
            txtValue = td.textContent || td.innerText;
            if (txtValue.toUpperCase().indexOf(filter) > -1) {
                tr[i].style.display = "";
            } else {
                tr[i].style.display = "none";
            }
        }
    }
}

and this is the css for my table

tr:nth-child(even){
    background-color: #F6F6F6
}

tr:nth-child(odd){
    background-color: #EEEEEE
}

this is the table ive been using

<table id="mytable">
  <tr>
    <th>
      <div>A</div>
      <input id="searchbox0" type="text" onkeyup="Filter(0)" placeholder="Filter..">
    </th>
    <th>
      <div>B</div>
      <input id="searchbox1" type="text" onkeyup="Filter(1)" placeholder="Filter..">
    </th>
    <th>
      <div>C</div>
      <input id="searchbox2" type="text" onkeyup="Filter(2)" placeholder="Filter..">
    </th>
    <th>
      <div>D</div>
      <input id="searchbox3" type="text" onkeyup="Filter(3)" placeholder="Filter..">
    </th>
  </tr>
  <tr onclick="window.location='04718J00065.html'">
    <td>04718J00065</td>
    <td>2100305513</td>
    <td>10</td>
    <td>-</td>
  </tr>
  <tr onclick="window.location='29417J01131.html'">
    <td>29417J01131</td>
    <td>2100305513</td>
    <td>*</td>
    <td>-</td> 
  </tr>
  <tr onclick="window.location='07416J01979.html'">
    <td>07416J01979</td>
    <td>2100029648</td>
    <td>*</td>
    <td>-</td> 
  </tr>
  <tr onclick="window.location='02518J01169.html'">
    <td>02518J01169</td>
    <td>2100030939</td>
    <td>*</td>
    <td>-</td> 
  </tr>
  <tr onclick="window.location='09013J00505.html'">
    <td>09013J00505</td>
    <td>20865</td>
    <td>10</td>
    <td>-</td> 

  </tr>
  <tr onclick="window.location='04718J00068.html'">
    <td>04718J00068</td>
    <td>2100305513</td>
    <td>10</td>
    <td>-</td> 
  </tr>
  <tr onclick="window.location='09618J05120.html'">
    <td>09618J05120</td>
    <td>2100305513</td>
    <td>10</td>
    <td>-</td> 
  </tr>
  <tr onclick="window.location='07416J01973.html'">
    <td>07416J01973</td>
    <td>20862</td>
    <td>10</td>
    <td>-</td> 
  </tr>
  <tr onclick="window.location='20614J00424.html'">
    <td>20614J00424</td>
    <td>20861</td>
    <td>10</td>
    <td>-</td> 
  </tr>
  <tr onclick="window.location='15713J01020.html'">
    <td>15713J01020</td>
    <td>20870</td>
    <td>30</td>
    <td>-</td> 
  </tr>
  <tr onclick="window.location='07714J00746.html'">
    <td>07714J00746</td>
    <td>20861</td>
    <td>10</td>
    <td>-</td> 
  </tr>
  <tr onclick="window.location='34414J00495.html'">
    <td>34414J00495</td>
    <td>30939</td>
    <td>30</td>
    <td>-</td>
  </tr>
  <tr onclick="window.location='15713J01016.html'">
    <td>15713J01016</td>
    <td>20862</td>
    <td>30</td>
    <td>-</td>
  </tr>
  <tr onclick="window.location='13414J01282.html'">
    <td>13414J01282</td>
    <td>20861</td>
    <td>10</td>
    <td>-</td>
  </tr>
  <tr onclick="window.location='09013J00489.html'">
    <td>09013J00489</td>
    <td>20861</td>
    <td>10</td>
    <td>-</td>
  </tr>
  <tr onclick="window.location='29818J05034.html'">
    <td>29818J05034</td>
    <td>2100305513</td>
    <td>*</td>
    <td>-</td>
  </tr>
  <tr onclick="window.location='23914J00685.html'">
    <td>23914J00685</td>
    <td>20870</td>
    <td>30</td>
    <td>-</td>
  </tr>
  <tr onclick="window.location='13414J01279.html'">
    <td>13414J01279</td>
    <td>20861</td>
    <td>10</td>
    <td>-</td>
  </tr>
  <tr onclick="window.location='14716J01400.html'">
    <td>14716J01400</td>
    <td>2100030939</td>
    <td>30</td>
    <td>-</td>
  </tr>
  <tr onclick="window.location='07714J00748.html'">
    <td>07714J00748</td>
    <td>20861</td>
    <td>10</td>
    <td>-</td>
  </tr>
</table>

what I'm looking for is a table of alternating visible row colours no matter what rows have been hidden. After filtering, what i get is some rows of the same colour next to each other where the hidden rows are still contributing towards the odd/even count. I have a feeling it's to do with hidden rows still contributing to the index count but I'm not sure how to get around this.

Any help here would be much appreciated.

J.Edwards
  • 47
  • 7

2 Answers2

4

Instead of changing the display propriety add/remove a class

tr[i].classList.add("active");

tr[i].classList.remove("active");

So then you can simple change the css like so

tr.active {
    display: block;
}
tr {
    display: none;
}
tr.active:nth-child(even){
    background-color: #F6F6F6
}
tr.active:nth-child(odd){
    background-color: #EEEEEE
}

As Stephen P pointed out my original answer was wrong, it look like ntl-child ignores the class, so a suggestion to solve this can be something like the following, for simplicity, as MarsAndBack said you can split this into multiple functions.

function Filter(n) {
    var input, filter, table, tr, td, i, txtValue, count;
    input = document.getElementById("searchbox" + n);
    filter = input.value.toUpperCase();
    table = document.getElementById("mytable");
    tr = table.getElementsByTagName("tr");
    for (i = 0, count = 0; i < tr.length; i++) {
        td = tr[i].getElementsByTagName("td")[n];
        if (td) {
            txtValue = td.textContent || td.innerText;
            if (txtValue.toUpperCase().indexOf(filter) > -1) {
                tr[i].style.display = "";
                if (count++ % 2 == 0) {
                  tr[i].style.background = "#F6F6F6";
                } else {
                  tr[i].style.background = "#EEEEEE";
                }
            } else {
                tr[i].style.display = "none";
            }
        }
    }
}
tr:nth-child(even){
    background-color: #F6F6F6
}

tr:nth-child(odd){
    background-color: #EEEEEE
}
<table id="mytable">
  <tr>
    <th>
      <div>A</div>
      <input id="searchbox0" type="text" onkeyup="Filter(0)" placeholder="Filter..">
    </th>
    <th>
      <div>B</div>
      <input id="searchbox1" type="text" onkeyup="Filter(1)" placeholder="Filter..">
    </th>
  </tr>
  <tr>
    <td>04718J00065</td>
    <td>2100305513</td>
  </tr>
  <tr>
    <td>29417J01131</td>
    <td>2100305513</td>
  </tr>
  <tr>
    <td>07416J01979</td>
    <td>2100029648</td>
  </tr>
  <tr>
    <td>02518J01169</td>
    <td>2100030939</td>
  </tr>
</table>
  • 2
    This looks really nice, and people are upvoting this, but did you (or they) try it? When I turned your CSS and a simple 9-row table into a stack-snippet it didn't work. I had all but one row with `class="active"` -- the one row w/o active (row 6 in my test) was hidden, and rows 5 & 7 had the same background color. – Stephen P Apr 11 '19 at 17:15
  • 1
    @StephenP you are right, I have changed my answer into a different approach please give it a try. – Francisco Soares Apr 12 '19 at 09:28
  • This worked perfectly. I have tested it out several times and can't get it to not work. Thank you! – J.Edwards Apr 12 '19 at 13:16
2

Give "zebra-striping" its own function:

Split your function up so the act of filtering and "zebra-striping" occur independent of one another; each having it's own function() definition.

Then ultimately as a last step in your overall logic, after all queries and filters are done, you run the zebra-striping function to do it's thing on whatever actual rows exist.

Kalnode
  • 9,386
  • 3
  • 34
  • 62