jspdf-autotable styles not working in live website - javascript

I am trying to set a custom font inside styles{} inside doc.autoTable({ }). This is my code:
let doc = new jsPDF();
doc.autoTable({
html: '#news_pos',
startX: 10,
startY: 15,
theme: 'grid',
bodyStyles: {lineColor: [0, 0, 0]},
styles: {
font: "SakalBharati", //<------ This is the font
fontSize: 10,
cellWidth: 'auto',
halign: 'center',
fillColor: [225, 197, 238]
},
})
doc.save("file.pdf");
The above code is working perfectly when I run it in localhost. But now, when I've uploaded it into my live website, strangely, it's not working. The code below works if I apply the font to a standard text (in both localhost and live website) like:
doc.setFont("SakalBharati","normal");
doc.text(10,15,"पूसीरे के");
/*This code works perfectly in both local and live server. Only
when I apply the font in jspdf-autotable (in live server),
it doesn't work*/
Localhost output:
Live website output:
Why is this happening? How do I fix this?
EDIT: I even tried converting the text to an image and appending it to the cell in my HTML table:
var tCtx = document.getElementById('textCanvas').getContext('2d'),
imageElem = document.getElementById('image');
tCtx.canvas.width = tCtx.measureText("पूसीरे के रेसुब ने नाबालिगों").width;
tCtx.fillText("पूसीरे के रेसुब ने नाबालिगों", 0, 10);
imageElem.src = tCtx.canvas.toDataURL();
htmltable_cell.appendChild(imageElem);
And then appending this image into my table cell in autotable:
doc.autoTable({
html: '#news_pos',
startX: 10,
startY: 15,
theme: 'grid',
didDrawCell: function(hookData) {
for(var j=1; j<document.getElementById("news_pos").rows.length; j++){
for(var k=0; k<document.getElementById("news_pos").rows[j].cells.length; k++){
if(document.getElementById("news_pos").rows[j].cells.item(k).innerHTML.includes("img")){
if(hookData.column.index == k && hookData.row.index == j){
var td = hookData.cell.raw;
var img = td.getElementsByTagName('img')[0];
var dim = hookData.cell.height - hookData.cell.padding('vertical');
doc.addImage(img.src, hookData.cell.x+4, hookData.cell.y+1, 80,dim+2);
}
}
}
}
},
bodyStyles: {lineColor: [0, 0, 0]}
})
This too gives the same output as the screenshots shared above

Related

html2pdf.js produces a blank document on iOS

