Node JS how to wait Dom loaded then call function? - javascript

I'm using wkhtmltopdf to print my data and I load content from json file to html. I'm trying to do, loop through the array and pass data to variable and the table take data from variable to show and save pdf then clear variable write next item in array.
When I run js file, it generates pdf for each item but same loaded on html template and pdf.
Here is my loop the data and savePDF function.
let rawdata = fs.readFileSync('data.json');
let data = JSON.parse(rawdata);
async function pdfCreate() {
let parcaNo = data1.oemCode;
let uygunlukItems = data1.uygunluk;
var params = {
parcaNo: parcaNo,
uygunlukItem: uygunlukItems
};
console.log(parcaNo);
for (var i = 0, p = Promise.resolve(); i < data.length; i++) {
parcaNo = data[i].oemCode;
uygunlukItems = data[i].uygunluk
console.log(data[i].oemCode)
p.then(saveToPdf('catalog', path.resolve(__dirname, `./PDF/${parcaNo}.pdf`), params, () => {}));
parcaNo = "",
uygunlukItems = [];
}
}
await pdfCreate();
Here is my json example :
Here is my json example :
How can I create pdf for each element ?
Thanks for your help!

Related

Not able to add list items to HTML Document

I am using fetch() command to get an array of data in JSON format. I am using function fetchURL() to get data in JSON format. I use async-await. Then in each data received I am trying to add it's login field to an ordered list that I have created in the HTML file.
I have made a createListItem() function to find the ordered list tag in the HTML file and append in it the login field. But first I try to store all the login fields in an array arr. But I am not able to store the login fields in it.
But when I directly use createListItem() function to create a list item with login" field as text I am able to add these fields to the ordered list and hence I get the ordered list.
I am commenting out the lines that get me direct Output on the browser window when I do not store the login fields in the arr:
Code:
function createListItem(text) {
const parent = document.getElementsByTagName("ol");
const entry = document.createElement("li");
entry.textContent = text;
parent[0].appendChild(entry);
}
const url = "https://api.github.com/users ";
async function fetchURL() {
return (await fetch(url)).json();
}
let arr = [];
async function createList() {
const data = await fetchURL();
for (let i = 0; i < data.length; i++) {
//createListItem(`${data[i].login}`);
arr.push(data[i].login);
}
}
createList();
you are getting the data in array, you need to create list after you call createList() function:
createList().then(function(){
arr.forEach(element => {
createListItem(element);
});
});
you can also define arr in the createList function and return that then your code would be like this:
async function createList() {
let arr = [];
const data = await fetchURL();
for (let i = 0; i < data.length; i++) {
//createListItem(`${data[i].login}`);
arr.push(data[i].login);
}
return arr;
}
createList().then(arr=>{
arr.forEach(element => {
createListItem(element);
});
});
You can achieve your objective with just one async function:
const url="http://jsonplaceholder.typicode.com/users";
async function getList(u){
const arr=(await fetch(u).then(r=>r.json())).map(e=>e.username);
document.querySelector("ol").innerHTML=arr.map(u=>`<li>${u}</li>`).join("");
console.log(arr);
}
getList(url);
<h2>List of login names</h2>
<ol></ol>
<p>end of page</p>
In the above snippet I used the public resource provided by typicode.com and extracted the property of username instead of login.

I want to fire a JSON variable stored in a JS file into an HTML file and loop over the contents

I am stuck on a problem where I have some JSON data stored in a variable that is defined within a function. Thus to access the JSON data, I would first need to make the function call. My function is as follows:
viewDeposits: function() {
var deposits = [];
App.contracts.BOKCoin.deployed().then(function(instance) {
bokcoinInstance = instance;
return bokcoinInstance.depositCount();
}).then(async function(depositCount) {
var count = depositCount.toNumber();
console.log(count);
for(var i=1; i<=count; i++) {
var x = await bokcoinInstance.deposits(i);
deposits.push(x);
}
console.log(deposits);
//send deposits to an html as an id
$('#deposits').html(deposits);
return deposits;
});
}
Next, I want to call this function and store in a variable in a .HTML file and loop through its contents. I am being able to store the return object into a variable.
Any help would be greatly appreciated. Thanks!

