Convert table to key-value pair with plain JS - javascript

I have a large table consisting of row numbers and prices. I want to be able to look up a price by using the row number.
function buildtable(){
var tableObj = document.getElementById( 'table' );
var allTRs = tableObj.getElementsByTagName( 'tr' );
for ( var trCounter = 0; trCounter < allTRs.length; trCounter++ )
{
var tmpArr = [];
var allTDsInTR = allTRs[ trCounter ].getElementsByTagName( 'td' );
for ( var tdCounter = 0; tdCounter < allTDsInTR.length - 1; tdCounter++ )
{
tmpArr.push( allTDsInTR[ tdCounter ].innerHTML );
}
arr.push( tmpArr );
}
}
the following code creates a list of lists.
How can I change the function so its creates a single key pair store?
HTML FOR TABLE
foreach($res as $row) {
$seat = $row['RowNumber'];
$price = $row['Zone.PriceMultiplier * 15.00'];
echo "<tr>";
echo "<td>".$seat."</td>";
echo "<td>".$price."</td>";
echo "<td><input type='checkbox' name='check_list[]' value=\"$seat;\" onclick='javatest(this);' </td>";
echo "</tr>";
}

You can use an object as the key-value map (hash table).
function buildtable() {
var tableObj = document.getElementById('table');
var map = {};
var allTRs = tableObj.getElementsByTagName('tr');
for (var trCounter = 1; trCounter < allTRs.length; trCounter++) {
var tmpArr = [];
var allTDsInTR = allTRs[trCounter].getElementsByTagName('td');
if (allTDsInTR.length) {
map[allTDsInTR[0].innerHTML.trim()] = parseFloat(allTDsInTR[1].innerHTML.trim());
}
}
console.log(map);
}
buildtable();
<table id='table'>
<thead>
<tr>
<td>
RowNumber
</td>
<td>
Price
</td>
<tr>
</thead>
<tbody>
<tr>
<td>
U01
</td>
<td>
24.5
</td>
<tr>
<tr>
<td>
U02
</td>
<td>
22
</td>
<tr>
</tbody>
</table>
The result will be something like:
{
"U01": 24.5,
"U02": 22
}

Something like this?
var tableRows = Array.from(document.querySelectorAll('#myTable > tbody > tr'));
var result = {};
tableRows.forEach(row => {
var cols = Array.from(row.getElementsByTagName('td'));
var key = cols[0].innerHTML;
var value = cols[1].innerHTML;
if (!result[key]) {
result[key] = [value];
} else {
result[key].push(value);
}
});
console.log(result);
<table id="myTable">
<thead>
<tr>
<th>RowNumber</th>
<th>Price</th>
</tr>
</thead>
<tbody>
<tr>
<td>U01</td>
<td>26.999999284744263</td>
</tr>
<tr>
<td>U02</td>
<td>26.999999284744263</td>
</tr>
<tr>
<td>U01</td>
<td>26.999999284744263</td>
</tr>
</tbody>
</table>

Related

How to insert array values into a HTML table with javascript?

