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 tr
s cannot have name
attributes "legally".
In a first filter()
loop I make all tr
s invisible and filter out only those tr
s 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 tr
s 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