Iterating over results of papa.parse object

I believe this may be an issue with async or promises, however, this concept has been a struggle for me to grasp. I have spent much time researching questions relating to papaparse and promises, but believe I am still not grasping some simple concept.
Overview
In the below code, a .csv file is gathered from the user, converted into an Object using PapaParse, then distance/duration values are added to the data from GoogleMaps Distance Matrix and finally, the intent is to return this data back to the user as a .csv containing this combined information.
In downloadCSV(), I am able to log the Object which results from getDistTime. However, I am unable to iterate over this object or send it to papa.unparse to convert to a .csv. Below the code, I have attached an image of the structure of arr within downloadCSV().
I have spent much time researching questions here, and on the papaparse repo. I would appreciate any help on how to best proceed.
Contents of arr:
Code
$("#submit").click(function(){
//REMOVE THIS LINE BEFORE LIVE OR VALIDATION WILL BE DUN GOOFED
event.preventDefault();
getData();
});
function getData(){
var csv = document.getElementById('exampleFormControlFile1').files[0];
// Parse CSV string
Papa.parse(csv, {
header: true,
complete: function(results) {
var final_rows = getDistTime(results)
downloadCSV(final_rows)
}
});
} // end getData
function downloadCSV(arr){
//console.log(arr) shows the results
// but trying to iterate over arr or unparsing shows undefined
console.log(arr)
csv = Papa.unparse(arr)
...more csv export code
}
function getDistTime(resources){
var rows = []
const promiseArr = [];
for (var i = 0; i < resources.data.length; i++) {
var origin1 = $("#citystate").val();;
var destinationA = resources.data[i]['DEMOBILIZATION CITY'] + ',' + resources.data[i]['DEMOBILIZATION STATE'];
promiseArr.push(googleRequest(origin1, destinationA));
}
Promise.all(promiseArr)
.then((resultsArr) => {
resultsArr.forEach((result, i) =>
pushToRows(resources.data[i], result, rows));
})
return rows
} // end getDistTime
function pushToRows(resources, dist_dur, rows){
resources["DISTANCE_MI"] = dist_dur[0];
resources["ACTUAL_DUR_HR"] = dist_dur[1];
resources["FINANCE_DUR_HR"] = (dist_dur[0] / 45.0).toFixed(2)
rows.push(resources)
} // end pushToRows
getDistTime is performing an async action and therefore rows is returning empty before the Promise.all has resolved as you wont have pushed any data to it until that promise resolves.
Looks like you'll need to await the result of getDistTime or change how get data works, not sure you're using async await so simplest way is to just return that Promise.all and then only download the csv once its returned and resolved in your complete callback.
for example you could do
function getData(){
var csv = document.getElementById('exampleFormControlFile1').files[0];
// Parse CSV string
Papa.parse(csv, {
header: true,
complete: function(results) {
getDistTime(results).then(finalRows => downloadCSV(finalRows));
}
});
} // end getData
function getDistTime(resources){
var rows = []
const promiseArr = [];
for (var i = 0; i < resources.data.length; i++) {
var origin1 = $("#citystate").val();;
var destinationA = resources.data[i]['DEMOBILIZATION CITY'] + ',' + resources.data[i]['DEMOBILIZATION STATE'];
promiseArr.push(googleRequest(origin1, destinationA));
}
return Promise.all(promiseArr)
.then((resultsArr) => {
resultsArr.forEach((result, i) =>
pushToRows(resources.data[i], result, rows)
);
return rows
})
} // end getDistTime

how to read/use imported table from API into javascript?

