Convert html page (with jquery ajax calls) to pdf - html

I am trying to save html page to pdf using evopdf htmlToPdfConverter. The html page is using jquery ajax to get the data from web api. Any static html content in the html page is printed in the pdf but the tables showing the data from the api are not getting populated.
The url in the code below opens correctly and loads the data from api when opened in browser.
Here is the code in the Console Application that I created that references the URL and should save the html page as pdf.
//console application
HtmlToPdfConverter htmlToPdfConverter = new HtmlToPdfConverter(); // cP7t/+rv/+zo6Oj/5/Hv/+zu8e7t8ebm5ub/7w== // HpCAkYKCkYKDiZGIn4GRgoCfgIOfiIiIiJGB
htmlToPdfConverter.LicenseKey = "HpCxxxxxxxxxxxxxxxxxxx";
htmlToPdfConverter.MediaType = "print";
htmlToPdfConverter.HtmlViewerWidth = 1024;
htmlToPdfConverter.PdfDocumentOptions.SinglePage = true; // SinglePagePdf.Checked;
htmlToPdfConverter.PdfDocumentOptions.PdfPageOrientation = PdfPageOrientation.Landscape;
htmlToPdfConverter.JavaScriptEnabled = true;
htmlToPdfConverter.ConversionDelay = 15;
string url = "https://localhost:44354/trm/test.html?pid=231";
string fileName = #"C:\QSaves\test.pdf";
htmlToPdfConverter.ConvertUrlToFile(url, fileName);
/////////////////////////////////////////
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script>
$(document).ready(function () {
function main() {
$.ajax({
url: 'api/csheet/?ID=' + 10,
type: 'get',
dataType: 'json',
success: function (data) {
$('#CTable').removeClass('w3-hide');
var tbl = $("#CompanyTable").dataTable({
destroy: true,
searching: false,
fixedHeader: {
header: true,
footer: true
},
data: data.Items,
sScrollX: true,
scrollH: true,
sScrollXInner: '100%',
processing: true,
bPaginate: false,
dom: 'Bfrtip',
columns: [
{
'data': 'Name',
},
]
});
}
});
}
main();
});
</script>

Your code shows the hint why it's not printing the table data.
You have document ready function which will init as soon its ready and then inside this function the Ajax will call API to load the data and populate it inside the table. Please modify the Ajax request to call in sync mode. By default Ajax requests are async that means it will call the API and will execute the further code before populating the table data.
Refer this doc for more better understanding about ajax request calls:
AJAX Request Calls
Do modify your ajax request to sync mode and then at finally call function to create the PDF.
Right now its working as below:
Page load
Document Ready Function get called
Ajax calls the API in async mode and executes further code which executes the PDF creation code before Ajax request populates the table with data, and thus you are getting PDF with empty table data.
How to get it correct:
Page load
Document ready function get called
Ajax calls the API in sync mode and executes it.
Add PDF generation code after the AJAX calls finish its data population to table.

Related

Google maps JSON markers load asynchronously?

I found some code to load Google Map marker data from a JSON file here: http://snippetrepo.com/snippets/multiple-markers-using-json-with-google-maps-api
It's working great, but I am getting a warning in the developer console:
Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check http://xhr.spec.whatwg.org/.
I did some research on this issue and it appears that the problem is that this code has 'async': false. I tried to just change that value to true but then I was getting another error with my function that displays the closest results to the user, because the marker array was empty when that function fired.
Is it possible to make this work asynchronously? Is there anything wrong with disabling async?
var json = (function () {
var json = null;
$.ajax({
'async': false,
'global': false,
'url': "js/hotels.json",
'dataType': "json",
'success': function (data) {
json = data;
}
});
return json;
})();

How to get HTML content inside an iFrame to an Action and save it in DB?

