Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sorting a table in JavaScript - hiding table rows with no subsequent rows

I have a table I've built in JavaScript that's basically a big list of publications, with a "year" header, followed by a row for each publication for that year:

  <table class="mytable" id="myTable">
  <tr class="header">
    <th style="width:60%;">2020</th>
  </tr>
  <tr name="latin_america_zero-deforestation">
    <td>"Cattle Ranchers and Deforestation.”
    </td>
  </tr>
  <tr name="latin_america_policy-outcomes">
    <td>“Impacts on Land Use Conversion.”
    </td>
  </tr>
  <tr name="latin_america_supply-chain_policy-outcomes">
    <td>“Costs of the Amazon Soy Moratorium.”
    </td>
  </tr>
  <tr class="header">
    <th style="width:60%;">2019</th>
  </tr>
  <tr name="africa_policy-outcomes">
    <td>“Environmental Change”
    </td>
  </tr>
  <tr name="latin_america_policy-outcomes">
    <td>“Land Use Change”
    </td>
  </tr>
  <tr class="header">
    <th style="width:60%;">2018</th>
  </tr>
  <tr name="north_america_zero-deforestation">
    <td>“Deforestation Remedies”
    </td>
  </tr>
  <tr name="latin_america_zero-deforestation">
    <td>“Land Use Change in Latin American Cerrados”
    </td>
  </tr>
</table>  

Based on the tr name, I then am able to filter by keywords (either region or topic) via some buttons:

  <button class="btn" onclick="filterSelection('policy-outcomes')">Policy Outcomes</button>

  <button class="btn" onclick="filterSelection('latin_america')"> Latin America</button>

The buttons call this function, which filters based on keywords found in the tr name tag:

//Sort by class..
function filterSelectionByTopic(thing) {

  var rows = $('#myTable').find('tr:not(:has(th))').get();
  console.log(rows)

$("#myTable tr").show()


$('#myTable').find('tr:not(:has(th))').not('thead td').not("[name*=" + thing + "]").fadeOut(300)

var tabhead = "header"
//$("#myTable tbody tr:not(."+thing + ')').hide();

//$("#myTable tr.header").fadeIn(1)

}

While this works fine, I want the filters to hide table headers (years) where no rows are returned.

For example, if I filtered using filterSelection('policy-outcomes'): 2020 and 2019 have publications that meet this criteria, 2018 does not. Currently 2018 will show up as a table header with no rows underneath, but I would like to hide any table header that does not have rows that meet the criteria.

So, in essence, filterSelection('policy-outcomes') should look like:

2020
Impacts on Land Use Conversion.
Costs of the Amazon Soy Moratorium.
2019
Environmental Change.
Land Use Change.

How can I accomplish this?

like image 733
DiamondJoe12 Avatar asked Sep 19 '25 23:09

DiamondJoe12


2 Answers

You could combine the :has selector with the adjacent sibling selector (s1 + s2). So do something like:

$("#myTable").find("tr.header:has(+ tr.header)").hide()
like image 94
Shreyansh Dash Avatar answered Sep 22 '25 13:09

Shreyansh Dash


This is my Vanilla JavaScript take on it.

Before writing the script I changed all name attributes to data-name as trs cannot have name attributes "legally".

In a first filter() loop I make all trs invisible and filter out only those trs that don't match the given pattern pat and are not of class "header". In a forEach() loop applied on this filtered set I then make only those trs visible again that either themselves have a dataset.name attribute or whose direct successor has this attribute.

const trs=[...document.querySelector("#myTable>tbody").children];
function fltTbl(pat){
  trs
   .filter(tr=>(tr.style.display="none",tr.classList.contains("header")||
tr.dataset?.name.indexOf(pat)>-1))
   .forEach((tr,i,a)=>{
  if (tr.dataset.name
      || a[i+1]?.dataset.name)
    tr.style.display="";
 });
}
<button class="btn" onclick="fltTbl('policy-outcomes')">Policy Outcomes</button>
<button class="btn" onclick="fltTbl('latin_america')">Latin America</button>
<button class="btn" onclick="fltTbl('deforestation')">Deforestation</button>

<table class="mytable" id="myTable">
  <tr class="header">
<th style="width:60%;">2020</th>
  </tr>
  <tr data-name="latin_america_zero-deforestation">
<td>"Cattle Ranchers and Deforestation.”
</td>
  </tr>
  <tr data-name="latin_america_policy-outcomes">
<td>“Impacts on Land Use Conversion.”
</td>
  </tr>
  <tr data-name="latin_america_supply-chain_policy-outcomes">
<td>“Costs of the Amazon Soy Moratorium.”
</td>
  </tr>
  <tr class="header">
<th style="width:60%;">2019</th>
  </tr>
  <tr data-name="africa_policy-outcomes">
<td>“Environmental Change”
</td>
  </tr>
  <tr data-name="latin_america_policy-outcomes">
<td>“Land Use Change”
</td>
  </tr>
  <tr class="header">
<th style="width:60%;">2018</th>
  </tr>
  <tr data-name="north_america_zero-deforestation">
<td>“Deforestation Remedies”
</td>
  </tr>
  <tr data-name="latin_america_zero-deforestation">
<td>“Land Use Change in Latin American Cerrados”
</td>
  </tr>
</table>
like image 22
Carsten Massmann Avatar answered Sep 22 '25 14:09

Carsten Massmann