I am trying to put an array in a HTML table with javascript function but i dont khont how to insert this array? The idea is when i click on button Insert, it'll add one person's information into row.
This's my table
<script>
//Array
var a = [
{name:"Micheal", age:20, hometown:"New York"},
{name:"Santino", age:25, hometown:"Los Angeles"},
{name:"Fredo", age:29, hometown:"California"},
{name:"Hagen", age:28, hometown:"Long Beach"},
]
//Insert data function
function Insert_Data() {
var table = document.getElementById("myTable");
//Help......
}
</script>
<!--Button Insert-->
<input type="button" onclick="Insert_Data" value="Insert" />
<!--Table-->
<table id="myTable">
<tr>
<th>Full Name</th>
<th>Age</th>
<th>Country</th>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
</tr>
</table>
You declare both thead and tbody and in function in loop fill the table
var a = [
{name:"Micheal", age:20, hometown:"New York"},
{name:"Santino", age:25, hometown:"Los Angeles"},
{name:"Fredo", age:29, hometown:"California"},
{name:"Hagen", age:28, hometown:"Long Beach"},
]
//Insert data function
function Insert_Data() {
var table = document.getElementById("datas");
table.innerHTML="";
var tr="";
a.forEach(x=>{
tr+='<tr>';
tr+='<td>'+x.name+'</td>'+'<td>'+x.age+'</td>'+'<td>'+x.hometown+'</td>'
tr+='</tr>'
})
table.innerHTML+=tr;
//Help......
}
<input type="button" onclick="Insert_Data()" value="Insert" />
<!--Table-->
<table id="myTable">
<thead>
<tr>
<th>Full Name</th>
<th>Age</th>
<th>Country</th>
</tr>
</thead>
<tbody id="datas">
</tbody>
</table>
Demo proof: https://jsfiddle.net/psw41g6k/
function Insert_Data() {
var table = document.getElementById("myTable");
var rows = table.querySelectorAll('tr');
console.log(rows)
for (let i = 1; i < rows.length; i++) {
rows[i].children[0].textContent = a[i-1].name
rows[i].children[1].textContent = a[i-1].age
rows[i].children[2].textContent = a[i-1].hometown
}
}
For dynamic tables if you gonna change your array frequently
let tableBody = a.reduce((rows, nextRow) =>{
return rows +=
'<tr>' +
Object.keys(nextRow).reduce((cols, nextCol) => {
return cols += '<th>' + nextRow[nextCol] + '</th>'
}, '') +
'</tr>'
}, '')
Create a dynamic element tr and td at the click of the button and append it to the table element in the document.
Use https://www.w3schools.com/jsref/met_node_appendchild.asp as a reference to understand how to create a dynamic element.
Here is a completely generic method, you can add a new key and it adds a new column to the data, no problem:
//Array
var myData = [
{name:"Micheal", age:20, hometown:"New York", example: "extra"},
{name:"Santino", age:25, hometown:"Los Angeles", example: "extra"},
{name:"Fredo", age:29, hometown:"California", example: "extra"},
{name:"Hagen", age:28, hometown:"Long Beach", example: "extra"},
]
//get references to the table and the head and body:
const myTable = document.getElementById('myTable');
const myTable_header = myTable.querySelector('thead')
const myTable_body = myTable.querySelector('tbody')
//Insert data function
function Insert_Data() {
//Help...... :
myTable_header.innerHTML = '';
var tr = document.createElement('tr');
const headers_data = Object.keys(myData[0]);
headers_data.forEach((key) => {
var th = document.createElement('th')
th.innerHTML = key
tr.appendChild(th);
})
myTable_header.appendChild(tr);
myTable_body.innerHTML = '';
for (let i = 0; i < myData.length; i++){
var tr = document.createElement('tr');
headers_data.forEach((key) => {
var td = document.createElement('td');
td.innerHTML = myData[i][key]
tr.appendChild(td);
});
myTable_body.appendChild(tr);
}
}
<!--Button Insert-->
<input type="button" onclick="Insert_Data()" value="Insert" />
<!--Table-->
<table id="myTable">
<thead>
<!-- Data is injected here -->
</thead>
<tbody>
<!-- Data is injected here -->
</tbody>
</table>

How to show data from a database in my table from my website?

