I have a content div with the id as "content". In the content div I have some graphs and some tables. I want to download that div as a pdf when user click on download button. Is there a way to do that using javascript or jQuery?
- 1code.google.com/p/jspdf is the best library i know of which can do this.alvinarul– alvinarul2013-06-25 09:05:48 +00:00Commented Jun 25, 2013 at 9:05
- How can I use jsPDF for downloading a content in specific div? from what i see in the examples in their site it cant be done.Midhun Mathew– Midhun Mathew2013-06-25 09:12:46 +00:00Commented Jun 25, 2013 at 9:12
- @alvinarul Note that jsPDF is currently not maintained and has some significant performance issues for multi-page documents.GROVER.– GROVER.2023-12-12 01:05:19 +00:00Commented Dec 12, 2023 at 1:05
8 Answers
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'); }); 20 Comments
doc variable inside the click function.Content inside a <div class='html-content'>....</div> can be downloaded as pdf with styles using jspdf & html2canvas.
You need to refer both js libraries,
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.5.3/jspdf.min.js"></script> <script type="text/javascript" src="https://html2canvas.hertzen.com/dist/html2canvas.js"></script> Then call below function,
//Create PDf from HTML... function CreatePDFfromHTML() { var HTML_Width = $(".html-content").width(); var HTML_Height = $(".html-content").height(); var top_left_margin = 15; var PDF_Width = HTML_Width + (top_left_margin * 2); var PDF_Height = (PDF_Width * 1.5) + (top_left_margin * 2); var canvas_image_width = HTML_Width; var canvas_image_height = HTML_Height; var totalPDFPages = Math.ceil(HTML_Height / PDF_Height) - 1; html2canvas($(".html-content")[0]).then(function (canvas) { var imgData = canvas.toDataURL("image/jpeg", 1.0); var pdf = new jsPDF('p', 'pt', [PDF_Width, PDF_Height]); pdf.addImage(imgData, 'JPG', top_left_margin, top_left_margin, canvas_image_width, canvas_image_height); for (var i = 1; i <= totalPDFPages; i++) { pdf.addPage(PDF_Width, PDF_Height); pdf.addImage(imgData, 'JPG', top_left_margin, -(PDF_Height*i)+(top_left_margin*4),canvas_image_width,canvas_image_height); } pdf.save("Your_PDF_Name.pdf"); $(".html-content").hide(); }); } Ref: pdf genration from html canvas and jspdf.
May be this will help someone.
4 Comments
Your solution requires some Ajax method to pass the html to a back-end server that has a html to pdf facility and then returning the pdf output generated back to the browser.
First setting up the client side code, we will setup the jQuery code as
var options = { "url": "/pdf/generate/convert_to_pdf.php", "data": "data=" + $("#content").html(), "type": "post", }; $.ajax(options); Then intercept the data from the html2pdf generation script (somewhere from the internet).
convert_to_pdf.php looks like this:
<?php $html = $_POST['data']; $pdf = html2pdf($html); header("Content-Type: application/pdf"); //check this is the proper header for pdf header("Content-Disposition: attachment; filename='some.pdf';"); echo $pdf; ?> 6 Comments
AFAIK there is no native jquery function that does this. Best option would be to process the conversion on the server. How you do this depends on what language you are using (.net, php etc.). You can pass the content of the div to the function that handles the conversion, which would return a pdf to the user.
1 Comment
Thought I would add my two cents, as some of the answers here are over 10 years old and have some significant performance bottlenecks.
Using @Vishnu S' answer with some minor modifications, we go from 910.52 ms per page to just 112.49 ms per page. A reduction of over 87%!
// SEE: https://www.npmjs.com/package/html-to-image import { toJpeg } from "html-to-image"; // The dimensions of a single A4 page; what we're basing the PDF document on. const A4_MARGIN_PX = 40; const A4_CONTENT_WIDTH_PX = 640; const A4_CONTENT_HEIGHT_PX = A4_CONTENT_WIDTH_PX * A4_PORTRAIT_RATIO; const A4_TOTAL_WIDTH_PX = A4_CONTENT_WIDTH_PX + (A4_MARGIN_PX * 2); const A4_TOTAL_HEIGHT_PX = A4_CONTENT_HEIGHT_PX + (A4_MARGIN_PX * 2); // Will return a data URI string. const htmlToPdf = async (element: HTMLElement): Promise<string> => { const elementBounds = element.getBoundingClientRect(); const pdfBounds = [A4_TOTAL_WIDTH_PX, A4_TOTAL_HEIGHT_PX]; const pdf = new jsPDF("portrait", "px", pdfBounds); // These settings are optional, but I've found they help with file size and retina display support. const pdfAsImage = await toJpeg(element, { quality: 0.95, pixelRatio: 2, }); const totalPages = Math.ceil(elementBounds.height / A4_CONTENT_HEIGHT_PX); for(let pageNum = 0; pageNum < totalPages; pageNum++){ // Add a page as long as it's not the first page, as jsPDF does this automatically. // This will focus the added page, as a side-effect. if(pageNum > 0) pdf.addPage(pdfBounds); pdf.addImage( pdfAsImage, "jpg", // Reposition the image based on the page number. A4_MARGIN_PX, A4_MARGIN_PX - (pageNum * (A4_CONTENT_HEIGHT_PX + (A4_MARGIN_PX * 2))), A4_CONTENT_WIDTH_PX, elementBounds.height ); } return pdf.output("datauristring"); }; Comments
Yes, it's possible to To capture div as PDFs in JS. You can can check the solution provided by https://grabz.it. They have nice and clean JavaScript API which will allow you to capture the content of a single HTML element such as a div or a span.
So, yo use it you will need and app+key and the free SDK. The usage of it is as following:
Let's say you have a HTML:
<div id="features"> <h4>Acme Camera</h4> <label>Price</label>$399<br /> <label>Rating</label>4.5 out of 5 </div> <p>Cras ut velit sed purus porttitor aliquam. Nulla tristique magna ac libero tempor, ac vestibulum felisvulput ate. Nam ut velit eget risus porttitor tristique at ac diam. Sed nisi risus, rutrum a metus suscipit, euismod tristique nulla. Etiam venenatis rutrum risus at blandit. In hac habitasse platea dictumst. Suspendisse potenti. Phasellus eget vehicula felis.</p> To capture what is under the features id you will need to:
//add the sdk <script type="text/javascript" src="grabzit.min.js"></script> <script type="text/javascript"> //login with your key and secret. GrabzIt("KEY", "SECRET").ConvertURL("http://www.example.com/my-page.html", {"target": "#features", "format": "pdf"}).Create(); </script> You need to replace the http://www.example.com/my-page.html with your target url and #feature per your CSS selector.
That's all. Now, when the page is loaded an image screenshot will now be created in the same location as the script tag, which will contain all of the contents of the features div and nothing else.
The are other configuration and customization you can do to the div-screenshot mechanism, please check them out here
1 Comment
Here is the method that worked for me (in Vue 2):
downloadQrCardAsPdf() { const fileName = this.qrEntryCard.title + "-" + this.qrEntryCard.id + "_" + this.qrEntryCard.createdAt + ".pdf"; html2canvas(this.$refs.qrCodeCardDiv).then(function (canvas) { const ctx = canvas.getContext("2d"); const imgData = ctx.getImageData(0,0, canvas.width, canvas.height); const pdf = new jsPDF({unit: 'px', format: [canvas.width, canvas.height]}); pdf.addImage(imgData, 'PNG',0,0, canvas.width, canvas.height); pdf.save(fileName); }); } Inspired by the answer of @Vishnu S and developed.
Comments
//surround the content you want to print with a div block, with an id. <div id=myDiv > // any content here </div> //then call this function: printDiv(myDiv); // it allows the user to print it, or save it as a pdf function printDiv(x) { var divContents = document.getElementById(x).innerHTML; var a = window.open('', '', 'height=500, width=500'); var date = new Date().toDateString(); a.document.write('<html>'); a.document.write('<head>'); a.document.write('<link rel="stylesheet" href="myCss.css">'); // you can create a specific css just for printing (other css then the css // used for the digital version) a.document.write('</head>'); a.document.write('<body> <div class=head><h1>myTitle</h1></div>'); // add title a.document.write(date); // add printout date a.document.write('</div>'); a.document.write(divContents); a.document.write('</body></html>'); a.document.close(); a.print(); }