-1

I'm trying to use plain javascript to take existing table td elements, empty the table and recreate it with row length of 3.

The plan was to capture the existing td elements, empty the table, loop through the td's, then fill a new tr element with 3 td cells, add the tr to a new tbody, then empty the tr and start over until the loop is done. However, the tbody never has more than 1 child element when I expect it to eventually have more than 1, and the end result is unexpected. Not shown below are the numerous log statements I used to debug, but I could not figure it out. And could not find others with similar problem except for jQuery solutions.

In a separate test based on this post, I tried using insertRow(), insertCell() instead of appendChild(), but I got same result.

I expected to be able to reuse after emptying it. What am I doing wrong?

NOTE: the images below are just stubs/placeholders, so nothing to look at :(

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>title</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.2/css/bulma.min.css" />
</head>
<body>  
    <section class="hero is-fullheight is-primary has-background-info">
        <div class="hero-body">
            <div class="container has-text-centered">
                <button onclick="redistributeCells()">redistributeCells</button>
            </div>
        </div>
        <div class="hero-body">
            <div class="container" style="max-width: 1350px;">
            <div class="columns is-vcentered">
                <div class="column is-fullwidth">
                    <div class="box" style="background-color: inherit">
                        <div class="table-container" id="myContainer">
                            <table class="table is-small" style="background-color: inherit;width:100%;" id="myTable">
                                <tbody>
                                    <tr>
                                        <td style="border: 0;"> 
                                            <figure class="image is-128x128" >
                                                <img src=https://res.cloudinary.com/xyz/image/upload/v1651958398/hhqjr29kfizcfz4jsndm.jpg >
                                            </figure>
                                        </td>
                                        <td style="border: 0;"> 
                                            <figure class="image is-128x128" >
                                                <img src=https://res.cloudinary.com/xyz/image/upload/v1651958378/w8yfkzjrb5ysjvuvqoax.jpg >
                                            </figure>
                                        </td>
                                        <td style="border: 0;"> 
                                            <figure class="image is-128x128" >
                                                <img src=https://res.cloudinary.com/xyz/image/upload/v1651784771/bufc2xs29j3m2yor9fup.jpg >
                                            </figure>
                                        </td>
                                        <td style="border: 0;"> 
                                            <figure class="image is-128x128" >
                                                <img src=https://res.cloudinary.com/xyz/image/upload/v1651784215/m4mcbt2sfqp7zskn2sii.jpg >
                                            </figure>
                                        </td>
                                        <td style="border: 0;"> 
                                            <figure class="image is-128x128" >
                                                <img src=https://res.cloudinary.com/xyz/image/upload/v1651705127/samples/people/boy-snow-hoodie.jpg >
                                            </figure>
                                        </td>
                                        <td style="border: 0;"> 
                                            <figure class="image is-128x128" >
                                                <img src=https://res.cloudinary.com/xyz/image/upload/v1651705126/samples/bike.jpg >
                                            </figure>
                                        </td>
                                    </tr>
                                    <tr>
                                        <td style="border: 0;"> 
                                            <figure class="image is-128x128" >
                                                <img src=https://res.cloudinary.com/xyz/image/upload/v1651705125/samples/ecommerce/shoes.png >
                                            </figure>
                                        </td>
                                    </tr>
                                </tbody>
                            </table>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </section>
    <script type="text/javascript">
        function show(item) {
            console.log(item);
        }
        
        function redistributeCells() {
            // let container = document.querySelector("#myContainer");
            let table = document.querySelector('#myTable');
            let cells = document.querySelectorAll('#myTable td');
            
            // Empty table
            table.replaceChildren();
            // New tbody
            let tbody = document.createElement('tbody');
            
            // Rebuild cell rows
            let tr = document.createElement('tr');
            
            show('cells: ' + cells.length);                     // 7

            for( let i=0; i < cells.length; i++ ) {

                if (i % 3 == 0 && i != 0) {
                    // Append row to body
                    tbody.appendChild(tr);
                    // Empty row to reuse again
                    tr.replaceChildren();
                }
                // Continue adding cells to row
                tr.appendChild(cells[i]);
                show('end-tbody: ' + tbody.children.length);   // always 0 or 1
            }
            // Add last row containing remaining td's to body
            tbody.appendChild(tr);
            // Add body to table
            table.appendChild(tbody);
        }
    </script>
</body>

</html>

Expected result:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>title</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.2/css/bulma.min.css" />
</head>
<body>  
    <section class="hero is-fullheight is-primary has-background-info">
        <div class="hero-body">
            <div class="container has-text-centered">
                <button onclick="redistributeCells()">redistributeCells</button>
            </div>
        </div>
        <div class="hero-body">
            <div class="container" style="max-width: 1350px;">
            <div class="columns is-vcentered">
                <div class="column is-fullwidth">
                    <div class="box" style="background-color: inherit">
                        <div class="table-container" id="myContainer">
                            <table class="table is-small" style="background-color: inherit;width:100%;" id="myTable">
                                <tbody>
                                    <tr>
                                        <td style="border: 0;"> 
                                            <figure class="image is-128x128" >
                                                <img src=https://res.cloudinary.com/xyz/image/upload/v1651958398/hhqjr29kfizcfz4jsndm.jpg >
                                            </figure>
                                        </td>
                                        <td style="border: 0;"> 
                                            <figure class="image is-128x128" >
                                                <img src=https://res.cloudinary.com/xyz/image/upload/v1651958378/w8yfkzjrb5ysjvuvqoax.jpg >
                                            </figure>
                                        </td>
                                        <td style="border: 0;"> 
                                            <figure class="image is-128x128" >
                                                <img src=https://res.cloudinary.com/xyz/image/upload/v1651784771/bufc2xs29j3m2yor9fup.jpg >
                                            </figure>
                                        </td>
                                    </tr>
                                    <tr>
                                        <td style="border: 0;"> 
                                            <figure class="image is-128x128" >
                                                <img src=https://res.cloudinary.com/xyz/image/upload/v1651784215/m4mcbt2sfqp7zskn2sii.jpg >
                                            </figure>
                                        </td>
                                        <td style="border: 0;"> 
                                            <figure class="image is-128x128" >
                                                <img src=https://res.cloudinary.com/xyz/image/upload/v1651705127/samples/people/boy-snow-hoodie.jpg >
                                            </figure>
                                        </td>
                                        <td style="border: 0;"> 
                                            <figure class="image is-128x128" >
                                                <img src=https://res.cloudinary.com/xyz/image/upload/v1651705126/samples/bike.jpg >
                                            </figure>
                                        </td>
                                    </tr>
                                    <tr>
                                        <td style="border: 0;"> 
                                            <figure class="image is-128x128" >
                                                <img src=https://res.cloudinary.com/xyz/image/upload/v1651705125/samples/ecommerce/shoes.png >
                                            </figure>
                                        </td>
                                    </tr>
                                </tbody>
                            </table>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </section>
    <script type="text/javascript" src="/static/js/app.js"></script>
    <script type="text/javascript">
    </script>    
</body>
</html>

1 Answers1

0

Details are commented in example below

const tBa = document.querySelector('tbody');

/**
* Function's purpose is to extract the `<td>` of a HTML `<table>` and 
* redistribute them in new `<tr>`s and a `<tbody>` that's built to
* a given number of columns.Then, it'll remove the original `<tbody>` 
* and append the new `<tbody>`.
* @param {object<DOM>} node - The `<tbody>` of targeted `<table>`.
* @param {number} cols - The amount of `<td>` per `<tr>`.
*/
const reDistTable = (nodeA, cols) => {
  // Calculate the number of rows needed for new <tbody>
  let size = nodeA.rows[0].cells.length;
  let quo = ~~(size / cols);
  let ext = size % cols > 0 ? 1 : 0;
  const rows = quo + ext;

  // Extract the <td> from old <tbody>
  let tData = [...nodeA.rows].flatMap(tr => [...tr.cells]).map(td => td);
  // Create new <tbody>
  const nodeB = nodeA.parentElement.createTBody();
  // Remove the old <tbody>
  nodeA.remove();
  
  for (let r = 0; r < rows; r++) {
    // Create and add <tr> to new <tbody>
    let row = nodeB.insertRow();
    for (let c = 0; c < cols; c++) {
      /* 
      Until there's no more <td> in tData array, take tData's first <td>
      and add it to the new <tbody>, otherwise add an empty `<td>`
      */
      let data = tData.length < 1 ? document.createElement('td') : tData.shift();
      row.append(data);
    }
  }
}

reDistTable(tBa, 3);
table,
td {
  border: 1px solid black;
}

table {
  border-collapse: collapse;
  width: 100%
}

figure {
  display: flex;
  width: 100%;
  margin: 0;
}

img {
  display: inline-block;
  width: 100%;
  height: auto;
  object-fit: contain;
}
<table>
  <tbody>
    <tr>
      <td>
        <figure>
          <img src='
https://placem.at/people?w=160&h=90&random=1&txt=1&txtclr=fc0'>
        </figure>
      </td>
      <td>
        <figure>
          <img src='
https://placem.at/places?w=160&h=90&random=1&txt=2&txtclr=fc0'>
        </figure>
      </td>
      <td>
        <figure>
          <img src='
https://placem.at/people?w=160&h=90&random=1&txt=3&txtclr=fc0'>
        </figure>
      </td>
      <td>
        <figure>
          <img src='
https://placem.at/things?w=160&h=90&random=1&txt=4&txtclr=fc0'>
        </figure>
      </td>
      <td>
        <figure>
          <img src='
https://placem.at/places?w=160&h=90&random=1&txt=5&txtclr=fc0'>
        </figure>
      </td>
      <td>
        <figure>
          <img src='
https://placem.at/people?w=160&h=90&random=1&txt=6&txtclr=fc0'>
        </figure>
      </td>
      <td>
        <figure>
          <img src='
https://placem.at/things?w=160&h=90&random=1&txt=7&txtclr=fc0'>
        </figure>
      </td>
      <td>
        <figure>
          <img src='
https://placem.at/places?w=160&h=90&random=1&txt=8&txtclr=fc0'>
        </figure>
      </td>
      <td>
        <figure>
          <img src='
https://placem.at/people?w=160&h=90&random=1&txt=9&txtclr=fc0'>
        </figure>
      </td>
      <td>
        <figure>
          <img src='
https://placem.at/things?w=160&h=90&random=1&txt=10&txtclr=fc0'>
        </figure>
      </td>
    </tr>
  </tbody>
</table>
zer00ne
  • 41,936
  • 6
  • 41
  • 68