I have a database that I want to access to display my product data, in this case the ItemCode and ItemName.
the connections are all correct and the functional, my problems is the loop and show the data in the table that I have in the html file.
let ctrl = {
showDados: function(r) {
/*dados[3].ItemCode;*/
let dados = JSON.parse(r.responseText);
let cod = dados.ItemCode;
let name = dados.ItemName;
let text = "";
let i;
for (i = 0; i < cod.length; i++) {
text += cod[i] + "<br>";
}
document.getElementById("cod").innerHTML = text;
for (i = 0; i < name.length; i++) {
text += name[i] + "<br>";
}
document.getElementById("name").innerHTML = text;
},
init: function() {
util.ajax(settings.serviceAddress + "OITM", ctrl.showDados);
}
};
$(document).ready(function() {
ctrl.init();
});
<div class="container">
<table class="table table-hover">
<thead>
<tr>
<th>Código</th>
<th>Nome</th>
</tr>
</thead>
<tbody>
<tr>
<td id="cod">FSE0204</td>
<td id="name">25130101_Loc.Finaneira - BCP- CT 400105814</td>
</tr>
<tr>
<td>FSE0205</td>
<td>25130201_Loc.Finaneira - Totta- CT 195649</td>
</tr>
</tbody>
</table>
</div>

jQuery - Combine <TR>(s) values that are in same Section # with same Group # / remove duplicates

