const fetchData = async () => {
fetch('https://*******/*****search-value={value}')
.then(response => response.text())
.then(data => {
console.log(data);
})
.catch(err => console.error(err));
}
I succesfully got the data from the api (it returns full html), and I got this response:
<div class="col-md-12">
<p class="text-info strong">
Succes.
</p>
<table class="table">
<tr>
<td width="40%">Number:</td>
<td>900000000053901</td>
</tr>
<tr>
<td>ID</td>
<td></td>
</tr>
<tr>
<td>Name:</td>
<td>Grafit</td>
</tr>
<tr>
<td>Spiece:</td>
<td>kutya</td>
</tr>
<tr>
<td>Type:</td>
<td>Border collie</td>
</tr>
<tr>
<td>Gender:</td>
<td>hím</td>
</tr>
<tr>
<td>Last modified:</td>
<td></td>
</tr>
<tr>
<td>Dangerous:</td>
<td>
Nem
</td>
</tr>
<tr>
<td>Last vaccine:</td>
<td>Intervet Nobivac DHPPi+RL, 2018.02.17</td>
</tr>
<tr>
<td>isDead:</td>
<td>
Nem
</td>
</tr>
</table>
Now I want to see the data from class="text-info strong" if Succes or not.
If Succes I want to read the html table () and parse it to a json.
{
Number: 900000000053901,
ID:"",
Name:"Grafit",
...
}
How can I achieve this?
You could do it with something like this:
function tableToJson(table) {
const data = [];
for (let i = 1; i < table.rows.length; i++) {
const tableRow = table.rows[i];
const rowData = {};
rowData[tableRow.cells[0].textContent] =
tableRow.cells[1].textContent.replace(/\n\ +/gm, '');
data.push(rowData);
}
return data;
}
const dataHTML = document.createElement('div');
dataHTML.innerHTML = data;
const isSuccess =
dataHTML.querySelector('.text-info.strong').textContent === 'success';
if(!isSuccess) return false;
const table = dataHTML.getElementsByTagName('table')[0];
return tableToJson(table);
Related
I have a script that fetches the data from a link and then inserts that in tables and shows it to the user. the script worked fine. but then I decided to make the function more dynamic so I added 2 arguments name and Html div name where the data will display. it worked fine when I called the function the first time but it doesn't show any data on the second call. I'm using PHP for my projects and new to javascript. but I made a similar function in PHP but that works. any suggestions?
function getInfoByCountry(name, displayName) {
fetch("https://something.com/countries/" + name)
.then(res => res.json())
.then(data => {
output = `
<tr>
<td>Total Cases</td>
<td>${data.cases}</td>
</tr>
<tr>
<td>Today Cases</td>
<td>${data.todayCases}</td>
</tr>
<tr>
<td>Deaths</td>
<td>${data.deaths}</td>
</tr>
<tr>
<td>Recovered</td>
<td>${data.recovered}</td>
</tr>
<tr>
<td>Critical</td>
<td>${data.critical}</td>
</tr>
<tr>
<td>Active Cases</td>
<td>${data.active}</td>
</tr>
`;
document.getElementById(displayName).innerHTML = output;
});
}
getInfoByCountry("USA", "USAInfo");
getInfoByCountry("China", "ChinaInfo");
<div class="table-responsive">
<table class="table table-striped mb-0">
<tbody id="ChinaInfo">
</tbody>
</table>
</div>
Add return like this
function getInfoByCountry(name, displayName) {
var display = document.getElementById(displayName);
return fetch("https://smthing.com/countries/"+name)
.then(res => res.json())
.then(data => {
output = `
<tr>
<td>Total Cases</td>
<td>${data.cases}</td>
</tr>
<tr>
<td>Today Cases</td>
<td>${data.todayCases}</td>
</tr>
<tr>
<td>Deaths</td>
<td>${data.deaths}</td>
</tr>
<tr>
<td>Recovered</td>
<td>${data.recovered}</td>
</tr>
<tr>
<td>Critical</td>
<td>${data.critical}</td>
</tr>
<tr>
<td>Active Cases</td>
<td>${data.active}</td>
</tr>
`;
document.getElementById(displayName).innerHTML += output;
}
);
}
getInfoByCountry("USA", "display");
getInfoByCountry("China", "display");
you just need to add return statement for returning output.
here is fiddle you can check function.
function getInfoByCountry(name,displayName) {
debugger;
return fetch("https://jsonplaceholder.typicode.com/posts/"+name)
.then(res => res.json())
.then(data => {
output = `
<tr>
<td>Total Cases</td>
<td>${data.title}</td>
</tr>
<tr>
<td>Today Cases</td>
<td>${data.body}</td>
</tr>
`;
document.getElementById(displayName).innerHTML = output;
});
}
You are adding the result using displayName as id attribute, you should add another one for USAinfo as mentioned in the comments, or a better implementation would be to create the table dynamically and append the result to the container.
function getInfoByCountry(name, displayName) {
fetch("API_URL" + name)
.then(res => res.json())
.then(data => {
output = `
<table class="table table-striped mb-0">
<tbody>
<tr>
<td>Total Cases</td>
<td>${data.cases}</td>
</tr>
<tr>
<td>Today Cases</td>
<td>${data.todayCases}</td>
</tr>
<tr>
<td>Deaths</td>
<td>${data.deaths}</td>
</tr>
<tr>
<td>Recovered</td>
<td>${data.recovered}</td>
</tr>
<tr>
<td>Critical</td>
<td>${data.critical}</td>
</tr>
<tr>
<td>Active Cases</td>
<td>${data.active}</td>
</tr>
</tbody>
</table><hr />
`;
document.getElementById("container").innerHTML += output;
});
}
getInfoByCountry("USA", "USAInfo");
getInfoByCountry("China", "ChinaInfo");
table, td {
border: 1px solid;
}
<div id="container" class="table-responsive">
</div>
It's well known, that 'array of objects' format of data storage is well suitable for data persisting. I'd be extremely grateful if a JavaScript guru helps me with finding the answer to how do I read this HTML-table with vanilla JavaScript and transport data from it into the following array of objects.
I have produced tons of code, mostly comparing two arrays of objects. Unfortunately, I didn't come even closer to a solution.
The table to scrape data from:
<table>
<tbody>
<tr>
<td colspan="3">Canada</td>
</tr>
<tr>
<td>Toronto</td>
<td>Montreal</td>
<td>Vancouver</td>
</tr>
<tr>
<td colspan="3">USA</td>
</tr>
<tr>
<td>New York</td>
<td>Chicago</td>
<td>Boston</td>
</tr>
<tr>
<td>Washington</td>
<td>Detroit</td>
<td>Los Angeles</td>
</tr>
</tbody>
</table>
Expected outcome to be like so:
[
{"country":"Canada","city":"Toronto"},
{"country":"Canada","city":"Montreal"},
{"country":"Canada","city":"Vancouver"},
{"country":"USA","city":"New York"},
{"country":"USA","city":"Chicago"},
{"country":"USA","city":"Boston"},
{"country":"USA","city":"Washington"},
{"country":"USA","city":"Detroit"},
{"country":"USA","city":"Los Angeles"}
]
The code is valid, unlike the approach:
let theResult = [];
arrayOfCountriesAndCitiesObjects.forEach((item, iIndex) => {
arrayOfCitiesObjects.forEach((elem, eIndex) => {
if(item.city !== elem.city && item.iIndex < elem.eIndex) theResult.push(copy(elem, item));
});
});
function copy(firstObj) {
for (let i = 1; i < arguments.length; i++) {
let arg = arguments[i];
for (let key in arg) {
firstObj[key] = arg[key];
}
}
return firstObj;
}
You could store the value of colSpan === 3 as country and push all other values as city to the result set.
This works with plain Javascript without any libraries.
var result = [],
country = '';
document
.querySelectorAll('table td')
.forEach(td => {
if (td.colSpan === 3) {
country = td.innerHTML;
return;
}
result.push({ country, city: td.innerHTML.trim() });
});
console.log(result);
<table>
<tbody>
<tr>
<td colspan="3">Canada</td>
</tr>
<tr>
<td>Toronto</td>
<td>Montreal</td>
<td>Vancouver</td>
</tr>
<tr>
<td colspan="3">USA</td>
</tr>
<tr>
<td>New York</td>
<td>Chicago</td>
<td>Boston</td>
</tr>
<tr>
<td>Washington</td>
<td>Detroit</td>
<td>Los Angeles</td>
</tr>
</tbody>
</table>
You can use for to loop thru each tr. Find the td on each tr, If there is only 1, store the text on currentCountry variable. If more than one, push the object to the result variable.
var currentCountry = "";
var result = [];
var tr = document.querySelectorAll('table tr');
for (var i = 0; i < tr.length; i++) {
var td = tr[i].querySelectorAll('td');
if (td.length === 1) currentCountry = td[0].innerHTML;
else if (td.length > 1) {
for (var a = 0; a < td.length; a++) {
result.push({country: currentCountry,city: td[a].innerHTML});
}
}
}
console.log(result);
<table>
<tbody>
<tr>
<td colspan="3">Canada</td>
</tr>
<tr>
<td>Toronto</td>
<td>Montreal</td>
<td>Vancouver</td>
</tr>
<tr>
<td colspan="3">USA</td>
</tr>
<tr>
<td>New York</td>
<td>Chicago</td>
<td>Boston</td>
</tr>
<tr>
<td>Washington</td>
<td>Detroit</td>
<td>Los Angeles</td>
</tr>
</tbody>
</table>
var country = null, result = [];
var tds = Array.from(document.querySelectorAll("#myTable tbody tr td"));
for (var i = 0; i < tds.length; i++) {
let item = tds[i];
if (item.getAttribute("colspan") == "3") {
country = item.innerText;
continue;
}
result.push({ country: country, city: item.innerText });
}
console.log(result);
<table id="myTable">
<tbody>
<tr>
<td colspan="3">Canada</td>
</tr>
<tr>
<td>Toronto</td>
<td>Montreal</td>
<td>Vancouver</td>
</tr>
<tr>
<td colspan="3">USA</td>
</tr>
<tr>
<td>New York</td>
<td>Chicago</td>
<td>Boston</td>
</tr>
<tr>
<td>Washington</td>
<td>Detroit</td>
<td>Los Angeles</td>
</tr>
</tbody>
</table>
Using reduce
const items = document.querySelectorAll('table tbody td')
const results = [...items].reduce((allItems, item)=>{
if(item.getAttribute('colspan') === '3'){
allItems['country'] = item.textContent
return allItems
}
allItems.push({country: allItems['country'],city:item.textContent})
return allItems
},[])
You need to assign all <tr> which contain country names a special class. Then use querySelectorAll and use forEach loop.
const tr = document.querySelectorAll('tr');
const arr = []
let count = '';
tr.forEach(x => {
if(x.classList.contains('head')){
count = x.children[0].innerHTML
}
else{
let child = [...x.querySelectorAll('td')]
arr.push(...child.map(a => ({country:count,city:a.innerHTML})))
}
})
console.log(arr)
<table>
<tbody>
<tr class="head">
<td colspan="3">Canada</td>
</tr>
<tr>
<td>Toronto</td>
<td>Montreal</td>
<td>Vancouver</td>
</tr>
<tr class="head" >
<td colspan="3">USA</td>
</tr>
<tr>
<td>New York</td>
<td>Chicago</td>
<td>Boston</td>
</tr>
<tr>
<td>Washington</td>
<td>Detroit</td>
<td>Los Angeles</td>
</tr>
</tbody>
</table>
Not that elegant, but to me slightly more comprehensive (while being the fastest for larger input data samples) reduce() solution:
const result = [...document.getElementsByTagName('td')].reduce((res, item) => (item.getAttribute('colspan') == 3 ? res.country = item.textContent : res.obj = [...(res.obj || []), {country: res.country, city: item.textContent}], res), {}).obj;
console.log(result);
<table>
<tbody>
<tr>
<td colspan="3">Canada</td>
</tr>
<tr>
<td>Toronto</td>
<td>Montreal</td>
<td>Vancouver</td>
</tr>
<tr>
<td colspan="3">USA</td>
</tr>
<tr>
<td>New York</td>
<td>Chicago</td>
<td>Boston</td>
</tr>
<tr>
<td>Washington</td>
<td>Detroit</td>
<td>Los Angeles</td>
</tr>
</tbody>
</table>
I want to print an integer with a comma as a separator, for example 10,234,234
in the price column.
I have made the function, but I am a little confused how to make it in the table. Below is my code
<table class="table">
<tr>
<th> Item</th>
<th>Price</th>
</tr>
#foreach (SHOP.ViewModels.ItemViewModel item in Model.Itemss)
{
<tr>
<td> #Html.DisplayFor(modelitem => item.itemName) </td>
<td> #Html.DisplayFor(modelitem => item.itemPrice)</td>
</tr>
}
<tr>
<td></td>
<td> #Html.EditorFor(model => model.TotalPrice, new { htmlAttributes = new { #class = "form-control", #onchange = "validationCheck();", #readonly = "readonly" } }) </td>
</tr>
</table>
<script>
function numberSeparator(x) {
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
</script>
You need to get all second td elements in the table and then update the content using the code.
<table class="table" id="table">
<!-- set id to get table^^^^^^^^---->
<tr>
<th> Item</th>
<th>Price</th>
</tr>
#foreach (SHOP.ViewModels.ItemViewModel item in Model.Itemss)
{
<tr>
<td> #Html.DisplayFor(modelitem => item.itemName) </td>
<td> #Html.DisplayFor(modelitem => item.itemPrice)</td>
</tr>
}
</table>
<script>
function numberSeparator(x) {
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
// get all second tds
[...document.querySelectorAll('#table tr > td:nth-child(2)')].forEach(e => {
// get text content and update
e.textContent = numberSeparator(e.textContent.trim());
})
</script>
FYI : It's always better to do it from the backend side if possible. There may be some functions available in your backend framework/programming language.
UPDATE : In your updated code you are creating an input so get input element update it's value.
<table class="table">
<tr>
<th> Item</th>
<th>Price</th>
</tr>
#foreach (SHOP.ViewModels.ItemViewModel item in Model.Itemss)
{
<tr>
<td> #Html.DisplayFor(modelitem => item.itemName) </td>
<td> #Html.DisplayFor(modelitem => item.itemPrice)</td>
</tr>
}
<tr>
<td></td>
<td> #Html.EditorFor(model => model.TotalPrice, new { htmlAttributes = new { #class = "form-control", #onchange = "validationCheck();", #readonly = "readonly" } }) </td>
</tr>
</table>
<script>
function numberSeparator(x) {
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
// get all second tds
[...document.querySelectorAll('#table tr > td:nth-child(2) input')].forEach(e => {
// get text content and update
e.value = numberSeparator(e.value.trim());
})
</script>
You can use toLocaleString to display a number with comma separators
let num = 1000000
let display = num.toLocaleString('us-US')
console.log(display) // 1,000,000
I suspect your code could work like this
#foreach (SHOP.ViewModels.ItemViewModel item in Model.Itemss)
{
<tr>
<td> #Html.DisplayFor(modelitem => item.itemName) </td>
<td> #Html.DisplayFor(modelitem => item.itemPrice.toLocaleString('us-US'))</td>
</tr>
}
I have this table where I am using sumtr for the table footer, and displaying all the data within datatables.
I need to display all the values as currency however.
I cannot change the values post sumtr because it won't be able to calculate the strings.
the Code for the tables here:
<table id="invoice_table">
<thead>
<tr>
<th>Type</th>
<th>Qty</th>
<th>Value</th>
</tr>
</thead>
<tbody>
#foreach (var item1 in Model.Date1)
{
try
{
string par = item1.theMoney.Value.ToString().Replace("-", "");
<tr>
<td>Cash</td>
<td class="sum">#Html.DisplayFor(modelItem => item1.theCount)</td>
<td class="sum">#Html.DisplayFor(modelItem => par)</td>
</tr>
}
catch { }
}
#foreach (var item2 in Model.Date2)
{
try
{
string par = item2.theMoney.Value.ToString().Replace("-", "");
<tr>
<td>Cheque</td>
<td class="sum">#Html.DisplayFor(modelItem => item2.theCount)</td>
<td class="sum">#Html.DisplayFor(modelItem => par)</td>
</tr>
}
catch { }
}
#foreach (var item3 in Model.Date3)
{
try
{
string par = item3.theMoney.Value.ToString().Replace("-", "");
<tr>
<td>Online</td>
<td class="sum">#Html.DisplayFor(modelItem => item3.theCount)</td>
<td class="sum">#Html.DisplayFor(modelItem => par)</td>
</tr>
}
catch { }
}
#foreach (var item4 in Model.Date4)
{
try
{
string par = item4.theMoney.Value.ToString().Replace("-", "");
<tr>
<td>PAP</td>
<td class="sum">#Html.DisplayFor(modelItem => item4.theCount)</td>
<td class="sum">#Html.DisplayFor(modelItem => par)</td>
</tr>
}
catch { }
}
</tbody>
<tfoot>
<tr class="summary">
<td>Total:</td>
<td class="first">?</td>
<td class="second">?</td>
</tr>
</tfoot>
</table>
<script type="text/javascript">
jQuery(function ($) {
$('#invoice_table').sumtr();
$('#invoice_table .summary').sumtrRatio('.first', '.second');
$('#invoice_table').DataTable({
dom: 'Blfrtip',
buttons: [
'copyHtml5',
'csvHtml5',
]
});
});
</script>
What the table looks like:
Need it to be in proper currency format ("C"): $94,029
How I did it
$('#invoice_table').sumtr({
onComplete: function(e){
e.find('.summary').each(function(index) {
var second = $(this).find('.second').data('sumtr');
$(this).find('.second').html('$' + (second).toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, '$1,'));
});
}
});
I am having the table with following data in it
<table>
<tr>
<td> cat </td>
<td> dog </td>
</tr>
<tr>
<td> hen </td>
<td> cock </td>
</tr>
</table>
I would like to delete the row based on the particular data given in table.
But I don't have any idea on how to delete the rows based on the particular data
Try this:
var table = document.querySelector('table');
var filterInput = document.querySelector('#filter');
filterInput.onkeyup = function () {
var val = this.value;
var td = table.getElementsByTagName('td');
var rows = [];
[].slice.call(td).forEach(function (el, i) {
if (el.textContent === val) {
rows.push(el);
}
});
rows.forEach(function(el) {
el.parentNode.style.display = 'none';
});
};
<input type="text" id="filter" placeholder="Hide row containing...">
<table>
<tr>
<td>cat</td>
<td>dog</td>
</tr>
<tr>
<td>hen</td>
<td>cock</td>
</tr>
</table>
Find the required element and then use style property to hide it. In the example, I went onto hide the table data element corresponding to the data dog.
var tds = $("td");
for(var i =0 ; i< tds.length ; i++)
{
var tdval = tds[i].innerHTML;
if(tdval.trim()=="dog")
{
document.getElementsByTagName("td")[i].style.display = "none";
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<tr>
<td> cat </td>
<td> dog </td>
</tr>
<tr>
<td> hen </td>
<td> cock </td>
</tr>
</table>