Parse HTML payload to JSON - javascript

I am facing a problem with the following payload.
The payload I am receiving on my Node.js backend on API call is as follows.
{
"id": "1",
"content":{
"text": "
<body>
<div>
<table>
<thead>
<tr>
<th><strong>Header 1</strong></th>
<th><strong>Header 2</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td>question 1</td>
<td>answer 1</td>
</tr>
<tr>
<td>question 2</td>
<td>answer 2</td>
</tr>
<tr>
<td>question 3</td>
<td>answer 3</td>
</tr>
</tbody>
</table>
</div>
</body>
"
}
}
so here I am storing the response as following:
var response = data
i.e. data is the JSON response
And I am saving the HTML data as follows
var HTMLContentText = response.content.text
As a result I will get this:
<body>
<div>
<table>
<thead>
<tr>
<th><strong>Header 1</strong></th>
<th><strong>Header 2</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td>question 1</td>
<td>answer 1</td>
</tr>
<tr>
<td>question 2</td>
<td>answer 2</td>
</tr>
<tr>
<td>question 3</td>
<td>answer 3</td>
</tr>
</tbody>
</table>
</div>
</body>
Here I want to perform the following operations
parse the HTML text into an object
get the table from the response
i.e. select("table").first();
get the rows of the table
i.e. select("tr")
I am having the same code in JAVA.
Here it is just for reference. Here, I used Jsoup parser for doing all the operations. I want to perform all in Javascript now.
// HTML as text (from JSON)
String HtmlFormattedText = (String)((JSONObject)JsonObject.get("content")).get("text");
// parse the html text into an object
Document HtmlFormattedDocumentObject = Jsoup.parse(HtmlFormattedText);
// get the table from the response
Element allRowsFromTable = HtmlFormattedDocumentObject.select("table").first();
// get the rows of the table
return allRowsFromTable.select("tr");

I created a snippet for this. The return value of the function contains all tr elements of the table - you don't need to select the table first.
const response = {
"id": "1",
"content": {
"text": `
<body>
<div>
<table>
<thead>
<tr>
<th><strong>Header 1</strong></th>
<th><strong>Header 2</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td>question 1</td>
<td>answer 1</td>
</tr>
<tr>
<td>question 2</td>
<td>answer 2</td>
</tr>
<tr>
<td>question 3</td>
<td>answer 3</td>
</tr>
</tbody>
</table>
</div>
</body>
`
}
}
// logging the result of the function
console.log(parseTable(response.content.text))
function parseTable(string) {
// creating an HTML element
const el = document.createElement('html')
// adding the string to the HTML element
el.innerHTML = string
// selecting and returning all tr elements
return el.getElementsByTagName('tr')
}
Note: I changed the single quote to backtick in your data, as it allows multiline strings.

Related

Getting value from another column when clicking targeted column JQuery

