skip to Main Content

I need help with a JavaScript. I tried myself a long time but I really have no clue how to do it. I am a beginner. Can I automatically convert this table?

.tg {
  border-collapse: collapse;
  border-spacing: 0;
}

.tg td {
  font-family: Arial, sans-serif;
  font-size: 14px;
  padding: 10px 5px;
  border-style: solid;
  border-width: 1px;
  overflow: hidden;
  word-break: normal;
}

.tg th {
  font-family: Arial, sans-serif;
  font-size: 14px;
  font-weight: normal;
  padding: 10px 5px;
  border-style: solid;
  border-width: 1px;
  overflow: hidden;
  word-break: normal;
}
<table class="tg">
  <tr>
    <th class="tg-031e">a</th>
    <th class="tg-031e">b</th>
    <th class="tg-031e">c</th>
    <th class="tg-031e">d</th>
    <th class="tg-031e"></th>
  </tr>
  <tr>
    <td class="tg-031e" rowspan="2">1</td>
    <td class="tg-031e">19:10</td>
    <td class="tg-031e">20:30</td>
    <td class="tg-031e">1</td>
    <td class="tg-031e"></td>
  </tr>
  <tr>
    <td class="tg-031e">12:30</td>
    <td class="tg-031e">13:40</td>
    <td class="tg-031e">3</td>
    <td class="tg-031e"></td>
  </tr>
  <tr>
    <td class="tg-031e" rowspan="2">2</td>
    <td class="tg-031e">14:10</td>
    <td class="tg-031e">15:30</td>
    <td class="tg-031e">2</td>
    <td class="tg-031e"></td>
  </tr>
  <tr>
    <td class="tg-031e">9:30</td>
    <td class="tg-031e">10:00</td>
    <td class="tg-031e">3</td>
    <td class="tg-031e"></td>
  </tr>
  <tr>
    <td class="tg-031e" rowspan="2">3</td>
    <td class="tg-031e">8:10</td>
    <td class="tg-031e">8:20</td>
    <td class="tg-031e">4</td>
    <td class="tg-031e"></td>
  </tr>
  <tr>
    <td class="tg-031e">7:10</td>
    <td class="tg-031e">7:20</td>
    <td class="tg-031e">3</td>
    <td class="tg-031e"></td>
  </tr>
  <tr>
    <td class="tg-031e" rowspan="2">4</td>
    <td class="tg-031e">8:10</td>
    <td class="tg-031e">8:20</td>
    <td class="tg-031e">5</td>
    <td class="tg-031e"></td>
  </tr>
  <tr>
    <td class="tg-031e">6:20</td>
    <td class="tg-031e">6:30</td>
    <td class="tg-031e"></td>
    <td class="tg-031e"></td>
  </tr>
</table>

The number of rows at the 1/2/3/4 should be not fixed

Automatically into this json

{
   "1":[
      {
         "a":"19:10",
         "b":"20:30",
         "c":"1"
      },
      {
         "a":"12:30",
         "b":"13:40",
         "c":3
      }
   ],
   "2":[
      {
         "a":"14:10",
         "b":"15:30",
         "c":"2"
      },
      {
         "a":"9:30",
         "b":"10:00",
         "c":"3"
      }
   ],
   "3":[
      {
         "a":"8:10",
         "b":"8:20",
         "c":"4"
      },
      {
         "a":"7:10",
         "b":"7:20",
         "c":"3"
      }
   ],
   "4":[
      {
         "a":"8:10",
         "b":"8:20",
         "c":"5"
      },
      {
         "a":"6:20",
         "b":"6:30",
         "c":"f"
      }
   ]
}

2