I have updated the code, which is currently working up to the Place for each Group #. The existing code determines a matching Section # with Group #, and combines the TR values, adding the Average(s) and dividing by the number of TR(s), and removing any duplicate(s).
I am attempting to determine a Place for each Group # within a Section #. (*example - Section 1: Group #1 - 1st / Group #2 - 3rd / Group #3 - 2nd)
$(function() {
alert('View Table Before Grouping');
sort_array();
combine_rows();
compute_average();
});
//function sort_array
function sort_array() {
var $table = $('table');
var header = $('table tr:first-child').html();
var l = [];
$table.find('tr').each( function() {
//get values from td(s) from each row
var section = $(this).find('.class_section_number').text();
var group_number = $(this).find('.group_number').text();
var average = $(this).find('td:eq(2)').text();
var place = $(this).find('td:eq(3)').text();
//add to array
l.push([section, group_number, average, place]);
//remove saved row
$(this).remove();
});
l = l.slice(1);
//sort the array by section #, then group #
l.sortBy(0, true, 1, true, 2, false);
$table.prepend(header);
//rebuild table after sort
$.each(l, function(key, value) {
$('table').append('<tr><td class="class_section_number">' + value[0] + '</td><td class="group_number">' + value[1] + '</td><td class="grade">' + value[2] + '</td><td>' + value[3] + '</td></tr>');
});
}
//function combine_rows
function combine_rows() {
$('table tr').each( function() {
//get current row data
var section = $(this).find('.class_section_number').text();
var group = $(this).find('.group_number').text();
var average = $(this).find('td:eq(2)').text();
//get next row data
var next_section = $(this).next('tr').find('.class_section_number').text();
var next_group = $(this).next('tr').find('.group_number').text();
var next_average = $(this).next('tr').find('td:eq(2)').text();
//check for section # / group # row match
if ((section === next_section) && (group === next_group)) {
//check for empty average
if (average === 'No Data') {
average = 0 + ',' + next_average;
}
else {
average = average + ',' + next_average;
}
//set combined average
$(this).next('tr').find('td:eq(2)').text(average);
//remove matching row
$(this).remove();
}
});
}
//function compute_average
function compute_average() {
$('table tr').each( function() {
//get average from row
var average = $(this).find('td:eq(2)').text();
//split average into array (*if comma separated values)
average_array = average.split(',');
var total = 0;
//total average values from array / divide by count and set
for (var i = 0; i < average_array.length; i++) {
total += (+average_array[i]);
$(this).find('td:eq(2)').text((total / average_array.length).toFixed(2));
}
});
}
//array sort function
Array.prototype.sortBy = function (propertyName, sortDirection) {
var sortArguments = arguments;
this.sort(function (objA, objB) {
var result = 0;
for (var argIndex = 0; argIndex < sortArguments.length && result === 0; argIndex += 2) {
var propertyName = sortArguments[argIndex];
result = (objA[propertyName] < objB[propertyName]) ? -1 : (objA[propertyName] > objB[propertyName]) ? 1 : 0;
result *= sortArguments[argIndex + 1] ? 1 : -1;
}
return result;
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.1/jquery.min.js"></script>
<table>
<tbody>
<tr>
<th>Section #</th>
<th>Group #</th>
<th>Averages</th>
<th>Place</th>
</tr>
<tr>
<td class="class_section_number">1</td>
<td class="group_number">2</td>
<td class="grade">78.29</td>
<td>Test Place 1st</td>
</tr>
<tr>
<td class="class_section_number">1</td>
<td class="group_number">2</td>
<td class="grade">85.52</td>
<td>Test Place 1st</td>
</tr>
<tr>
<td class="class_section_number">1</td>
<td class="group_number">1</td>
<td class="grade">74.41</td>
<td>Test Place 2nd</td>
</tr>
<tr>
<td class="class_section_number">1</td>
<td class="group_number">2</td>
<td>No Data</td>
<td>Test Place 3rd</td>
</tr>
<tr><td class="class_section_number">2</td>
<td class="group_number">1</td>
<td class="grade">78.90</td>
<td>Test Place 2nd</td>
</tr>
</tr>
<tr><td class="class_section_number">1</td>
<td class="group_number">3</td>
<td class="grade">91.03</td>
<td>Test Place 2nd</td>
</tr>
</tr>
<tr><td class="class_section_number">2</td>
<td class="group_number">2</td>
<td class="grade">81.69</td>
<td>Test Place 2nd</td>
</tr>
<tr>
<td class="class_section_number">2</td>
<td class="group_number">2</td>
<td class="grade">81.13</td>
<td>Test Place 1st</td>
</tr>
<tr>
<td class="class_section_number">2</td>
<td class="group_number">2</td>
<td class="grade">78.13</td>
<td>Test Place 1st</td>
</tr>
</tbody>
</table>

Iterate over table cells, re-using rowspan values

I have a simple HTML table, which uses rowspans in some random columns. An example might look like
A | B |
---|---| C
D | |
---| E |---
F | | G
I'd like to iterate over the rows such that I see rows as A,B,C, D,E,C, then F,E,G.
I think I can probably cobble together something very convoluted using cell.index() to check for "missed" columns in later rows, but I'd like something a little more elegant...
without jquery:
function tableToMatrix(table) {
var M = [];
for (var i = 0; i < table.rows.length; i++) {
var tr = table.rows[i];
M[i] = [];
for (var j = 0, k = 0; j < M[0].length || k < tr.cells.length;) {
var c = (M[i-1]||[])[j];
// first check if there's a continuing cell above with rowSpan
if (c && c.parentNode.rowIndex + c.rowSpan > i) {
M[i].push(...Array.from({length: c.colSpan}, () => c))
j += c.colSpan;
} else if (tr.cells[k]) {
var td = tr.cells[k++];
M[i].push(...Array.from({length: td.colSpan}, () => td));
j += td.colSpan;
}
}
}
return M;
}
var M = tableToMatrix(document.querySelector('table'));
console.table(M.map(r => r.map(c => c.innerText)));
var pre = document.createElement('pre');
pre.innerText = M.map(row => row.map(c => c.innerText).join('\t')).join('\n');
document.body.append(pre);
td {
border: 1px solid rgba(0,0,0,.3);
}
<table>
<tr>
<td colspan=2>A</td>
<td rowspan=2>B</td>
</tr>
<tr>
<td>C</td>
<td rowspan=3>D</td>
</tr>
<tr>
<td rowspan=2>E</td>
<td rowspan=4>F</td>
</tr>
<tr></tr>
<tr>
<td rowspan=2 colspan=2>G</td>
</tr>
<tr></tr>
<tr>
<td rowspan=3 colspan=3>H</td>
</tr>
<tr></tr>
<tr></tr>
<tr>
<td colspan=3>I</td>
</tr>
</table>
Try this:
<table id="tbl">
<tr>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td colspan="2" rowspan="2">A</td>
<td rowspan="2">C</td>
</tr>
<tr>
<td rowspan="2">E</td>
</tr>
<tr>
<td>F</td>
<td>G</td>
</tr>
</table>
Script:
var finalResult = '';
var totalTds = $('#tbl TR')[0].length;
var trArray = [];
var trArrayValue = [];
var trIndex = 1;
$('#tbl TR').each(function(){
var currentTr = $(this);
var tdIndex = 1;
trArray[trIndex] = [];
trArrayValue[trIndex] = [];
var tdActuallyTraversed = 0;
var colspanCount = 1;
$('#tbl TR').first().children().each(function(){
if(trIndex > 1 && trArray[trIndex - 1][tdIndex] > 1)
{
trArray[trIndex][tdIndex] = trArray[trIndex - 1][tdIndex] - 1;
trArrayValue[trIndex][tdIndex] = trArrayValue[trIndex - 1][tdIndex];
finalResult = finalResult + trArrayValue[trIndex][tdIndex];
}
else
{
if(colspanCount <= 1)
{
colspanCount = currentTr.children().eq(tdActuallyTraversed).attr('colspan') != undefined ? currentTr.children().eq(tdActuallyTraversed).attr('colspan') : 1;
}
if(colspanCount > 1 && tdIndex > 1)
{
trArray[trIndex][tdIndex] = currentTr.children().eq(tdActuallyTraversed + colspanCount).attr('rowspan') != undefined ?currentTr.children().eq(tdActuallyTraversed + colspanCount).attr('rowspan') : 1;
trArrayValue[trIndex][tdIndex] = trArrayValue[trIndex][tdIndex - 1];
colspanCount--;
}
else
{
trArray[trIndex][tdIndex] = currentTr.children().eq(tdActuallyTraversed).attr('rowspan') != undefined ?currentTr.children().eq(tdActuallyTraversed).attr('rowspan') : 1;
trArrayValue[trIndex][tdIndex] = currentTr.children().eq(tdActuallyTraversed).html();
tdActuallyTraversed++;
}
finalResult = finalResult + trArrayValue[trIndex][tdIndex];
}
tdIndex++;
});
trIndex++;
});
alert(finalResult);
Fiddle
i am not sure about the performance, but it works well.
what I understood with your question is: You want to split the merged cell with same value and then iterate the table simply by row.
I've created a JSFiddle that will split the merged cells with the same value. Then you'll have a table that can be iterated simply by rows to get the desired output that you specified.
See it running here http://jsfiddle.net/9PZQj/3/
Here's the complete code:
<table id="tbl" border = "1">
<tr>
<td>A</td>
<td>B</td>
<td rowspan="2">C</td>
</tr>
<tr>
<td>D</td>
<td rowspan="2">E</td>
</tr>
<tr>
<td>F</td>
<td>G</td>
</tr>
</table>
<br>
<div id="test"> </div>
Here's the jquery that is used to manipulate the table's data.
var tempTable = $('#tbl').clone(true);
var tableBody = $(tempTable).children();
$(tableBody).children().each(function(index , item){
var currentRow = item;
$(currentRow).children().each(function(index1, item1){
if($(item1).attr("rowspan"))
{
// copy the cell
var item2 = $(item1).clone(true);
// Remove rowspan
$(item1).removeAttr("rowspan");
$(item2).removeAttr("rowspan");
// last item's index in next row
var indexOfLastElement = $(currentRow).next().last().index();
if(indexOfLastElement <= index1)
{
$(currentRow).next().append(item2)
}
else
{
// intermediate cell insertion at right position
$(item2).insertBefore($(currentRow).next().children().eq(index1))
}
}
});
console.log(currentRow)
});
$('#test').append(tempTable);
You can use this Gist. It supports all the requirements by W3C, even "rowspan=0" (which seems to be only supported by Firefox).

Click table row and get value of all cells

I don't know JQuery, so I'm hoping there is a way to do this in pure Javascript.
I need to click on a table row and get the value of each cell in that row. Here is the format of my table:
<table class='list'>
<tr>
<th class='tech'>OCB</th>
<th class='area'>Area</th>
<th class='name'>Name</th>
<th class='cell'>Cell #</th>
<th class='nick'>Nickname</th>
</tr>
<tr onclick="somefunction()">
<td>275</td>
<td>Layton Installation</td>
<td>Benjamin Lloyd</td>
<td>(801) 123-456</td>
<td>Ben</td>
</tr>
</table>
Is there anyway short of putting a unique ID to each cell?
There is no need to add ids or add multiple event handlers to the table. One click event is all that is needed. Also you should use thead and tbody for your tables to separate the heading from the content.
var table = document.getElementsByTagName("table")[0];
var tbody = table.getElementsByTagName("tbody")[0];
tbody.onclick = function (e) {
e = e || window.event;
var data = [];
var target = e.srcElement || e.target;
while (target && target.nodeName !== "TR") {
target = target.parentNode;
}
if (target) {
var cells = target.getElementsByTagName("td");
for (var i = 0; i < cells.length; i++) {
data.push(cells[i].innerHTML);
}
}
alert(data);
};
<table class='list'>
<thead>
<tr>
<th class='tech'>OCB</th>
<th class='area'>Area</th>
<th class='name'>Name</th>
<th class='cell'>Cell #</th>
<th class='nick'>Nickname</th>
</tr>
</thead>
<tbody>
<tr>
<td>275</td>
<td>Layton Installation</td>
<td>Benjamin Lloyd</td>
<td>(801) 123-456</td>
<td>Ben</td>
</tr>
</tbody>
</table>
Example:
http://jsfiddle.net/ZpCWD/
Check this fiddle link
HTML:
<table id="rowCtr" class='list'>
<thead>
<tr>
<th class='tech'>OCB</th>
<th class='area'>Area</th>
<th class='name'>Name</th>
<th class='cell'>Cell #</th>
<th class='nick'>Nickname</th>
</tr>
</thead>
<tbody>
<tr>
<td>275</td>
<td>Layton Installation</td>
<td>Benjamin Lloyd</td>
<td>(801) 123-456</td>
<td>Ben</td>
</tr>
</tbody>
</table>
JAVASCRIPT:
init();
function init(){
addRowHandlers('rowCtr');
}
function addRowHandlers(tableId) {
if(document.getElementById(tableId)!=null){
var table = document.getElementById(tableId);
var rows = table.getElementsByTagName('tr');
var ocb = '';
var area = '';
var name = '';
var cell = '';
var nick = '';
for ( var i = 1; i < rows.length; i++) {
rows[i].i = i;
rows[i].onclick = function() {
ocb = table.rows[this.i].cells[0].innerHTML;
area = table.rows[this.i].cells[1].innerHTML;
name = table.rows[this.i].cells[2].innerHTML;
cell = table.rows[this.i].cells[3].innerHTML;
nick = table.rows[this.i].cells[4].innerHTML;
alert('ocb: '+ocb+' area: '+area+' name: '+name+' cell: '+cell+' nick: '+nick);
};
}
}
}
var elements = document.getElementsByTagName('td');
for (var i =0; i < elements.length; i++) {
var cell_id = 'id' + i;
elements[i].setAttribute('id', cell_id);
}
Maybe put something like this in function your onclick links to from the tr?
$("tr").click(function () {
var rowItems = $(this).children('td').map(function () {
return this.innerHTML;
}).toArray();
});
This shows the row's first cell which is clicked according to dataTr.querySelectorAll("td")[0].innerText;
document.querySelector("#myTable").addEventListener("click",event => {
let dataTr = event.target.parentNode;
let dataRes = dataTr.querySelectorAll("td")[0].innerText;
console.log(dataRes);
});

Categories

Resources