Skip to content

Instantly share code, notes, and snippets.

@WickyNilliams
Last active February 22, 2023 15:07
Show Gist options
  • Star 36 You must be signed in to star a gist
  • Fork 17 You must be signed in to fork a gist
  • Save WickyNilliams/9252235 to your computer and use it in GitHub Desktop.
Save WickyNilliams/9252235 to your computer and use it in GitHub Desktop.
parseTable.js - convert HTML table to array of objects. MIT licensed (https://opensource.org/licenses/MIT)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>parseTable</title>
</head>
<body>
<table>
<thead>
<tr>
<th>name</th>
<th>age</th>
<th>eye colour</th>
<th>coffee?</th>
<th>food</th>
</tr>
</thead>
<tbody>
<tr>
<td>dave</td>
<td>35</td>
<td>blue</td>
<td><input type="checkbox" checked /></td>
<td><input type="text" value="sandwich" /></td>
</tr>
<tr>
<td>sarah</td>
<td>29</td>
<td>brown</td>
<td><input type="checkbox" checked /></td>
<td><input type="text" value="soup" /></td>
</tr>
<tr>
<td>john</td>
<td>42</td>
<td>green</td>
<td><input type="checkbox" /></td>
<td><input type="text" value="stew" /></td>
</tr>
</tbody>
</table>
<pre></pre>
<script src="parseTable.js"></script>
<script>
var table = document.querySelector("table");
var output = document.querySelector("pre");
var data = parseTable(table);
// OUTPUTS
// =======
//
// [
// {
// name: "dave",
// age: "35",
// "eye colour": "blue",
// "coffee?": true,
// food: "sandwich"
// },
// {
// name: "sarah",
// age: "29",
// "eye colour": "brown",
// "coffee?": true,
// food: "soup"
// },
// {
// name: "john",
// age: "42",
// "eye colour": "green",
// "coffee?": false,
// food: "stew"
// }
// ]
</script>
</body>
</html>
/**
* @license
*
* The MIT License (MIT)
*
* Copyright (c) 2014 Nick Williams
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/**
* @param {HTMLTableRowElement} row
* @param {string[]} headings
* @returns {Record<string, string | boolean>}
*/
function parseRow(row, headings) {
const rowData = {};
for (const cell of row.cells) {
const input = cell.querySelector("input,select");
let value;
if (input) {
value = input.type === "checkbox" ? input.checked : input.value;
} else {
value = cell.innerText;
}
rowData[headings[cell.cellIndex]] = value;
}
return rowData;
}
/**
* given a table, generate an array of objects.
* each object corresponds to a row in the table.
* each object's key/value pairs correspond to a column's heading and the row's value for that column
*
* @param {HTMLTableElement} table the table to convert
* @return {Array<Object>} array of objects representing each row in the table
*/
function parseTable(table) {
const headings = [];
for (const heading of table.tHead.rows[0].cells) {
headings.push(heading.innerText);
}
const data = [];
for (const row of table.tBodies[0].rows) {
data.push(parseRow(row, headings));
}
return data;
}
@WickyNilliams
Copy link
Author

Can be improved quite a bit by adding type hinting to each column, so you get the correct types back:

<th data-type="int">age</th>

Though you could brute force this by calling JSON.parse(cellValue), but may not give desired results.

Could also add programmatic rules for processing titles to friendlier names, or again use data attributes:

<th data-name="eyeColor">eye color</th>

@DenizUgur
Copy link

Hey, I'm interested in your code but I have a question:
Currently I'm working on a chrome extension and I need to parse a table to array for future process. In the table I don't have part. So how to I process this type of table.

http://codepaste.net/joh9i4

@miriamelia
Copy link

Hello :)
..is it possible to use this code for my Bachelor Thesis?
Thanks & Regards,
Miriam

@WickyNilliams
Copy link
Author

@miriamelia sure thing! I've just added a comment making it explicit that the code is MIT licensed. You are free to reuse, modify etc the code. Just make sure to include the license block and copyright notice when you use it (so that you comply with the MIT license).

Out of curiosity, what are you using it for?

@miriamelia
Copy link

@WickyNilliams thank you very much, MIT license is perfect :)
I am writing an application to build decision trees interactively and I am importing a .csv file as a table, that's where I am using your code.

@josefinaestevez
Copy link

I'm going to use it for my Bachelor Thesis too :)

@WickyNilliams
Copy link
Author

Awesome! Glad to be of help to you :)

@galihprasetio
Copy link

image
how to parse table using input type="checkbox" or input type="text".
Can you help me please ??

thank you,

@WickyNilliams
Copy link
Author

WickyNilliams commented Oct 8, 2019

@galihprasetio i just updated the script, this should now be supported :) for checkboxes it will return true/false for all other inputs it will return its value

@galihprasetio
Copy link

galihprasetio commented Oct 9, 2019

@galihprasetio i just updated the script, this should now be supported :) for checkboxes it will return true/false for all other inputs it will return its value

Very nice @WickyNilliams,
I will apply this in my project.

Thank you very much.

@rcorsari
Copy link

rcorsari commented May 28, 2021

Hello, cool functions! One kind hint request. In the THEAD for the user , I mean the browser view, in the THs I'd like to display nice readable strings.
Meanwhile I'd like to set some data attribute with value the real name for MySQL table row's names when it is time to convert the table to array.
Is it possible to do that in your opinion?
Thank you

WOW I got it :-)
at line #60 instead of innerText I have replaced with dataset.dbrow and into every TH, I have set the attribute data-dbrow="givenDBRowName"

fantastic ( I'm learning javascript :-) )

@SergioPonce2308
Copy link

I want to know how I can skip columns

@WickyNilliams
Copy link
Author

@SergioPonce2308 it's probably easier to remove the field after parsing the table, rather than extend the function

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment