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:
- Go to https://github.com/MrRio/jsPDF and download the latest Version.
- 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...
- Better use the latest version of pdfMake. You were using 0.1.22... I used 0.1.68 found on cdnjs.
- 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
How to Run Node Js Code from Npm Inside of Swift
Triggering Onclick Event Using Middle Click
Download a Div in a HTML Page as PDF Using JavaScript
What Is Wkerrordomain Error 4 from Wkwebview
How to Return a Variable from Google Maps JavaScript Geocoder Callback
Rendering React Components with Promises Inside the Render Method
Rails - How to Include JavaScript Files Only on Certain Pages
How to Detect Scroll Position of Page Using Jquery
Ruby Methods Within JavaScript Within Haml
Ruby with Watir: Handling JavaScript Popup Window
How to Print an Iframe from JavaScript in Safari/Chrome
How to Detect When a Youtube Video Finishes Playing
Explanation of [].Slice.Call in JavaScript
How to See Ping Pong in Web Socket in iOS
Websocket Handshake with Ruby and Em::Websocket::Server