I am using an API from Caspio to import a Data Table that will be variable.
for that, I am doing the following
<script type="text/javascript" id='Test' src="https://c1afw487.caspio.com/dp/6e444000877ca58e63624b0b8c78/emb"></script>
and then to format it (send it to the bottom of my web page) I am doing this:
<div id='InfoTable' style='width: 40%; float: left;'>
<a id='TestTwo' href="https://c1afw487.caspio.com/dp/6e444000877ca58e63624b0b8c78">DataTable </a>
</div>
Now, I am trying to access the data from the table. For that I am trying something like this
var DataTest = document.getElementById('Test');
var DataTestTwo = document.getElementById('TestTwo');
console.log(JSON.stringify(DataTest));
console.log(JSON.stringify(DataTestTwo));
But the first test returns { } and the second one null (notice how I tried to give an ID to the imported table so I could access it but any of my attempts worked).
What is the proper way to access the Table?
I dont know anything about that specific API but quick google seems to suggest that they have a separate rest api for requesting JSON data. You should look into that.
Stringifying an html element does nothing usefull...its an html element not your request payload data.
You can go over the table itself and extract all the contents into a json.
Something like this.
https://jsfiddle.net/rainerpl/wvdoek03/14/
var getHeaders = (table) => {
const headerRow = table.tBodies[0].children[0];
const headers = [];
let i;
for (i = 0; i < headerRow.children.length; i++) {
headers.push(headerRow.children[i].innerText);
}
return headers;
}
var getData = (table) => {
const data = [];
let i;
for (i = 1; i < table.tBodies[0].children.length; i++) {
let newDataRow = [];
for (j = 0; j < table.tBodies[0].children[i].children.length; j++) {
newDataRow.push(table.tBodies[0].children[i].children[j].innerText);
}
data.push(newDataRow);
}
return data;
}
JsonTable = function() {
const table = document.getElementsByTagName('table')[0];
const headers = getHeaders(table);
const data = getData(table);
this.getRow = (rowNr) => {
const result = {};
headers.forEach((key, index) => {
result[key] = data[rowNr][index];
});
return result;
}
console.log('table', table, 'has data:', data, ' and headers ', headers);
}
const jsonTable = new JsonTable();
console.log('First row is', jsonTable.getRow(0));
console.log('Second row is', jsonTable.getRow(1));
You can view the console output on jsFiddle to see what it looks like.
( use inspect developer tool to see console output )

Return list of Objects with Node js

I recently started development of a Node js application and it uses Selenium in a controller to fetch list of items from a web page and I want to return the fetched list of items as a JSON response.
exports.read_all_products = function (req, res) {
var driver = new webdriver.Builder().forBrowser('phantomjs').build();
driver.get('https://www.test.com/products?PC=' +req.params.category);
driver.wait(until.elementLocated(By.className('product-slide-all')), 20000, 'Could not locate the element within the time specified');
driver.findElements(By.className("product-slide-all")).then(function (elements) {
var arr = [];
elements.forEach(function (element) {
element.getAttribute("innerHTML").then(function (html) {
const dom = new JSDOM(html);
var obj = new Object();
obj.product_name = dom.window.document.querySelector(".product-name").textContent;
obj.product_code = dom.window.document.querySelector(".product-code").textContent;
obj.price = dom.window.document.querySelector(".product-price").textContent;
arr.push(obj);
});
});
res.json(arr);
});
}
Issue is I am always getting an empty JSON response even though items were added to the array. I want to know the proper way of handling this scenario.
Thanks.
It looks like the issue is because Selenium is running an async process, thus the response immediately returns because there is nothing blocking it.
findElements returns a Promise which you need to return the response from.
Take a look at How do I return the response from an asynchronous call?
Finally I was able to get it work with the help of webdriver.promise.map.
Moved web driver HTML extraction to separate function.
var findItems = function (category) {
var driver = new webdriver.Builder().forBrowser('phantomjs').build();
var map = webdriver.promise.map;
driver.get('https://www.test.com?PC=' + category);
driver.wait(until.elementLocated(By.className('product-slide-all')), 30000, 'Could not locate the element within the time specified');
var elems = driver.findElements(By.className("product-slide-all"));
return map(elems, elem => elem.getAttribute("innerHTML")).then(titles => {
return titles;
});
}
then call it from response handling function like bellow,
exports.read_all_products = function (req, res) {
findItems(req.params.category).then(function (html) {
var value;
var arr = [];
Object.keys(html).forEach(function (key) {
value = html[key];
const dom = new JSDOM(value);
var obj = new Object();
obj.product_name = dom.window.document.querySelector(".product-name").textContent;
obj.product_code = dom.window.document.querySelector(".product-code").textContent;
obj.price = dom.window.document.querySelector(".product-price").textContent;
arr.push(obj);
});
res.json(arr);
})
};
it's described in this stack overflow answers.

Categories

Resources