How to Save HTML Page as PDF Using JavaScript or Jquery

Download a div in a HTML page as pdf using javascript

You can do it using jsPDF

HTML:

<div id="content">
<h3>Hello, this is a H3 tag</h3>

<p>A paragraph</p>
</div>
<div id="editor"></div>
<button id="cmd">generate PDF</button>

JavaScript:

var doc = new jsPDF();
var specialElementHandlers = {
'#editor': function (element, renderer) {
return true;
}
};

$('#cmd').click(function () {
doc.fromHTML($('#content').html(), 15, 15, {
'width': 170,
'elementHandlers': specialElementHandlers
});
doc.save('sample-file.pdf');
});

Export HTML page to PDF on user click using JavaScript

This is because you define your "doc" variable outside of your click event. The first time you click the button the doc variable contains a new jsPDF object. But when you click for a second time, this variable can't be used in the same way anymore. As it is already defined and used the previous time.

change it to:

$(function () {

var specialElementHandlers = {
'#editor': function (element,renderer) {
return true;
}
};
$('#cmd').click(function () {
var doc = new jsPDF();
doc.fromHTML(
$('#target').html(), 15, 15,
{ 'width': 170, 'elementHandlers': specialElementHandlers },
function(){ doc.save('sample-file.pdf'); }
);

});
});

and it will work.

Generate pdf from HTML in div using Javascript

jsPDF is able to use plugins. In order to enable it to print HTML, you have to include certain plugins and therefore have to do the following:

  1. Go to https://github.com/MrRio/jsPDF and download the latest Version.
  2. Include the following Scripts in your project:

    • jspdf.js
    • jspdf.plugin.from_html.js
    • jspdf.plugin.split_text_to_size.js
    • jspdf.plugin.standard_fonts_metrics.js

If you want to ignore certain elements, you have to mark them with an ID, which you can then ignore in a special element handler of jsPDF. Therefore your HTML should look like this:

<!DOCTYPE html>
<html>
<body>
<p id="ignorePDF">don't print this to pdf</p>
<div>
<p><font size="3" color="red">print this to pdf</font></p>
</div>
</body>
</html>

Then you use the following JavaScript code to open the created PDF in a PopUp:

var doc = new jsPDF();          
var elementHandler = {
'#ignorePDF': function (element, renderer) {
return true;
}
};
var source = window.document.getElementsByTagName("body")[0];
doc.fromHTML(
source,
15,
15,
{
'width': 180,'elementHandlers': elementHandler
});

doc.output("dataurlnewwindow");

For me this created a nice and tidy PDF that only included the line 'print this to pdf'.

Please note that the special element handlers only deal with IDs in the current version, which is also stated in a GitHub Issue. It states:

Because the matching is done against every element in the node tree, my desire was to make it as fast as possible. In that case, it meant "Only element IDs are matched" The element IDs are still done in jQuery style "#id", but it does not mean that all jQuery selectors are supported.

Therefore replacing '#ignorePDF' with class selectors like '.ignorePDF' did not work for me. Instead you will have to add the same handler for each and every element, which you want to ignore like:

var elementHandler = {
'#ignoreElement': function (element, renderer) {
return true;
},
'#anotherIdToBeIgnored': function (element, renderer) {
return true;
}
};

From the examples it is also stated that it is possible to select tags like 'a' or 'li'. That might be a little bit to unrestrictive for the most usecases though:

We support special element handlers. Register them with jQuery-style
ID selector for either ID or node name. ("#iAmID", "div", "span" etc.)
There is no support for any other type of selectors (class, of
compound) at this time.

One very important thing to add is that you lose all your style information (CSS). Luckily jsPDF is able to nicely format h1, h2, h3 etc., which was enough for my purposes. Additionally it will only print text within text nodes, which means that it will not print the values of textareas and the like. Example:

<body>
<ul>
<!-- This is printed as the element contains a textnode -->
<li>Print me!</li>
</ul>
<div>
<!-- This is not printed because jsPDF doesn't deal with the value attribute -->
<input type="textarea" value="Please print me, too!">
</div>
</body>

How to Export HTML to PDF (multiple pages) using jQuery?

I found 2 issues...


    1. Better use the latest version of pdfMake. You were using 0.1.22... I used 0.1.68 found on cdnjs.


    1. Seems like pdfMake isn't able to "split" an image and spead to several pages... So you have to provide some already splitted chunks. Fortunately, I found a SO answer about this specifically... Which I very slightly adapted here.

You can choose a predefined page format, like letter or A4, etc as a pdfMake param. See possible options.

Then you will have to adjust the height of the splitted image chunks by try/fail. Here, I found that 775px seemed good for a letter page... But only tried it with the HTML you provided.

SO snippets are disallowing downloads. So, useless to make it a snippet but you can check my CodePen.

Some documentation:

  • html2canvas
  • pdfMake
// Slightly adapted function from this SO answer: https://stackoverflow.com/a/21937796/2159528
// It now returns the objects formatted for pdfMake
function getClippedRegion(image, x, y, width, height) {
var canvas = document.createElement("canvas"),
ctx = canvas.getContext("2d");

canvas.width = width;
canvas.height = height;

// source region dest. region
ctx.drawImage(image, x, y, width, height, 0, 0, width, height);

return {
// Those are some pdfMake params
image: canvas.toDataURL(),
width: 500
};
}

$("body").on("click", "#downloadPDF", function () {

html2canvas($("#downloadPDFData")[0], {
onrendered: function (canvas) {

// split the canvas produced by html2canvas into several, based on desired PDF page height
let splitAt = 775; // A page height which fits for "LETTER" pageSize...

let images = [];
let y = 0;
while (canvas.height > y) {
images.push(getClippedRegion(canvas, 0, y, canvas.width, splitAt));
y += splitAt;
}

// PDF creation using pdfMake
var docDefinition = {
content: images,
pageSize: "LETTER"
};
pdfMake.createPdf(docDefinition).download("report.pdf");
}
});
});


Related Topics



Leave a reply



Submit