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?
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()
                        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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With