Convert HTML tables to JSON div elements.

by stitot

HTML

<script src="https://cdn.jsdelivr.net/npm/@highcharts/grid-pro/grid-pro.js"></script>

<button id="convert-tables">Click to convert tables</button>


<table class="static">
  <thead>
    <tr><th>Name</th><th>Age</th><th>City</th></tr>
  </thead>
  <tbody>
    <tr><td>Ada</td><td>36</td><td>London</td></tr>
    <tr><td>Linus</td><td>55</td><td>Helsinki</td></tr>
    <tr><td>Grace</td><td>40</td><td>New York</td></tr>
    <tr><td>Alan</td><td>35</td><td>Manchester</td></tr>
    <tr><td>Katherine</td><td>29</td><td>Toronto</td></tr>
    <tr><td>Tim</td><td>48</td><td>San Francisco</td></tr>
    <tr><td>Margaret</td><td>50</td><td>Sydney</td></tr>
  </tbody>
</table>

<p>Just some lorem lipsum</p>

<table class="static">
  <thead>
    <tr><th>Country</th><th>Population (millions)</th><th>GDP (USD billions)</th></tr>
  </thead>
  <tbody>
    <tr><td>Norway</td><td>5.5</td><td>579</td></tr>
    <tr><td>Sweden</td><td>10.5</td><td>635</td></tr>
    <tr><td>Finland</td><td>5.6</td><td>300</td></tr>
    <tr><td>Denmark</td><td>5.9</td><td>420</td></tr>
    <tr><td>Iceland</td><td>0.4</td><td>34</td></tr>
  </tbody>
</table>

CSS

@import url("https://cdn.jsdelivr.net/npm/@highcharts/grid-pro/css/grid-pro.css");

table.static {
  border-collapse: collapse;
  margin: 20px 0;
  th, td {
    border: 1px solid #000;
    padding: 8px;
  }
}

JavaScript

let gridIndex = 0;

function parseValue(value) {
  const trimmed = value.trim();
  const num = Number(trimmed);
  return !isNaN(num) && trimmed !== "" ? num : trimmed;
}

/* Assumes a well formed table with thead etc., but could be refactored to use e.g. first row in body as headers etc */
function tableToObject(table) {
  const headers = [...table.tHead.rows[0].cells].map((c) =>
    c.textContent.trim(),
  );
  const rows = [...table.tBodies[0].rows];
  const data = Object.fromEntries(headers.map((h) => [h, []]));

  rows.forEach((tr) => {
    [...tr.cells].forEach((cell, i) => {
      const key = headers[i];
      if (key) data[key].push(parseValue(cell.textContent));
    });
  });

  return data;
}

function replaceWithGrid(table, data) {
  const div = document.createElement("div");
  const id = `grid-converted-${++gridIndex}`;

  div.id = id;
  table.parentNode.insertBefore(div, table);
  table.remove();

  Grid.grid(id, {
    dataTable: {
      columns: data,
    },
  });
}

function convertAllTables() {
  document.querySelectorAll("table").forEach((table) => {
    const data = tableToObject(table);
    replaceWithGrid(table, data);
  });
}

document
  .getElementById("convert-tables")
  ?.addEventListener("click", convertAllTables);