How To Get Rid Of <tbody> and </tbody> HTML Table Tags But Not Remove The Content Inside The Tags?

635 Views Asked by At

I've taken a look at some of the other questions about removing table tbody tags (see below) but am still stuck on a problem.

<tbody> tag displays in chrome but not source

Javascript delete a table tbody tag

How do i remove <tbody> tags from an HTML table?

After performing an SQL query, I want to generate an HTML table with the results, and then group similar rows by wrapping them in tbody /tbody tags in order to color-code the groups using CSS odd/even notation.

My javascript function to do this works fine, but the problem is that when the rows are first generated, the Chrome browser is wrapping them in tbody /tbody tags. So in the end I am left with the HTML below with an extra set of outer tbody tags (which is messing up the column alignment in the table and not displaying properly).

(* I want to get rid of the outer set of tbody tags *)

<tbody>
   <tbody></tbody>
   <tbody></tbody>
   <tbody></tbody>
   <tbody></tbody>
   <tbody></tbody>
</tbody>

I realize I could work some logic into the php being used to display the table rows to begin with, and try to insert the opening and closing tbody tags that way so that the outer set is never generated, but it's a bit cleaner just displaying all the rows and then grouping them afterwards.

Is it possible to remove the outer tbody tags without removing the content between them? Thanks.

html file

    <!-- start all funds table -->
    <table id="all_funds_table" data-role="table" data-mode="columntoggle" class="table 
      table-sm table-striped table-hover">
        <thead>
            <tr>
                <th>ng</th>
                <th>FID</th>
                <th>Lid</th>
            </tr>
        </thead>
        <!-- <tbody> -->
            <?php                
                if ($result = $connection->query($sql)) {
                    
                    while ($row = $result->fetch_assoc()) {
                        // only display rows with ng = 1
                        if ($row['ng'] == 1) {
            ?>
                            <tr class="gpRep">
                                <td style = "text-align: center"><?= $row['ng'] ?></td>
                                <td style = "text-align: center"><a href="group.php?FID=<?php echo $row['FID']; ?>"><?= $row['FID'] ?></a></td>
                                <td style = "text-align: center"><a href="fund.php?lid=<?php echo $row['lid']; ?>"><?= $row['lid'] ?></a></td>
                            </tr>                  

            <?php
                        // collapse rows with ng != 1
                        } else {
            ?>

                            <tr class="collapse">
                                <td style = "text-align: center"><?= $row['ng'] ?></td>
                                <td style = "text-align: center"><a href="group.php?FID=<?php echo $row['FID']; ?>"><?= $row['FID'] ?></a></td>
                                <td style = "text-align: center"><a href="fund.php?lid=<?php echo $row['lid']; ?>"><?= $row['lid'] ?></a></td>
                            </tr>  
            
            <?php

                        } // end if ($row['ng'] == 1)

                    } // end while
                    $result->free();
                } // end if
            
                if ($mysqli->connect_error) {
                    die("Connection failed: " . $mysqli->connect_error);
                }
                
                $connection->close();
            ?>
            <!-- close connection  -->
            <!-- </tbody> -->
            <script type="text/javascript">
                wrapRows();
            </script>
        </table>
    <!-- end all funds table -->

js file

function wrapRows(){
    $('#all_funds_table tr.gpRep').each(function(){
        $(this).nextUntil('.gpRep').add(this).wrapAll('<tbody />');
    });
} 
1

There are 1 best solutions below

2
On

Using Javascript

Embrace the required <tbody> and instead move the rows outside of it as you iterate over them. Remove the original <tbody> when complete.

Note the need to add the first row back after calling nextUntil in each case.

$('#all_funds_table tr.gpRep').each(function(){
    $(this).nextUntil('.gpRep').addBack().wrapAll('<tbody />')
        .parent().appendTo($('#all_funds_table'));
});
$('#all_funds_table tbody:first').remove();

Using PHP

There really isn't any good reason not to output the <tbody> tags in the first place. This will save processing time in the browser.

    <?php                
        if ($result = $connection->query($sql)) {
            $first = true;
            while ($row = $result->fetch_assoc()) {
                // only display rows with ng = 1
                if ($row['ng'] == 1) {
                    if (!$first) { echo '</tbody>'; }
                    $first = false;
    ?>
                    <tbody>
                    <tr class="gpRep">
                        <td style = "text-align: center"><?= $row['ng'] ?></td>
                        <td style = "text-align: center"><a href="group.php?FID=<?php echo $row['FID']; ?>"><?= $row['FID'] ?></a></td>
                        <td style = "text-align: center"><a href="fund.php?lid=<?php echo $row['lid']; ?>"><?= $row['lid'] ?></a></td>
                    </tr>                  

    <?php
                // collapse rows with ng != 1
                } else {
    ?>

                    <tr class="collapse">
                        <td style = "text-align: center"><?= $row['ng'] ?></td>
                        <td style = "text-align: center"><a href="group.php?FID=<?php echo $row['FID']; ?>"><?= $row['FID'] ?></a></td>
                        <td style = "text-align: center"><a href="fund.php?lid=<?php echo $row['lid']; ?>"><?= $row['lid'] ?></a></td>
                    </tr>  
    
    <?php

                } // end if ($row['ng'] == 1)

            } // end while
            $result->free();
        } // end if
    
        if ($mysqli->connect_error) {
            die("Connection failed: " . $mysqli->connect_error);
        }
        
        $connection->close();
    ?>
    <!-- close connection  -->
    <!-- </tbody> -->
    <script type="text/javascript">
        wrapRows();
    </script>
</tbody>
</table>

This mix of HTML and PHP isn't particularly easy to read. Depending how much data you have to output, you may find it neater to first load the information into an array in the format you want, then convert the array to HTML output.