I'm writing a Tampermonkey script that removes rows from a table on RateYourMusic voting pages if the descriptor is 'scary', 'disturbing', or 'macabre'. That part works — but the blank rows that remain (empty green blocks) won't go away.
Here's how it looks like:
(I should say that I barely know any JavaScript, and I've been struggling with this problem for a while using ChatGPT to help.)
document.querySelectorAll('td > div:first-child').forEach(div => {
const descriptor = div.textContent.trim().toLowerCase();
if (['scary', 'disturbing', 'macabre'].includes(descriptor)) {
const tr = div.closest('tr');
if (tr) {
console.log('remove', tr.innerHTML)
tr.remove(); // this works!
}
}
});
document.querySelectorAll('tr').forEach(tr => {
const text = tr.textContent.replace(/\s|\u200B|\u00A0/g, '');
if (text === '' && tr.offsetHeight > 30) {
console.log('remove empty',tr.innerHTML)
tr.remove(); // this *doesn't* work reliably
}
});
td {
border: 1px solid black
}
<table>
<tbody>
<tr>
<td colspan="2">
<div>macabre</div>
</td>
</tr>
<tr>
<td colspan="2"> </td>
</tr>
</tbody>
</table>
The second part is meant to clean up leftover ghost rows — visually tall trs with no content — but they’re still showing up. I’ve tried using .textContent, .innerText, and different height thresholds. I also confirmed in DevTools that the remaining rows really are trs, sometimes just containing nbsp;.
Here’s what one of them looks like in DevTools:
<tr>
<td colspan="2"> </td>
</tr>
How can I reliably detect and remove these “ghost” rows?
Thank you all for the advice! Here's the code that ended up working perfectly:
function removeBlockedFromVotingPage() {
document.querySelectorAll('td').forEach(td => {
const tr = td.closest('tr');
if (!tr) return;
const div = td.querySelector('div');
const descriptor = safeText(div);
const text = safeText(td).replace(/\u00A0/g, '');
if (!div && text === '') {
tr.remove();
console.log('[RYM Filter] Removed empty/downvoted row');
} else if (div && isBlocked(descriptor)) {
const prev = tr.previousElementSibling;
const next = tr.nextElementSibling;
if (prev?.matches('div.descriptora') && isBlank(prev)) prev.remove();
if (next?.matches('div.descriptora') && isBlank(next)) next.remove();
tr.remove();
console.log(`[RYM Filter] Removed descriptor: "${descriptor}"`);
}
});
// Remove leftover green separator blocks
document.querySelectorAll('div.descriptora, div.descriptord').forEach(div => {
if (isBlank(div)) {
div.remove();
console.log('[RYM Filter] Removed leftover descriptor block');
}
});
}