I'm having a school timetable manually created. The number of textboxes are 33. I want to store it in db. But what if I store its innerHtml content in Db? Since the students can also view the timetable, but fetching that much data may decrease performance.
I'm trying to get the data using Ajax, but nothing happens. Not even an error.
I'm working on Java with Struts Framework and the fields are inside an iFrame element.
I don't know what to write in execute method to get the html content.
Ajax Code :
<script type="text/javascript">
var jarray=[];
var jsonTT={};
var jsonTTData="";
function GenerateTableJson(){
jsonTTData="";
jsonTTData=$("#bdyTimeTableData").html();
jsonTT["timeTable"]=escape(jsonTTData.trim());
$("#contentTT").val(jsonTT);
console.log(jsonTT);
var postdata ={};
postdata = {
"FinalSave":[{
"timeTable":"TT",
"department":$("#departmentid").val(),
"semester":$("#semesterid").val(),
"division":$("#divisionid").val()
}]
};
postdata = JSON.stringify(postdata);
$.ajax({
url: "SaveNPrintTT.action",
cache:false,
contentType : 'application/json',
type : 'POST',
async : true,
data:postdata,
success:function(res){
$.ajax({
url: url,
cache:false,
method:"POST",
dataType : 'json',
success:function(res){
}
});
}
});
return true;
}
function PrintPreview() {
var toPrint = document.getElementById('bdyTimeTableData');
var popupWin = window.open('TimeTable', '_blank', 'resizable=yes,scrollbars=yes,status=yes');
popupWin.document.open();
popupWin.document.write('<html><title>::Print Preview::</title><link rel="stylesheet" type="text/css" href="Print.css" media="screen"/></head><body onload="window.print()""">')
popupWin.document.write(toPrint.innerHTML);
popupWin.document.write('</html>');
popupWin.document.close();
window.PrintPreview =PrintPreview;
}
</script>
My JSP code.
Only Textboxes with values.
But for save button, I'm calling Action Class name - saveTT
I need the content in Action to save it in Db. OR Do i write an insert query, inserting 33 values in db?

Submit form without opening browser in Windows 8