I am using eKoopman's html2pdf.js library https://github.com/eKoopmans/html2pdf.js to produce a list of recommendation for a user at the end of an assessment. These are dynamically generate based on the responses.
It works wonderfully on desktop. However when I try to output the PDF on iOS the document is blank except for the headers and footers that I add in a separate function.
Its like it completely ignores the element.
Below is the code I trigger when the user clicks a button.
var element = $('#recommendationsdisplay').html();
var opt = {
margin: [.75,0,.75,0],
filename: 'Click_Start_' + Math.floor(Date.now() / 10000) + '.pdf',
enableLinks: true,
image: {
type: 'jpeg',
quality: 1
},
html2canvas: {
scale: 2,
dpi: 300,
letterRendering: true
},
jsPDF: {
unit: 'in',
format: 'letter',
orientation: 'portrait'
},
pagebreak:{
mode: ['avoid-all', 'css', 'legacy'],
avoid: 'div.recgrid-item'
}
};
html2pdf().from(element, 'string').set(opt).toPdf().get('pdf').then(function (pdfObject) {
/* some image related encoding */
var headerTitle = "Recommendations";
var footerCR = "© 2020";
// Header and Footer
for (var i = 1; i < pdf_pages.length; i++) {
pdfObject.setPage(i);
pdfObject.setFontSize(14);
pdfObject.setTextColor('#0090DA');
pdfObject.addImage(headerData, 'PNG', 0, 0, 8.5, .5);
pdfObject.setFontSize(10);
pdfObject.setTextColor('#777777');
pdfObject.text(footerCR, 4, 10.5);
pdfObject.text(' ' + i, 7.375, 10.5);
pdfObject.addImage(logoData, 'PNG', .75, 10.25, 1, .325);
}
}).save();
EDIT: It seems like the issue is with the canvas size limitation. The element is rendered properly in the PDF if its height is NOT above a certain threshold (fewer items chosen in the assessment). My document is only a few pages long (<7)though and I have seen other users report being able to create PDFs with dozens of pages so I am not sure what the issue is.
pagebreak mode = avoid-all causing the problem. Take away 'avoid-all' .
I have resolved this issue by splitting the whole document into pages and then passing pages one by one to the html2pdf library to generate and bind all pages into a single pdf file.
Example code.
var opt = {
margin: [5, 10, 0.25, 10],
pagebreak: {mode: 'css', after: '.page2el'},
image: {type: 'jpeg', quality: 1},
filename: 'testfile.pdf',
html2canvas: {dpi: 75, scale: 2, letterRendering: true},
jsPDF: {unit: 'pt', format: 'letter', orientation: 'p'},
};
var count = 1;
let doc = html2pdf().set(opt).from(document.getElementById('page2el')).toPdf();
jQuery("#cs_pdf").find("div").each(function (e) {
// Filtering document each page with starting id with page2el
if (jQuery(this).attr('id') && jQuery(this).attr('id').indexOf('page2el') != -1) {
if (count != 1) {
doc = doc.get('pdf').then((pdf) => {
pdf.addPage();
var totalPages = jQuery("#cs_pdf").find(".page2el").length + 1;
// Adding footer text and page number for each PDF page
for (let i = 1; i <= totalPages; i++) {
pdf.setPage(i);
pdf.setFontSize(10);
pdf.setTextColor(60);
if (i !== 1) {
pdf.text('Page ' + i + ' of ' + totalPages, pdf.internal.pageSize.getWidth() - 100, pdf.internal.pageSize.getHeight() - 25);
}
if (i === 1) {
pdf.text("Confidential", pdf.internal.pageSize.getWidth() - 340, pdf.internal.pageSize.getHeight() - 35);
} else {
pdf.text(consultant_company, pdf.internal.pageSize.getWidth() - 530, pdf.internal.pageSize.getHeight() - 25);
}
}
}).from(document.getElementById(jQuery(this).attr('id'))).toContainer().toCanvas().toPdf();
}
count++;
}
// On Jquery each loop completion executing save function on doc object to compile and download PDF file
}).promise().done(function () {
doc.save();
});

How to set header and footer using html2pdf - jspdf javascript plugin?

