Benedict K.
Benedict K.

Reputation: 37

Select nested elements with jQuery

I have a problem by selecting an element by jQuery.

I have an HTML table that has a special field. You can see the structure of the field here:

    <td>
      <em class='block'>Create Events:</em>
      -
      <hr style='margin: 8px 0;'>
      <em class='block'>Update Events:</em>
      -
      <hr style='margin: 8px 0;'>
      <em class='block'>Required object:</em>
    </td>

I want to delete the row (the parent element of the td element) if after the first em element follows a "-" (like in the example above).

Sometimes there is something else like in this example:

    <td>
      <em class='block'>Create Events:</em>
      here is something else and this line should not get removed
      <hr style='margin: 8px 0;'>
      <em class='block'>Update Events:</em>
      -
      <hr style='margin: 8px 0;'>
      <em class='block'>Required object:</em>
    </td>

I know how to select elements by class Name or element name or the first child of an element.

But in this case, nothing worked. How can I get the text behind the first em element and test if it is "-" and not an outer string?

Upvotes: 1

Views: 2124

Answers (3)

Shadow4Kill
Shadow4Kill

Reputation: 178

If I understood your question right, You can use regex in order to achieve what you want. Here is a code that I wrote for you.

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>

</head>

<body>
  <table>
    <tr>
      <td>
        <em class='block'>Create Events:</em> -
        <hr style='margin: 8px 0;'>
        <em class='block'>Update Events:</em> -
        <hr style='margin: 8px 0;'>
        <em class='block'>Required object:</em>
      </td>
    </tr>
    <tr>
      <td>
        <em class='block'>Create Events:</em> here is something else and this line should not get removed
        <hr style='margin: 8px 0;'>
        <em class='block'>Update Events:</em> -
        <hr style='margin: 8px 0;'>
        <em class='block'>Required object:</em>
      </td>
    </tr>
  </table>

  <script>
    $('table tr td').each(function() {
      var content = '<td>' + $(this).html() + '</td>';
      var regex =
        /<td>([\s\S]+?)<em class="block">Create Events:<\/em>([\s\S]+?)-([\s\S]+?)<em class="block">Update Events:<\/em>/i;
      if (regex.test(content)) {
        $(this).closest('tr').remove();
      }
    });
  </script>
</body>

</html>

Try this one out, it should work as it worked on my side.

Note: In regex I used " instead of ' because HTML renders both kinds of quotations as "

P.S: This is not a good way to achieve this goal. instead you should wrap your first line of text in a span with an ID then look for if it is - or any other text.

Upvotes: 1

Nihil
Nihil

Reputation: 117

If a full table may or may not contain rows with Create Events: -. Then an iteration would be needed. For each row available in the table, you need to take the first em of the row, and check the next sibling's text content. If it matches a '-', then the whole row should be deleted.

First is the iteration of the table and all it's rows:

$('table tr').each(function(i, tr) {...}

Within the loop, we identify the first em available on each td tag. Then we get the following text using nextSibling.nodeValue and trim it to prevent additional spaces.

var $em = $(tr).find('td em:first');
var createContent = $em[0].nextSibling.nodeValue.trim();

And finally, we compare that the content equals '-'. You can see the full code below.

<table>
    <tr> 
        <td>
            <em class='block'>Create Events:</em> here is something else and this line should not get removed
            <hr />
            <em class='block'>Update Events:</em> -
            <hr />
            <em class='block'>Required object:</em>
        </td>
    </tr>
    <tr>
        <td>
            <em class='block'>Create Events:</em> -
            <hr />
            <em class='block'>Update Events:</em> -
            <hr />
            <em class='block'>Required object:</em>
        </td>
    </tr>
</table>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
    $(document).ready(function() {
        $('table tr').each(function(i, tr) {
            var $em = $(tr).find('td em:first');
            var createContent = $em[0].nextSibling.nodeValue.trim();

            if (createContent === '-') {
                $(tr).remove();
            }
        });
    });
</script>

You can check the documentation of jQuery's each here.

Upvotes: 0

Rory McCrossan
Rory McCrossan

Reputation: 337560

To achieve this you need to look for the text node following the first em. To to that you can select the element in jQuery and then retrieve the nextSibling node from the underlying Element object.

If you place that logic in a filter() which checks the node's value, then you can simply remove() the rows where it's empty, something like this:

$('tr').filter(function() {
  return ($(this).find('td em:first')[0].nextSibling.textContent || '').trim() === '-';
}).remove();
hr { margin: 8px 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
  <tr>
    <td>
      <em class='block'>Create Events:</em> -
      <hr />
      <em class='block'>Update Events:</em> -
      <hr />
      <em class='block'>Required object:</em>
    </td>
  </tr>
  <tr>

    <td>
      <em class='block'>Create Events:</em> here is something else and this line should not get removed
      <hr />
      <em class='block'>Update Events:</em> -
      <hr />
      <em class='block'>Required object:</em>
    </td>
  </tr>
</table>

Upvotes: 0

Related Questions