I'm building an app using Microsoft's new HTMl5 framework for Metro apps. I've created a form that I use to submit GET data. The problem is, clicking the "Run Query" (Submit) button on the app opens a browser window. What are some ways that I can submit the data in the GET method without opening a browser window.
I've tried using jQuery to do so but with little yield. It throws the message "jQuery" is not defined.
Is there any HTML I can use, or, better yet, something I can add into default.js?
As requested, jQuery I'm using:
jQuery(document).ready(function () {
jQuery('.ajaxform').submit(function () {
$.ajax({
url: $(this).attr('action'),
type: $(this).attr('method'),
dataType: 'json',
data: $(this).serialize(),
success: function (data) {
for (var id in data) {
jQuery('#' + id).html(data[id]);
}
}
});
return false;
});
});
Get the values from your form, save it in an object, encode it using javascript function and use xhr,
Get form values using js, say
var b=document.getElementById(textboxname).value;
var params={
parameter:b,
}
In order to encode your parameters you can use the following javascript function,
function formatParams(y) {
var queryStr = "";
for (var propertyName in y) {
var val = y[propertyName];
queryStr += propertyName + "=" + encodeURI(val) + "&";
}
return queryStr.slice(0, -1);
}
Call your web service using WinJS.xhr
WinJS.xhr({
type: "get/post",
url: "your URL",
data: formatParams(params),
headers: { "Content-type": "application/x-www-form-urlencoded" }
}).done(function (response) {
var json = JSON.parse(response.responseText);
//process accordingly
}
Im assuming you are getting JSON response from your web service.
I'm guessing here you are referring to an external script for jQuery.
Since winjs is running under different security restrictions than a typical web app in a browser your scripts must be local.
Since you are already using jquery - assuming version 2.0 or greater which is Win8/winjs compatible - make sure you have included a reference to jquery LOCALLY in your project and NOT from an external website, you can just use $(document) instead of jQuery(document).
ie:
<script src="/scripts/jquery-2.0.0.js" /> (or whatever your version is)
and make sure you have the files locally. You can just go in Visual Studio to Tools->Library Package Manager->Package Manager Console and type in
install-package jquery

viewbag data is empty in $.ajax

Iam using asp.net mvc4 and facing some problem in accessing viewbag.price.
This is what i am doing:-
[HttpPost]
public ActionResult FillModel(int id)
{
var vehModel = db.Vehicle_Model.Where(vehMod => vehMod.MakeID == id).ToList().Select(vehMod => new SelectListItem() { Text = vehMod.Model, Value = vehMod.pkfModelID.ToString() });
ViewBag.Price = 100;
return Json(vehModel, JsonRequestBehavior.AllowGet);
}
i am calling above using below:-
$.ajax({
url: '#Url.Action("FillModel","Waranty")',
type: 'post',
data: { id: id },
dataType: 'json',
success: function (data) {
$('#ddModel').empty();
$.each(data, function (index, val) {
var optionTag = $('<option></option>');
$(optionTag).val(val.Value).text(val.Text);
$('#ddModel').append(optionTag);
});
var a = '#ViewBag.Price';
},
error: function () {
alert('Error');
}
});
But i am not able to access ViewBag.Price.
Anyone know the reason??
thanks
The reason you aren't able to access items from the ViewBag inside your ajax success function is because the view that contains your script has already been rendered by the Razor view engine, effectively setting the variable a to whatever the value of #ViewBag.Price was at the time the page was rendered.
Looking at the process flow might be helpful:
(1) The request comes in for the view that has your script fragment in it.
(2) The controller method that returns your view is called.
(3) The Razor view engine goes through the view and replaces any references to #ViewBag.Price in your view with the actual value of ViewBag.Price. Assuming ViewBag.Price doesn't have a value yet, the success function in your script is now
success: function (data) {
$('#ddModel').empty();
$.each(data, function (index, val) {
var optionTag = $('<option></option>');
$(optionTag).val(val.Value).text(val.Text);
$('#ddModel').append(optionTag);
});
var a = '';
}
(4) The rendered html gets sent to the client
(5) Your ajax request gets triggered
(6) On success, a gets set to the empty string.
As you had mentioned in the comments of your question, the solution to this problem is to include a in the Json object returned by your action method, and access it using data.a in your script. The return line would look like
return Json(new {
model = vehModel,
a = Price
});
Keep in mind that if you do this, you'll have to access model data in your ajax success function with data.model.Field. Also, you shouldn't need to specify the JsonRequestBehavior.AllowGet option, since your method only responds to posts and your ajax request is a post.

How to fetch a specific div id from an html file through ajax

I have two html files called index.html & video.html
video.html holds coding like:
<div id="video">
<iframe src="http://www.youtube.com/embed/tJFUqjsBGU4?html5=1" width=500 height=500></iframe>
</div>
I want the above mentioned code to be crawled from video.html page from index.html
I can't use any back-end coding like php or .net
Is there any way to do using Ajax?
Try this...
$.ajax({
url: 'video.html',
success: function(data) {
mitem=$(data).filter('#video');
$(selector).html(mitem); //then put the video element into an html selector that is on your page.
}
});
For sure,send an ajax call.
$.ajax({
url: 'video.html',
success: function(data) {
data=$(data).find('div#video');
//do something
}
});
Yep, this is a perfect use case for ajax. When you make the $.ajax() request to your video.html page, you can then treat the response similar to the way you'd treat the existing DOM.
For example, you'd start the request by specifying the URI in the the following way:
$.ajax({
url: 'video.html'
})
You want to make sure that request succeeds. Luckily jQuery will handle this for you with the .done callback:
$.ajax({
url: "video.html",
}).done(function ( data ) {});
Now it's just a matter of using your data object in a way similar to the way you'd use any other jQuery object. I'd recommend the .find() method.
$.ajax({
url: "video.html",
}).done(function ( data ) {
$(data).find('#video'));
}
});
Since you mentioned crawl, I assume there is the possibility of multiple pages. The following loads pages from an array of urls, and stores the successful loads into results. It decrements remainingUrls (which could be useful for updating a progressbar) on each load (complete is called after success or error), and can call a method after all pages have been processed (!remainingUrls).
If this is overkill, just use the $.ajax part and replace myUrls[i] with video.html. I sepecify the type only because I ran into a case where another script changed the default type of ajax to POST. If you're loading dynamic pages like php or aspx, then the cache property might also be helpful if you're going to call this multiple times per session.
var myUrls = ['video1.html', 'video2.html', 'fail.html'],
results = [],
remainingUrls;
$(document).ready(function () {
remainingUrls = myUrls.length;
for (var i = 0, il = myUrls.length; i < il; i++) {
$.ajax({
url: myUrls[i],
type: 'get', // somebody might override ajax defaults
cache: 'false', // only if you're getting dynamic pages
success: function (data) {
console.log('success');
results.push(data);
},
error: function () {
console.log('fail');
},
complete: function() {
remainingUrls--;
if (!remainingUrls) {
// handle completed crawl
console.log('done');
}
}
});
}
});
not tested, but should be something similair to this: https://stackoverflow.com/a/3535356/1059828
var xhr= new XMLHttpRequest();
xhr.open('GET', 'index.html', true);
xhr.onreadystatechange= function() {
if (this.readyState!==4) return;
if (this.status!==200) return; // or whatever error handling you want
document.getElementsByTagName('html').innerHTML= this.responseText;
};
xhr.send();