I want to convert HTML contents to a pdf file and store it to the server so, I used jspdf - html2pdf function for convert HTML contents to pdf file.
so i am trying a javascript code in angular project like that,
var element = this.pdfTable.nativeElement
var opt = {
margin: 0.5,
filename: 'ct-scan.pdf',
enableLinks: false,
pagebreak: { mode: 'avoid-all' },
image: { type: 'jpeg', quality: 0.98 },
html2canvas: { scale: 2 },
jsPDF: { unit: 'in', format: 'a4', orientation: 'portrait' }
};
html2pdf().from(element).set(opt).toPdf().get('pdf').then(function (pdf) {
var totalPages = pdf.internal.getNumberOfPages();
for (var i = 1; i <= totalPages; i++) {
pdf.setPage(i);
pdf.setFontSize(10);
pdf.setTextColor(150);
pdf.text('Page ' + i + ' of ' + totalPages, pdf.internal.pageSize.getWidth() - 100,
pdf.internal.pageSize.getHeight() - 30);
}
}).save()
it works fine., but the header and footer are not set in the result. so anybody can help me to solve this issue? thanks in advance.
Since your unit is using inch jsPDF: { unit: 'in' ... , minus the width of 100 and the height of 30 will become negative number. The pdf won't show the text probably.
Solution: You can print the current width and height by console.log; or just divided by 2 to make it go center, then you can adjust the text to your desired position.
var element = this.pdfTable.nativeElement;
var opt = {
margin: 0.5,
filename: 'ct-scan.pdf',
enableLinks: false,
pagebreak: { mode: 'avoid-all' },
image: { type: 'jpeg', quality: 0.98 },
html2canvas: { scale: 2 },
jsPDF: { unit: 'in', format: 'a4', orientation: 'portrait' }
};
html2pdf().from(element).set(opt).toPdf().get('pdf').then(function (pdf) {
var totalPages = pdf.internal.getNumberOfPages();
//print current pdf width & height to console
console.log("getHeight:" + pdf.internal.pageSize.getHeight());
console.log("getWidth:" + pdf.internal.pageSize.getWidth());
for (var i = 1; i <= totalPages; i++) {
pdf.setPage(i);
pdf.setFontSize(10);
pdf.setTextColor(150);
//divided by 2 to go center
pdf.text('Page ' + i + ' of ' + totalPages, pdf.internal.pageSize.getWidth()/2,
pdf.internal.pageSize.getHeight()/ 2);
}
}).save();

Adding Images with JSPDF

Am using JSPDF to generate PDF in javascript, when I add Images and I generate the PDF file, the PDF file does not display the image until I generate the PDF a second time. Here is my code below
var doc = new jsPDF('p', 'pt', 'a4');
var res = doc.autoTableHtmlToJson(document.getElementById("data-table-committee"));
var header = function (data) {
doc.setFontSize(18);
doc.setTextColor(40);
doc.setFontStyle('normal');
doc.text("Committee Count List", data.settings.margin.left, 80);
console.log('adding image');
doc.addImage(headerImgData, 'PNG', data.settings.margin.left, 20, 150, 30);
console.log('adding image done');
};
var options = {
beforePageContent: header,
margin: {
top: 50
},
startY: doc.autoTableEndPosY() + 20
};
doc.autoTable(res.columns, res.data, options);
doc.save("Committee Count List.pdf");
What am I doing wrong and How can I get my image to be displayed the first time I generate the PDF
You can also create pdf using pdfkit. Here is the code that generates pdf with an image.
var PDFDocument = require ('pdfkit');
var fs = require('fs');
doc = new PDFDocument
doc.pipe(fs.createWriteStream('output.pdf'))
doc.image('E:/sii/nodejs/uploads/public/uploads/test.jpg', {
fit: [250, 300],
align: 'center',
valign: 'center'
});
doc.end()

Webview doesn´t display correctly in android

I´m using appcelerator studio %.2.0 GA webView with chartjs plugin line update.
With this code below, I have a perfect view in web browser like Chrome (without webview), but on android smartphone or emulator it not runs correctly. Appears a red line on the bottom and double line on the strokeGrid.
Does anybody help ?
This is the code:
Javascript-
var count = 0;
//
// create base UI tab and root window
//
var win = Titanium.UI.createWindow({
title:'BtTest',
backgroundColor:'#eff2d8',
layout: 'vertical'
});
var mainView = Ti.UI.createView({
top: 0,
width: Ti.UI.SIZE,
height: Ti.UI.SIZE,
backgroundColor: '#7cd0F7',
});
var webView = Ti.UI.createWebView({
backgroundColor: '#F0F8FF',
top:100,
left: 0,
height: Ti.UI.FILL,
width: Ti.UI.FILL,
cacheMode: Ti.UI.Android.WEBVIEW_LOAD_NO_CACHE,
borderColor: 'black',
url: 'html/lineChart.html'
});
mainView.add(webView);
function send(value)
{
Ti.App.fireEvent("app:fromChart", {message: value});
Ti.API.info('Sent: ', value);
count ++;
Ti.API.info("Count: " + count);
}
function interval()
{
setInterval(function()
{
send(Math.floor(Math.random() * 100));
}, 500);
}
interval();
win.add(mainView);
win.open();
HTML-
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
<script src="../js/Chart.min.js"></script>
</head>
<body>
<canvas id="updating-chart" width="320" height="220"> </canvas>
<script>
var N = 20;
var zero_array = [];
for (i = 0; i < N; i++)
zero_array.push("");
var canvas = document.getElementById('updating-chart'),
ctx = canvas.getContext('2d'),
startingData = {
labels: zero_array,
datasets: [
{
strokeColor: "rgba(255,0,0,1)",
data: [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
}]
},
latestLabel = startingData.labels[0];
var lineOptions = {
bezierCurve: false,
scaleOverlay : false,
scaleOverride : false,
scaleSteps : null,
scaleStepWidth : null,
scaleStartValue : null,
scaleLineColor : "rgba(0,0,0,1)",
scaleLineWidth : 1,
scaleShowLabels : true,
scaleLabel : "<%=value%>",
scaleFontFamily : "'Arial'",
scaleFontSize : 12,
scaleFontStyle : "normal",
scaleFontColor : "#666",
scaleShowGridLines : true,
scaleGridLineColor : "rgba(0,0,0,1)",
scaleGridLineWidth : 1,
pointDot : true,
pointDotRadius : 0,
pointDotStrokeWidth : 1,
datasetStroke : true,
datasetStrokeWidth : 2,
datasetFill : false,
animation : false,
responsive: false,
maintainAspectRatio: true
};
// We wait for everything to be loaded
window.onload = function main()
{
// Get the context of the canvas
var ctx = document.getElementById("line_example").getContext("2d");
// Create the Chart object
var line_example_chart = new Chart(ctx).Line(data,lineOptions);
// Used for the labels on the X axis
var label_idx = 1;
Ti.App.addEventListener("app:fromChart", function(e)
{
var msg = e.message;
if(msg == 0) msg = 1;
line_example_chart.removeData();
line_example_chart.addData([msg], label_idx++);
});
window();
};
</script>
If you are building for an older version of android, the webview for appcelerator was not Chromium based which might cause things to look a bit different. You can read more about it here.
A quote from the WebView documentation for appcelerator:
Starting with Android 4.4 (API Level 19), the WebView component is based off of Chromium, introducing a number of changes to its rendering engine. Web content may look or behave differently depending on the Android version. The WebView does not have full feature parity with Chrome for Android.

Html2canvas for each div export to pdf separately

I have Page, It has 6 div with same class name "exportpdf", I am converting those div into pdf using jspdf and html2canvas
var elementTobePrinted = angular.element(attrs.selector),
iframeBody = elementTobePrinted.contents().find('div.exportpdf');
In html2canvas.....
html2canvas(elementTobePrinted, {
onrendered: function (canvas) {
var doc = new jsPDF();
for(var i=1;i<elementTobePrinted.length;i++){
doc.addImage(canvas.toDataURL("image/jpeg"), 'jpeg', 15, 40, 180, 160);
doc.addImage(canvas.toDataURL("image/jpeg"),'JPEG', 0, 0, 215, 40)
doc.addPage();
}
doc.save(attrs.fileName);
}
I converted page to canvas.its create same div contents for whole pdf. I need each div contents into same pdf with different pages.
Can anyone help me?
The problem is with html2canvas:
doc.addImage(canvas.toDataURL("image/jpeg"), 'jpeg', 15, 40,180, 160);
Here I need to pass elementTobePrinted list to addImage.
On angular 2(now 6) framework.
u can use the logic as below,
On click execute generateAllPdf() function,
gather all 6 id's from my html collection,
iterate through each id and call html2canvas function,
as html2canvas runs in background to process images, i m using
await on function,
after the html2canvas completes its process, i ll save the
document,
If suppose i wont use await i ll end-up in downloading an empty
page.
below is my code logic,
// As All Functions in js are asynchronus, to use await i am using async here
async generateAllPdf() {
const doc = new jsPDF('p', 'mm', 'a4');
const options = {
pagesplit: true
};
const ids = document.querySelectorAll('[id]');
const length = ids.length;
for (let i = 0; i < length; i++) {
const chart = document.getElementById(ids[i].id);
// excute this function then exit loop
await html2canvas(chart, { scale: 1 }).then(function (canvas) {
doc.addImage(canvas.toDataURL('image/png'), 'JPEG', 10, 50, 200, 150);
if (i < (length - 1)) {
doc.addPage();
}
});
}
// download the pdf with all charts
doc.save('All_charts_' + Date.now() + '.pdf');
}
I think the issue here is that elementTobePrintedis not what you think it is.
When you run the code:
var elementTobePrinted = angular.element(attrs.selector)
This will return you a list of every element that matches the conditions, so you said you have 6 of these elements ("It has 6 divs").
Have you tried replacing:
html2canvas(elementTobePrinted, {
onrendered: function (canvas) {
var doc = new jsPDF();
for(var i=1;i<elementTobePrinted.length;i++) {
doc.addImage(canvas.toDataURL("image/jpeg"), 'jpeg', 15, 40, 180, 160);
doc.addImage(canvas.toDataURL("image/jpeg"),'JPEG', 0, 0, 215, 40)
doc.addPage();
}
doc.save(attrs.fileName);
}
With...
for(var i=0; i<elementTobePrinted.length; i++){
html2canvas(elementTobePrinted[i], {
onrendered: function (canvas) {
var doc = new jsPDF();
doc.addImage(canvas.toDataURL("image/jpeg"), 'jpeg', 15, 40, 180, 160);
doc.addImage(canvas.toDataURL("image/jpeg"),'JPEG', 0, 0, 215, 40)
doc.addPage();
doc.save(attrs.fileName);
}
}
The reason I suggest this is that html2Canvas wants a SINGLE element as its first parameter and your example above passes a list of elements (I think, assuming angular.element(attrs.selector) finds all 6 divs you are trying to print).

Categories

Resources