Answers


  1. Here’s how I did it

    The only thing missing is the f for the last row, which seems to have appeared out of absolutely nowhere

    const answer = [...document.querySelectorAll(".tg>tbody>tr:has(td)")].reduce((acc, row, index, rows) => {
      const offset = +(row.cells.length > 4);
      const [a, b, c] = [...row.cells].slice(offset).map(({textContent}) => textContent);
      const n = rows[index - 1 + offset].cells[0].textContent;
      acc[n] = acc[n] || [];
      acc[n].push({a, b, c});
      return acc
    }, {})
    console.log(answer)
    .tg {
      border-collapse: collapse;
      border-spacing: 0;
    }
    
    .tg td {
      font-family: Arial, sans-serif;
      font-size: 14px;
      padding: 10px 5px;
      border-style: solid;
      border-width: 1px;
      overflow: hidden;
      word-break: normal;
    }
    
    .tg th {
      font-family: Arial, sans-serif;
      font-size: 14px;
      font-weight: normal;
      padding: 10px 5px;
      border-style: solid;
      border-width: 1px;
      overflow: hidden;
      word-break: normal;
    }
    <table class="tg">
      <tr>
        <th class="tg-031e">a</th>
        <th class="tg-031e">b</th>
        <th class="tg-031e">c</th>
        <th class="tg-031e">d</th>
        <th class="tg-031e"></th>
      </tr>
      <tr>
        <td class="tg-031e" rowspan="2">1</td>
        <td class="tg-031e">19:10</td>
        <td class="tg-031e">20:30</td>
        <td class="tg-031e">1</td>
        <td class="tg-031e"></td>
      </tr>
      <tr>
        <td class="tg-031e">12:30</td>
        <td class="tg-031e">13:40</td>
        <td class="tg-031e">3</td>
        <td class="tg-031e"></td>
      </tr>
      <tr>
        <td class="tg-031e" rowspan="2">2</td>
        <td class="tg-031e">14:10</td>
        <td class="tg-031e">15:30</td>
        <td class="tg-031e">2</td>
        <td class="tg-031e"></td>
      </tr>
      <tr>
        <td class="tg-031e">9:30</td>
        <td class="tg-031e">10:00</td>
        <td class="tg-031e">3</td>
        <td class="tg-031e"></td>
      </tr>
      <tr>
        <td class="tg-031e" rowspan="2">3</td>
        <td class="tg-031e">8:10</td>
        <td class="tg-031e">8:20</td>
        <td class="tg-031e">4</td>
        <td class="tg-031e"></td>
      </tr>
      <tr>
        <td class="tg-031e">7:10</td>
        <td class="tg-031e">7:20</td>
        <td class="tg-031e">3</td>
        <td class="tg-031e"></td>
      </tr>
      <tr>
        <td class="tg-031e" rowspan="2">4</td>
        <td class="tg-031e">8:10</td>
        <td class="tg-031e">8:20</td>
        <td class="tg-031e">5</td>
        <td class="tg-031e"></td>
      </tr>
      <tr>
        <td class="tg-031e">6:20</td>
        <td class="tg-031e">6:30</td>
        <td class="tg-031e"></td>
        <td class="tg-031e"></td>
      </tr>
    </table>
    Login or Signup to reply.
  2. You could parse your html into a DOM document using DOMParser. After that, you can use querySelector() and querySelectorAll() to extract data from the table.

    Here is an example how it can be done:

    function tableToJson(html) {
        // parse html string into dom object
        const doc = new DOMParser().parseFromString(html, "text/html");
        // extract table node
        const table = doc.querySelector("table");
        // extract header names from first row. NOTE: map cannot be called on result of querySelectorAll, it has to be converted to an array using spread operator first
        const headers = [...table.querySelectorAll("th")].map((h) => h.textContent);
        const json = [];
        // iterate through rows not containing table headers
        table.querySelectorAll("tr:not(:has(th))").forEach((row) => {
            const item = {};
            // check if td needs a new json array item
            const spanned = row.querySelector("td[rowspan]");
            const rowspan = spanned ? parseInt(spanned.getAttribute("rowspan")) : 0;
    
            // process all td nodes in row
            row.querySelectorAll("td").forEach((td, index) => { if (td.textContent) item[headers[index]] = td.textContent })
    
            // append current item to json array
            if (rowspan || json.length === 0) {
                // cell is spanned, wrap it in an array under 'json'
                json.push([item]);
            }
            else {
                // push item to last array in 'json'
                json[json.length - 1].push(item);
            }
        })
        return json;
    }
    
    const html = `<style type="text/css">
    .tg {border-collapse:collapse;border-spacing:0;}
    .tg td{font-family:Arial, sans-serif;font-size:14px;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;}
    .tg th{font-family:Arial, sans-serif;font-size:14px;font-weight:normal;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;}
    </style>
    <table class="tg">...`;
    
    const formatted = tableToJson(html);
    

    If your html contains multiple tables, you may specify which table to extract from html by updating this line:

    const table = doc.querySelector("table");
    

    Hope that helps

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search