Removing a td that contains text?

Hi there,

I have a td that i am trying to remove using CSS but I don’t think it is possible with CSS.

I have a td that looks like this:

<td ng-bind-html="ctrl.quizMain.questionsData[ctrl.questionId].rows[rowID]" class="ng-binding">remove</td>

What I need to do is remove this td based on the text inside it.

What would be the best way to do this with JS? Or CSS?

Many thanks!

CSS does not operate on the contents of elements, it operates on the elements themselves. (There were proposals, but they’ve been withdrawn)

One way (my brain’s telling me there should be a cleaner one, but… its 6 AM. So this is what my brain comes up with.)

document.evaluate("//td[text()='remove']",document,null,XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
1 Like

Are you wanting to remove the content from the cell, or the cell itself?
You can’t really remove a cell from a table, it would leave a gap. The only way is to increase the span of an adjacent cell to take its space.

1 Like

Good point… in any case, it would probably be desirable to get the actual text nodes first; then you can remove their parent elements or do whatever is appropriate. This can be done using a tree walker that only accepts text nodes containing a given string:

// Creates a tree walker that finds text
// nodes containing a given string
function createTextWalker (root, text) {
  return document.createTreeWalker(root, NodeFilter.SHOW_TEXT, {
    acceptNode (node) {
      return node.textContent.includes(text)
        ? NodeFilter.FILTER_ACCEPT
        : NodeFilter.FILTER_REJECT
    }
  })
}

// Iterator wrapper for convenience
function iterateTreeWalker (walker) {
  return {
    [Symbol.iterator] () {
      return this
    },

    next () {
      const value = walker.nextNode()
      return { value, done: !value }
    }
  }
}

// Find the text nodes and remove their
// parent elements
const textNodes = iterateTreeWalker(
  createTextWalker(document.body, 'remove')
)

for (const node of textNodes) {
  node.parentElement.remove()
}
2 Likes

I am trying to remove the actual cell itself

As I say, a table is a two dimensional grid of a fixed number of rows and columns. You can’t have a different number of columns in a particualr row, except by increasing the span of another cell to knock the cell out.
So can we assume you want to add a colspan or rowspan attribute to an adjacent cell to the one in question? Because nothing else makes sense, except if it were only a single row (one dimensional) table, but semantically, that’s not really a table, that’s a list.

1 Like

Sorry to butt in, but really interested in the createTreeWalker and document.evaluate approaches.

Albeit I have been experimenting with iterators and am vaguely familiar with these two methods, they are not something I have used before.

What would be the advantage over something like this?

  document.addEventListener('DOMContentLoaded', event => {

    const matchCells = (str, root = document) => (
      Array.from(root.querySelectorAll('td')).filter(elem => elem.textContent === str)
    )

    matchCells('Match this!!').forEach( cell => cell.remove() )
  })

edit: Test script

<!DOCTYPE html>
<html lang='en'>
<head>
  <meta charset='UTF-8'>
  <meta name='viewport' content='width=device-width, initial-scale=1.0'>
  <title>Document</title>
</head>
<body>
  <table>
    <caption>Table</caption>
    <tr>
      <td>Match this</td>
      <td>Lorem Impsum</td>
    </tr>
    <tr>
      <td>dolor sit</td>
      <td>Match this!!</td>
    </tr>
    <tr>
      <td>Donec ante dolor</td>
      <td>At ipsum vitae</td>
    </tr>
    <tr>
      <td>Maecenas elit orci</td>
      <td>Match this!!</td>
    </tr>
  </table>
<script>
  document.addEventListener('DOMContentLoaded', event => {

    const matchCells = (str, root = document) => (
      Array.from(root.querySelectorAll('td')).filter(elem => elem.textContent === str)
    )

    matchCells('Match this!!').forEach( cell => cell.remove() )
  })
</script>
</body>
</html>