How do you convert an HTML table to a javascript array using the tags's class names as the array values? Say we have the following HTML code:
<table class="grid">
<tr>
<td class="available"></td>
<td class="busy"></td>
<td class="busy"></td>
<td class="available"></td>
</tr>
<tr>
<td class="busy"></td>
<td class="available"></td>
<td class="busy"></td>
<td class="available"></td>
</tr>
</table>
I want the array to look like: [["available","busy","busy","available"],["busy","available","busy","available"]]
I have tried the following:
var myTableArray = [];
$("table#grid tr").each(function() {
var arrayOfThisRow = [];
var tableData = $(this).find('td');
if (tableData.length > 0) {
tableData.each(function() { arrayOfThisRow.push($(this).text()); });
myTableArray.push(arrayOfThisRow);
}
});
console.log(myTableArray);
but it is printing an empty array as the td tags contain no text. I then tried replacing
$(this).text()
with
$(this).className()
but that did not work. Any suggestions?
CodePudding user response:
map
is the way to go.
jQuery's $.map
is a little weird in that it seems to think it's ok to flatten mapped arrays without asking and we're not going to fix it so you have to couch the mapped array in an array.
// Cache the rows
const rows = $('.grid tr');
// `map` over each row...
const arr = $.map(rows, row => {
// Find the row cells...
const cells = $(row).find('td');
// ...and return an array of each cell's text
return [$.map(cells, cell => $(cell).text())];
});
console.log(arr);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table class="grid">
<tr>
<td class="available">available</td>
<td class="busy">busy</td>
<td class="busy">busy</td>
<td class="available">available</td>
</tr>
<tr>
<td class="busy">busy</td>
<td class="available">available</td>
<td class="busy">busy</td>
<td class="available">available</td>
</tr>
</table>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
Alternatively, if you wanted a vanilla JS solution, you can just pick up the rows with querySelectorAll
, and then iterate over them with map
, then return the text from the cell (assuming that you fix the HTML).
(Note: [...nodelist]
is shorthand for creating an array from a nodelist so that map
can work. You could also use Array.from(nodelist)
).
// Cache the rows
const rows = document.querySelectorAll('.grid tr');
// `map` over each row...
const arr = [...rows].map(row => {
// Find the row cells...
const cells = row.querySelectorAll('td');
// ...and return an array of each cell's text
return [...cells].map(cell => cell.textContent);
});
console.log(arr);
<table class="grid">
<tr>
<td class="available">available</td>
<td class="busy">busy</td>
<td class="busy">busy</td>
<td class="available">available</td>
</tr>
<tr>
<td class="busy">busy</td>
<td class="available">available</td>
<td class="busy">busy</td>
<td class="available">available</td>
</tr>
</table>
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
CodePudding user response:
Vanilla JS Solution
- Get and Make array with
<tr>
- Map every
<tr>
and make array with<td>
elements - Map only class names from every
<td>
The example will return ARRAY from CLASS element names.
Example:
var res = [...document.querySelectorAll('.grid tr')] // 1. Get and Make array with <tr>
.map((el) => [...el.children] // 2. Map every <tr> and make array with <td> elements
.map(e => e.getAttribute('class'))); // 3. Map only class names from every <td>
console.log(res);
<table class="grid">
<tr>
<td class="available"></td>
<td class="busy"></td>
<td class="busy"></td>
<td class="available"></td>
</tr>
<tr>
<td class="busy"></td>
<td class="available"></td>
<td class="busy"></td>
<td class="available"></td>
</tr>
</table>
<iframe name="sif3" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
This example will make ARRAY from the text content of the table.
Example:
var res = [...document.querySelectorAll('.grid tr')] // 1. Get and Make array with <tr>
.map((el) => [...el.children] // 2. Map every <tr> and make array with <td> elements
.map(e => e.innerText)); // 3. Map only text content from every <td>
console.log(res);
<table class="grid">
<tr>
<td>available</td>
<td>busy</td>
<td>busy</td>
<td>available</td>
</tr>
<tr>
<td>busy</td>
<td>available</td>
<td>busy</td>
<td>available</td>
</tr>
</table>
<iframe name="sif4" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>