javascriptjqueryhtml-table

Removing blank <tr> rows left after deleting table content


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:

enter image description here

(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">&nbsp;</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">&nbsp;</td>
</tr>

How can I reliably detect and remove these “ghost” rows?


Solution

  • 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');
          }
        });
      }