Create Javascript object from HMTL table - javascript

I have a table like
<table id="misc_inputs">
<thead>
<tr><th>Property</th><th>Input</th></tr>
</thead>
<tbody>
<tr>
<td>a</td>
<td><input type="number" value="1"></td>
</tr>
<tr>
<td>b</td>
<td><input type="number" value="2"></td>
</tr>
...
I would like to convert that table to a Javascript object like
misc_inputs = {"a": 1, "b": 2, ...
How can the result be generated?

You can use below re-usable javascript method to convert any HTML table into Javascript object.
<table id="MyTable">
<thead>
<tr><th>Property</th><th>Input</th></tr>
</thead>
<tbody>
<tr>
<td>a</td>
<td><input type="number" value="1"></td>
</tr>
<tr>
<td>b</td>
<td><input type="number" value="2"></td>
</tr>
</tbody>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
$(document).ready(function () {
function ConvertHTMLToJSObject(htmlTableId)
{
var objArr = {};
var trList = $('#' + htmlTableId).find('tr');
$('#' + htmlTableId).find('tbody tr').each(function ()
{
var row = $(this);
var key = $(row).first().text().trim();
var value = $(row).find('input').attr("value");
objArr[key] = value;
});
return objArr;
}
var obj = ConvertHTMLToJSObject("MyTable");
console.log(obj);
});

You can loop through each inputs and create the object:
var misc_inputs = {};
$("#misc_inputs input[type=number]").each(function(i, el){
var k = $(this).closest('td').prev().text();
return misc_inputs[k] = +el.value;
});
console.log(misc_inputs);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="misc_inputs">
<thead>
<tr><th>Property</th><th>Input</th></tr>
</thead>
<tbody>
<tr>
<td>a</td>
<td><input type="number" value="1"></td>
</tr>
<tr>
<td>b</td>
<td><input type="number" value="2"></td>
</tr>
</tbody>
</table>

Probably you can do it without any library but with jQuery it's easier. Something like that should work (not tested):
// Here we will store the results
var result = {};
// Ask jQuery to find each row (TR tag) and call a function for each
$('tr').each(function(){
// Inside a jQuery each() "this" is the current element, the TR tag in this example
var row = $(this);
// We ask jQuery to find every TD inside the current row (the second parameter of a jQuery selector is the parent node for your search). We take the first one and then we take the content of the tag
var label = $("td", row).first().text();
// We ask for an "input" tag inside the current row and we read its "value" attribute
var value = $("input", row).attr("value");
// Store everything in result
result[label] = value;
});

Related

make each table value display in each textbox

I have this html table and 2 textboxes:
<table id="myTbl">
<thead>
<tr>
<th>A</th>
<th>B</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>2</td>
</tr>
</tbody>
</table>
<input type="text" name="txt" id="txt" >
<input type="text" name="txt" id="txt2" >
I want when reload the page, the values 1 and 2 must display in each textbox. How can I do it?
I have tried this js code but wrong and I want it auto display, not to click it:
var cells = document.querySelectorAll('#myTbl tbody ');
Array.from(cells).forEach(function (elem) {
elem.addEventListener('click', function () {
document.getElementById('txt').value = this.textContent;
})
})
var tbody = document.getElementsByTagName('tbody')[0]
var input1 = document.getElementById('txt')
var input2 = document.getElementById('txt2')
input1.value = tbody.getElementsByTagName('td')[0].textContent
input2.value = tbody.getElementsByTagName('td')[1].textContent

Reverse table rows top row go on bottom without change the position of th, HOW?

I use the HTML code.
I have a table and I write in first tr td "A" and "B" in second tr td
I have these two rows
but I want to print "B" in first tr and "A" in second
!! But I don't want to change my th position!!
Is it possible with any script like js or Jquery or with any type js CDN....??
<table id='table1'>
<tr>
<th>name</th>
</tr>
<tr>
<td>A</td>
</tr>
<tr>
<td>B</td>
</tr>
</table>
Give this a try:
Your script
$(function(){
$("tbody").each(function(elem,index){
var arr = $.makeArray($("tr",this).detach());
arr.reverse();
$(this).append(arr);
});
});
The second way to do the same will be like this:
var tbody = $('table tbody');
tbody.html($('tr',tbody).get().reverse());
I hope this helps! Thanks!
You can swap the .textContent of the <td> children of the <tr> elements
const {rows:[{cells:[a]}, {cells:[b]}]} = table1;
[a.textContent, b.textContent] = [b.textContent, a.textContent];
<table id='table1'>
<tr>
<td>A</td>
</tr>
<tr>
<td>B</td>
</tr>
</table>
Since you can use reverse() with an array, you can use get() to convert this to an array first. If you have a dynamic number of rows you can use something like this:
$('tbody').each(function(){
var row = $(this).children('tr');
console.log(row)
$(this).html(row.get().reverse())
})
Use this below code:
$(function(){
$("tbody").each(function(elem,index){
var arr = $.makeArray($("tr",this).detach());
arr.reverse();
$(this).append(arr);
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id='table1'>
<tbody>
<tr>
<td>A</td>
</tr>
<tr>
<td>B</td>
</tr>
<tr>
<td>C</td>
</tr>
</tbody>
</table>
You can loop through each row, starting at the bottom and add it to the bottom - this will reverse the rows.
This will mean you don't need to load all the rows into an array, but will mean additional DOM manipulation.
var tbl = $("#table1>tbody")
var l = tbl.find("tr").length;
for (var i=l; i>=0; --i)
{
tbl.find("tr").eq(i).appendTo(tbl);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id='table1'><tbody>
<tr> <td>A</td> </tr>
<tr> <td>B</td> </tr>
<tr> <td>C</td> </tr>
<tr> <td>D</td> </tr>
<tr> <td>E</td> </tr>
</tbody></table>
Problem Solved
<script type="text/javascript">
var trCount = $('#table1 tr').length;
var $rows = [];
for (var i = 0; i < trCount; i++)
$rows.push($('#table1 tr:last-child').remove());
$("#table1 tbody").append($rows);
</script>
Thanks to all
You can do that with pure vanilla JS, you don't need jquery or any other library for that.
function reverseOrder(table) {
const rows = table.querySelector('tbody').children;
const swaptemp = rows[0].children[0].innerHTML;
rows[0].children[0].innerHTML = rows[1].children[0].innerHTML;
rows[1].children[0].innerHTML = swaptemp;
}
const tableToReserveOrder = document.getElementById('table1');
reverseOrder(tableToReserveOrder);
<table id='table1'>
<tr>
<td>A</td>
</tr>
<tr>
<td>B</td>
</tr>
</table>
This is just a demonstration for your use case, you can play around with value of n which is 0 for this case where n+1 is 1.

How to change the node when blur event occur?

Source HTML structure.
<table>
<tr>
<td>class</td>
<td><input type="text" id="data1"></td>
</tr>
<tr>
<td>name</td>
<td><input type="text" id="data2"></td>
</tr>
</table>
Event: The Source HTML struture turns into the Target HTML struture after typing test1 in input whose id is data1 and mouse focus go out of the input.
Target HTML structure.
<table>
<tr>
<td>class</td>
<td>test1</td>
</tr>
<tr>
<td>name</td>
<td><input type="text" id="data2"></td>
</tr>
</table>
Here is my JS.
function changeNode(event){
ob =document.activeElement;
_str = ob.value;
ob.parentNode.removeChild(ob);
ob.parentNode.innerText = _str;
}
document.addEventListener("blur",changeNode,true);
Why my JS can't achieve my expected target?
How to fix it?
You are selecting the active element while the event is that an object's focus is lost.
You should select event.target as ob and your code should work:
Also: you don't need to delete the object, your overriding all inner text so the object is automatically deleted.
function changeNode(event){
ob = event.target;
_str = ob.value;
ob.parentNode.innerText = _str;
}
document.addEventListener("blur",changeNode,true);
<table>
<tr>
<td>class</td>
<td><input type="text" id="data1"></td>
</tr>
<tr>
<td>name</td>
<td><input type="text" id="data2"></td>
</tr>
</table>
Several problems in your code:
You need to add the event listener to the input itself, not the document object. You can then simply use event.target instead of activeElement (input is no longer active after the blur event…)
You're trying to access ob.parentNode after removing ob. Try storing it in a variable first:
function changeNode(event) {
var ob = event.target;
var cell = ob.parentNode;
var _str = ob.value;
cell.removeChild(ob);
cell.innerText = _str;
}
document.querySelectorAll("input").forEach(function(input) {
input.addEventListener("blur", changeNode);
});
<table>
<tr>
<td>class</td>
<td><input type="text" id="data1"></td>
</tr>
<tr>
<td>name</td>
<td><input type="text" id="data2"></td>
</tr>
</table>
Note: querySelectorAll(…).forEach
might not be reliable in some old browsers, if you need to support them, see css-tricks.com: Loop Over querySelectorAll Matches
function changeNode(event){
var ob=event.target;
ob.parentNode.append(ob.value);
ob.parentNode.removeChild(ob);
}
document.getElementById("data1").addEventListener("blur",changeNode,true);
<table>
<tr>
<td>class</td>
<td><input type="text" id="data1"></td>
</tr>
<tr>
<td>name</td>
<td><input type="text" id="data2"></td>
</tr>
</table>
function changeNode(event) {
var ob = event.target;
var cell = ob.parentNode;
var _str = ob.value;
cell.removeChild(ob);
cell.innerText = _str;
}
document.addEventListener("blur",changeNode,true);

Get clicked column index from row click

I have a row click event. Recently had to add a checkbox to each row. How can I identify the clicked cell on row click event?
Or prevent row click when clicked on the checkbox.
Attempts: this.parentNode.cellIndex is undefined on the row click event.
function pop(row){
alert(row.cells[1].innerText);
}
<table style="width:100%">
<tr>
<th>Select</th>
<th>Site</th>
</tr>
<tr onclick="pop(this);">
<td><input type="checkbox" id="123456" /></td>
<td>Lonodn</td>
</tr>
</table>
Do you want something like this? You can just check the type attribute of the source element of the event and validate whether to allow it or not, you can stop the event using e.stopPropagation();return;.
function pop(e, row) {
console.log(e.srcElement.type);
if(e.srcElement.type === 'checkbox'){
e.stopPropagation();
return;
}else{
console.log(row);
alert(row.cells[1].innerText);
}
}
<table style="width:100%">
<tr>
<th>Select</th>
<th>Site</th>
</tr>
<tr onclick="pop(event, this);">
<td><input type="checkbox" id="123456" /></td>
<td>Lonodn</td>
</tr>
</table>
You should pass in the event details to your function and check the target property:
function pop(e){
// If the target is not a checkbox...
if(!e.target.matches("input[type='checkbox']")) {
alert(e.target.cellIndex);
}
}
<table style="width:100%">
<tr>
<th>Select</th>
<th>Site</th>
</tr>
<tr onclick="pop(event)">
<td><input type="checkbox" id="123456" /></td>
<td>Lonodn</td>
</tr>
</table>
Note: If you have nested elements inside the <td>, you might want to check e.target.closest("td") instead.
Note 2: You might need a polyfill for the matches method depending on which browsers you're supporting.
Here is an example if you don't want to attach a listener on every row :
document.getElementById("majorCities").addEventListener("click", function(e){
if(e.target.type === 'checkbox'){
var checked = e.target.checked;
var tr = e.target.parentElement.parentElement;
var city = tr.cells[1].innerHTML;
console.log(city+":checked="+checked);
}
});
<table id="majorCities" style="width:100%">
<tr>
<th>Select</th>
<th>Site</th>
</tr>
<tr>
<td><input type="checkbox"/></td>
<td>London</td>
</tr>
<tr>
<td><input type="checkbox"/></td>
<td>Paris</td>
</tr>
<tr>
<td><input type="checkbox"/></td>
<td>New-York</td>
</tr>
</table>
window.pop = function(row){
console.log('here');
var parent = row.parentNode;
Array.from(row.parentNode.querySelectorAll('tr')).forEach(function(tr, index){
if (tr === row) {
alert(index)
}
})
}
https://jsfiddle.net/sz42oyvm/
Here is for the pleasure, another example with an object containing the cities' names and a method to draw the table with ids corresponding to the name of the clicked city, so getting the clicked name is easier.
(function () {
var mySpace = window || {};
mySpace.cities = {};
mySpace.cities.pointer = document.getElementById("majorCities");
mySpace.cities.names = ["Select","City"];
mySpace.cities.data = [{"name":"Paris"},{"name":"New Delhi"},{"name":"Washington"},{"name":"Bangkok"},{"name":"Sydney"}];
mySpace.cities.draw = function(){
this.pointer.innerHTML="";
var html = "";
html+="<tr>"
for(var i=0;i < this.names.length;i++){
html+="<th>"+this.names[i];
html+="</th>"
}
html+="</tr>"
for(var i=0;i < this.data.length;i++){
html+="<tr>"
html+="<td><input id='"+this.data[i].name+"' type='checkbox'/></td>"
html+="<td>"+this.data[i].name+"</td>"
html+="</tr>"
}
this.pointer.innerHTML=html;
}
mySpace.cities.draw();
mySpace.cities.pointer.addEventListener("click", function(e){
if(e.target.type === 'checkbox'){
var checked = e.target.checked;
var city = e.target.id;
console.log(city+":checked="+checked);
}
});
})();
table {width:25%;background:#ccc;border:1px solid black;text-align:left;}
td,tr {background:white;}
th:first-of-type{width:20%;}
<table id="majorCities">
</table>

Converting user input from html table to JSON with jQuery

I am able to convert a pre populated table with data to JSON object with jQuery. Here is the code:
var header = $('table thead tr th').map(function () {
return $(this).text();
});
var tableObj = $('table tbody tr').map(function (i) {
var row = {};
$(this).find('td').each(function (i) {
var rowName = header[i];
row[rowName] = $(this).text();
});
return row;
}).get();
JSON.stringify(tableObj);
And the html table is like this:
<table>
<thead>
<tr>
<th>Name</th>
<th>E-mail</th>
<th>Job</th>
</tr>
</thead>
<tbody>
<tr>
<td>jason</td>
<td>jason#example.com</td>
<td>Developer</td>
</tr>
<tr>
<td>ted</td>
<td>ted#example.com</td>
<td>Bear</td>
</tr>
</tbody>
</table>
Now my task is to actually handle empty table with user inputs. When user load the page, the table is empty with no value, after the user entered the input and click submit, I want to convert the user input data into JSON object and pass it back to back-end.
I am trying to make it happen by warp the table into a form, and add <input> tag in each <td>, something like this:
<form>
<table>
<tbody>
<tr>
<td><input type="text"/></td>
<td><input type="text"/></td>
<td><input type="text"/></td>
</tr>
<tr>
<td><input type="text"/></td>
<td><input type="text"/></td>
<td><input type="text"/></td>
</tr>
</tbody>
</table>
<button type="submit">Submit</button>
</form>
I try to use the .submit() method from jQuery to make it work but I am getting syntax errors:
$('form').submit(
var header = $('table thead tr th').map(function () {
return $(this).text();
});
var tableObj = $('table tbody tr').map(function (i) {
var row = {};
$(this).find('td').each(function (i) {
var rowName = header[i];
row[rowName] = $(this).text();
});
return row;
}).get();
JSON.stringify(tableObj);
);
How should I change my code to make it work?
That's happening bacause there is no text in the td. You need to find the value of the input.
1) You need to get the input in the td
2) You need to get the value of the input
Also try to look at the editable div
Try this:
row[rowName] = $(this).find('input').val();

Categories

Resources