When the user clicks on the 'Number' column I want to be able to get the 'Name' column value in the same row. So for example if I clicked on '999' I would want to be able to get David.
$('#table').on('click', 'td:nth-child(2)', function()
{
row = $(this).text();
alert(row);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table border id='table'>
<thead>
<td>Name</td>
<td>Number</td>
<td>Address</td>
</thead>
<tbody>
<tr>
<td>David</td>
<td>999</td>
<td>Street 1</td>
</tr>
<tr>
<td>Bob</td>
<td>555</td>
<td>Street 3</td>
</tr>
<tr>
<td>Jessica</td>
<td>068</td>
<td>Street 5</td>
</tr>
</tbody>
</table>
You can use $(this).closest('tr').find('td:first').text() to get the closest first td and its text.
If the wanted item is inside of the tr but you dont know the place or you want it dynamically, you can add a class or id to the name td and change the code to this $(this).closest('tr').find('#WantedRowId').text()
$('#table').on('click', 'td:nth-child(2)', function() {
alert($(this).closest('tr').find('td:first').text());
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table border id='table'>
<thead>
<td>Name</td>
<td>Number</td>
<td>Address</td>
</thead>
<tbody>
<tr>
<td>David</td>
<td>999</td>
<td>Street 1</td>
</tr>
<tr>
<td>Bob</td>
<td>555</td>
<td>Street 3</td>
</tr>
<tr>
<td>Jessica</td>
<td>068</td>
<td>Street 5</td>
</tr>
</tbody>
</table>
You can find below a more appropriate solution that dynamically checks what is the "Name" column index and retrieves accordingly.
As such, if you insert other columns, like ID and what not, it'll still work without updating this specific logic.
$('#table').on('click', 'td:nth-child(2)', function()
{
$td = $(this);
indexCol = $td.closest('table').find('td:contains(Name)').index()
alert( $td.closest('tr').find('td').eq(indexCol).text());
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table border id='table'>
<thead>
<td>Name</td>
<td>Number</td>
<td>Address</td>
</thead>
<tbody>
<tr>
<td>David</td>
<td>999</td>
<td>Street 1</td>
</tr>
<tr>
<td>Bob</td>
<td>555</td>
<td>Street 3</td>
</tr>
<tr>
<td>Jessica</td>
<td>068</td>
<td>Street 5</td>
</tr>
</tbody>
</table>

Datatables. Hide / Show multiple rows within loop

This questions targets to Datatables plug-in for JQuery.
I have HTML table with 3 languages en, ru, fr. For example if English language is chosen French and Russian entries should be hidden, if Russian language is chosen then French and English entries should be hidden and so on.
In the HTML table id looks like:
etc_1_en
etc_1_ru
etc_1_fr
etc_2_en
etc_2_ru
etc_2_fr
etc_3_en
etc_3_ru
etc_3_fr
...
But each entry have the same class: row
HTML table like this:
<table>
<thead>
<tr>
<th>Header content 1</th>
<th>Header content 2</th>
</tr>
</thead>
<tbody>
<tr id="etc_1_en" class="row">
<td>Etc 1</td>
<td>Etc 2</td>
</tr>
<tr id="etc_1_ru" class="row">
<td>Etc 3</td>
<td>Etc 4</td>
</tr>
<tr id="etc_1_fr" class="row">
<td>Etc 5</td>
<td>Etc 6</td>
</tr>
<tr id="etc_2_en" class="row">
<td>Foo 1</td>
<td>Foo 2</td>
</tr>
<tr id="etc_2_ru" class="row">
<td>Foo 3</td>
<td>Foo 4</td>
</tr>
<tr id="etc_2_fr" class="row">
<td>Foo 5</td>
<td>Foo 6</td>
</tr>
</tbody>
</table>
There are 3 buttons with ID like:
btn_id_en
btn_id_ru
btn_id_fr
But each button have the same class: btn
Here is JQuery code:
tbl = $('#myTable').DataTable();
var rows = tbl.rows().data();
// there looping through all entries
rows.each(function (row, index) {
var row = tbl.row(index);
var data = row.data();
var id = row.id();
// there trying to assign each row to child variable (using Datatable)
var child = row.child;
if (/* some conditions */) { // if / else conditions is working, tested with console.log();
// this part not working, something wrong with child maybe
child.show();
} else {
// this part not working, something wrong with child maybe
child.hide();
}
}
row.id() returning correct ID of each row (tested via console.log(id);). Problem is that hide not working. I'm thinking that something wrong with declaring child.
Maybe I have to use remove() instead of hide(), but in this case how could I restore it after another button will be clicked?
Have you any ideas?
If you're use case is simply to have buttons then this should work:
var lang = ""
$.fn.dataTable.ext.search.push(
function(settings, data, dataIndex) {
var thisId = Object.keys(settings.aIds)[dataIndex].split("_")[2]
return thisId === lang;
}
);
var table = $('#example').DataTable({
"language": {
"infoFiltered": ""
}
});
$(".filter").click(function(e) {
lang = $(e.target).attr("id").split("_")[2];
table.draw();
});
Working JSFiddle here: https://jsfiddle.net/annoyingmouse/opu869ko/
That was fun!
You need a custom filter:
$.fn.dataTable.ext.search.push(
function(settings, data, dataIndex) {
var langs = new Set();
$(".filter").each(function(k, v) {
if ($(v).is(':checked')) {
langs.add($(v).attr("id").split("_")[2]);
}
});
var thisId = Object.keys(settings.aIds)[dataIndex].split("_")[2]
return langs.has(thisId);
}
);
And I'm wary of using buttons as you'd probably need to show the hidden rows at some point so I've replaced them with checkboxes:
<label for="btn_id_en">
<input class="filter" id="btn_id_en" type="checkbox" checked="checked">
English
</label>
<label for="btn_id_ru">
<input class="filter" id="btn_id_ru" type="checkbox" checked="checked">
Russian
</label>
<label for="btn_id_fr">
<input class="filter" id="btn_id_fr" type="checkbox" checked="checked">
French
</label>
<hr>
<table id="example" class="display" cellspacing="0" width="100%">
<thead>
<tr>
<th>Header content 1</th>
<th>Header content 2</th>
</tr>
</thead>
<tbody>
<tr id="etc_1_en" class="row">
<td>Etc 1</td>
<td>Etc 2</td>
</tr>
<tr id="etc_1_ru" class="row">
<td>Etc 3</td>
<td>Etc 4</td>
</tr>
<tr id="etc_1_fr" class="row">
<td>Etc 5</td>
<td>Etc 6</td>
</tr>
<tr id="etc_2_en" class="row">
<td>Foo 1</td>
<td>Foo 2</td>
</tr>
<tr id="etc_2_ru" class="row">
<td>Foo 3</td>
<td>Foo 4</td>
</tr>
<tr id="etc_2_fr" class="row">
<td>Foo 5</td>
<td>Foo 6</td>
</tr>
</tbody>
</table>
Working JSFiddle here.
Hope that helps.
child is not a variable but a function. Replacing:
var child = row.child;
with
var child = row.child();
should fix it.
See here: https://datatables.net/reference/api/row().child().hide()

How to copy specific content from one table to another using Javascript

I am currently developing a tool to display large amount of data in different tables. Different amount of data from one table has to be assigned into another table more than once. This view takes almost 20 seconds to load and i want to lower the time by manipulating the DOM instead of assigning every match within PHP. I want to place a few identifiers hidden in the first table and on click of one row, show the additional data within the next element.
Here is an example how the Tables look before:
<table>
<tr>
<th>Name</th>
</tr>
<tr class="iWantToClickThis">
<td>Bla Bla</td>
<td style="visibility:hidden;">3,5</td>
</tr>
</table>
<table style="visibility:hidden">
<tr>
<th>Additional Header</th>
</tr>
<tr id="1">
<td>Additional Info 1</td>
</tr>
<tr id="2">
<td>Additional Info 2</td>
</tr>
<tr id="3=>
<td>Additional Info 3</td>
</tr>
<tr id="4">
<td>Additional Info 4</td>
</tr>
<tr id="5">
<td>Additional Info 5</td>
</tr>
<tr id="6">
<td>Additional Info 6</td>
</tr>
</table>
And after the click:
<table>
<tr>
<th>Name</th>
</tr>
<tr class="iWantToClickThis">
<td>Bla Bla</td>
<td style="visibility:hidden;">3,4,5</td>
</tr>
<tr>
<td colspan="2>
<table>
<tr>
<th>Additional Header</th>
</tr>
<tr id="3">
<td>Additional Info 3</td>
</tr>
<tr id="5">
<td>Additional Info 5</td>
</tr>
</table>
</td>
</table>
I've found out how to achieve this with a single row but how do i do that with different, identitying them by their ids?

Break a HTML Table to two tables dynamically in javascript

I am using an user control in asp.net in which I am creating a html table from code behind. Initial structure is given below.
<table>
<tr>
<td>Property1</td>
<td>Property2</td>
<td>Property3</td>
<td>Property4</td>
</tr>
<tr>
<td>Value1</td>
<td>Value2</td>
<td>Value3</td>
<td>Value4</td>
</tr>
</table>
My problem is I want to restructure it according to the size of container it is going to be placed [as it is a user control]. For Ex If width of each cell is 20px and container width is 40px then structure will be as given below;
<table>
<tr>
<td>Property1</td>
<td>Property2</td>
</tr>
<tr>
<td>Value1</td>
<td>Value2</td>
</tr>
</table>
<table>
<tr>
<td>Property3</td>
<td>Property4</td>
</tr>
<tr>
<td>Value3</td>
<td>Value4</td>
</tr>
</table>
Thanks for the suggestion #user2167382.
Finally I have solved it though I had to use jquery.
Below is my html.
<table id="sourceT">
<tr>
<td>Col 1</td>
<td>Col 2</td>
<td>Col 3</td>
</tr>
<tr>
<td>Col 1 - value</td>
<td>Col 2 - value</td>
<td>Col 3 - value</td>
</tr>
</table>
<table id="targetT">
</table>
Here is the jquery logic.
var $target = $("#targetT");
$("#sourceT tr").each(function() {
var $tds = $(this).children(),
$row = $("<tr></tr>");
var i=1;
while(i<3)
{
alert(i) ; $row.append($tds.eq(i).clone()).appendTo($target);
i++;
}
});
Hope it will help somebody else.

How to append a table row towards last of a row with a specific class?

I'm trying to append a row to the html format of an asp data grid. My grid is having paging and that too is converted as a row in the html format. So, I added a class to the rows with the actual records. Now, i need to append an html table row to the grid. This should be appended towards the end of the records. Somebody knows how to do this?
Table Structure:
<table>
<th>
</th>
<tbody>
<tr class="clientData">1</tr>
<tr class="clientData">2</tr>
<tr class="clientData">3</tr>
<tr>Exclude This Row</tr>
<tr>Exclude This Row</tr>
</tbody>
</table>
Script:
{ $("#ctl00_Content_GrdCustomer tbody").append(selCustomersRow); } //
Something like
$('#ctl00_Content_GrdCustomer tbody tr.clientData').last().after(selCustomersRow);
Or like Angel's comment, select directly the last tr.clientData :
$('#ctl00_Content_GrdCustomer tbody tr.clientData:last').after(selCustomersRow);
http://api.jquery.com/after/
A better way would be to use the correct table tags.
i.e.
<table>
<thead>
<tr>
<td>Column header 1</td>
<td>Column header 2</td>
<td>Column header 3</td>
</tr>
</thead>
<tbody>
<tr>
<td>Column 1</td>
<td>Column 2</td>
<td>Column 3</td>
</tr>
<tr>
<td>Column 1</td>
<td>Column 2</td>
<td>Column 3</td>
</tr>
</tbody>
<tfoot>
<tr>
<td>Column footer 1</td>
<td>Column footer 2</td>
<td>Column footer 3</td>
</tr>
</tfoot>
</table>
You may not need to have a header, but you can stick all of your "records" within the tbody and your pagination within the tfoot.
This way you can use
$("#ctl00_Content_GrdCustomer tbody").append(selCustomersRow);
Which will append the row to the end tbody, but before the pagination within the tfoot.
Try that ...
{ $("#ctl00_Content_GrdCustomer tbody tr").last().append(selCustomersRow); }

Categories