Innovate anywhere, anytime withruncode.io Your cloud-based dev studio.
Django

Export HTML Web Page to PDF Using JsPDF

2022-07-25

Using jsPDF in Django templates to export as PDF

jsPDF is used to generate pdf files in client-side Javascript.

You can find the links for jsPDF here and also you can find the link to project homepage.

You've to include the scripting files/links in head section to work properly.

Tip: We have to download the newest version of the library and include it in the HEAD or at the end of the BODY section.

Example to run the script from local storage:

In the HEAD section:

(or)

In the BODY section:

After loading the scripts in HEAD/BODY section, now we can start using the jsPDF library.

Lets start with some of basics of jsPDF to get the idea of using it in our applications:

First let us discuss how to create a new document?

It's simple as below mentioned:

var doc = new jsPDF(orientation, unit, format, compress);

The constructor can take several parameters.

  • orientation - The default value of orientation is "portrait". We can set it to "landscape" if we want a different page orientation.
  • unit - We can tell jsPDF in which units we want to work. Use on of the following: "pt" (points), "mm" (default), "cm", "in".
  • format - It's default page format. We can change it we want other formats also like: "a3", "a4" (default), "a5", "letter", "legal".

As an order to understand, here is an example:

var doc = new jsPDF('landscape');
doc.text(20, 20, 'Hello landscape world!');

We can add new page using the following code:

doc.addPage(width, height);

As parameters we can pass the page width and height in the units defined in the docuent constructor. Adding pages moves us to this page, so many operations will be executed on that page. If we want to go to another page we can use the setPage function.

doc.setPage(pageNumber);

You can also get the actual number of pages by using the below code:

doc.internal.getNumberOfPages();

In an order to understand, here is an example:

var doc = new jsPDF();
doc.text(20, 20, 'Hello world!');
doc.text(20, 30, 'This is client-side Javascript, pumping out a PDF.');
doc.addPage('a6','l');
doc.text(20, 20, 'Do you like that?');

Now it's time to work with text:

  1. The most important thing is displaying text, we do it using the funtion named doc.text which takes 3 parameters. like below:
doc.text(X, Y, "Text to be displayed");

- The first two are X and Y positions of the text in units defined in the document constructor.

Here we have to notice a point: Y position, it is the position of the text baseline, so printing something with the Y position set to 0 will actually print it over the top edge of the document.

- The third argument is the text to be displayed.

2. The second thing is the font name used to draw the text. We can choose one of the following: couriertimesarial. We can change the font family and font style by running the doc.setFont function.

doc.setFont("arial", "bold");

By executing the doc.getFontList function we can find out what fonts are available and what font styles we can set for given font.

doc.getFontList();
/*
{
    "courier": ["normal", "bold", "italic", "bolditalic"],
    "Courier": ["", "Bold", "Oblique", "BoldOblique"],
    "times": ["normal", "bold", "italic", "bolditalic"],
    "Times": ["Roman", "Bold", "Italic", "BoldItalic"],
    "helvetica": ["normal", "bold", "italic", "bolditalic"],
    "Helvetica": ["", "Bold", "", ""] 
}
*/

We can also change the font style individually by using the doc.setFontStyle or the doc.setFontType function, which is alias to the first one.

doc.setFontType("bolditalic");
// is the same as calling
doc.setFontStyle("bolditalic");

3. Next things is the font size. Now, for that we use doc.setFontSize function.

doc.setFontSize(40);

Example:

var doc = new jsPDF();
doc.setFontSize(22);
doc.text(20, 20, 'This is a title');

doc.setFontSize(16);
doc.text(20, 30, 'This is some normal sized text underneath.');

4. The text color. We can change the text color using the doc.setTextColor function and passing three parameters which are RGB (Red, Green, Blue) color values.

var doc = new jsPDF();
// I know the proper spelling is colour ;)
doc.setTextColor(100);
doc.text(20, 20, 'This is gray.');

doc.setTextColor(150);
doc.text(20, 30, 'This is light gray.');

doc.setTextColor(255, 0, 0);
doc.text(20, 40, 'This is red.');

doc.setTextColor(0, 255, 0);
doc.text(20, 50, 'This is green.');

doc.setTextColor(0, 0, 255);
doc.text(20, 60, 'This is blue.');

5.Next things is the splitting text. Now, for that we use doc.splitTextToSize function

const splitText = doc.splitTextToSize('hey I am a veeeeeeeeeeery long string', 10)
doc.text(splitText, 0, 0)

6.Text alignment inside the doc

var doc = new jsPDF('p', 'pt', 'letter');
    
    doc.text( 'This text is normally\raligned.', 140, 50 );
    
    doc.text( 'This text is centered\raround\rthis point.', 140, 120, 'center' );
    
    doc.text( 'This text is rotated\rand centered around\rthis point.', 140, 300, 45, 'center' );
    
    doc.text( 'This text is\raligned to the\rright.', 140, 400, 'right' );
    
    doc.text( 'This text is\raligned to the\rright.', 140, 550, 45, 'right' );
    
    doc.text( 'This single line is centered', 460, 50, 'center' );

    doc.text( 'This right aligned text\r\rhas an empty line.', 460, 200, 'right' );
    
    
    doc.save('Test.pdf');

In a order of full example:

var doc = new jsPDF();

doc.text(20, 20, 'This is the default font.');

doc.setFont("courier");
doc.setFontType("normal");
doc.text(20, 30, 'This is courier normal.');

doc.setFont("times");
doc.setFontType("italic");
doc.text(20, 40, 'This is times italic.');

doc.setFont("helvetica");
doc.setFontType("bold");
doc.text(20, 50, 'This is helvetica bold.');

doc.setFont("courier");
doc.setFontType("bolditalic");
doc.text(20, 60, 'This is courier bolditalic.');

Now it's time to work with Images:

We have only function for the images is the doc.addImage. It takes image as a first parameter, image format/type as a second and X,Y positions of the image as a third and fourth arguments respectively. Here we can also optionally pass new image size as a fifth and sixth arguments.

var img = new Image();
img.addEventListener('load', function() {
    var doc = new jsPDF();
    doc.addImage(img, 'png', 10, 50);
});
img.src = 'image_path/image_name.png';

In the above example, we passed an Image HTML DOM element as a first argument of the addImage function, however it can also be a base64 encoded image string.

var imgData = 'data:image/jpeg;base64,/.......base64code.....iiigAoooo//2Q==';
var doc = new jsPDF();
doc.setFontSize(40);
doc.text(35, 25, "Octonyan loves jsPDF");
doc.addImage(imgData, 'JPEG', 15, 40, 180, 180);

Working With Graphics:

First of all, we have to set the drawn shapes fill and stroke with colors. We do it using the doc.setFillColor and the doc.setDrawColor accordingly, passing RGB color values as parameters. 

doc.setFillColor(100, 100, 240);
doc.setDrawColor(100, 100, 0);

We can also set the stroke width. The stroke width unit is the same as defined in the document constructor.

doc.setLineWidth(1);

Every shape drawing function takes the center point co-ordinates (triangle is the only exception) as two first parameters. They also take the last parameter for drawing style. It can be "S", "F", "DF", "FD" string and the meanings are: "stroke", "fill", "stroke and fill", "fill and stroke". The last two of course differ in the order of the drawing operations.

For example, we can draw an ellipse, by passing two radiuses :

// Empty ellipse
doc.ellipse(50, 50, 10, 5);
// Filled ellipse
doc.ellipse(100, 50, 10, 5, 'F');
// Filled circle with borders

or a circle, by passing only one radius as parameter :

doc.circle(150, 50, 5, 'FD');

or a rectangle, by passing it's width and height as parameters :

var doc = new jsPDF();

// Empty square
doc.rect(20, 20, 10, 10); 

// Filled square
doc.rect(40, 20, 10, 10, 'F');

// Empty red square
doc.setDrawColor(255,0,0);
doc.rect(60, 20, 10, 10);

// Filled square with red borders
doc.setDrawColor(255,0,0);
doc.rect(80, 20, 10, 10, 'FD'); 

// Filled red square
doc.setDrawColor(0);
doc.setFillColor(255,0,0);
doc.rect(100, 20, 10, 10, 'F'); 

 // Filled red square with black borders
doc.setDrawColor(0);
doc.setFillColor(255,0,0);
doc.rect(120, 20, 10, 10, 'FD');

or a rounded rectangle, by passing it's width, height and border radius as parameters : 

// Filled sqaure with rounded corners
doc.roundedRect(50, 150, 10, 10, 3, 3, 'FD');
// Black sqaure with rounded corners
doc.setDrawColor(0);
doc.setFillColor(255, 255, 255);
doc.roundedRect(140, 20, 10, 10, 3, 3, 'FD');

and a triangle, by passing each corners co-ordinates.

// Filled triangle with borders
var doc = new jsPDF();
doc.triangle(60, 100, 60, 120, 80, 110, 'FD');
doc.setLineWidth(1);
doc.setDrawColor(255,0,0);
doc.setFillColor(0,0,255);
doc.triangle(100, 100, 110, 100, 120, 130, 'FD');

Last but not least, we can also draw lines passing through the co-ordinates of two points.

// Line
doc.line(50, 250, 100, 250);

Here is an example and some of functionalities we can apply on lines:

var doc = new jsPDF();

doc.line(20, 20, 60, 20); // horizontal line
 
doc.setLineWidth(0.5);
doc.line(20, 25, 60, 25);

doc.setLineWidth(1);
doc.line(20, 30, 60, 30);

doc.setLineWidth(1.5);
doc.line(20, 35, 60, 35);

doc.setDrawColor(255,0,0); // draw red lines

doc.setLineWidth(0.1);
doc.line(100, 20, 100, 60); // vertical line

doc.setLineWidth(0.5);
doc.line(105, 20, 105, 60);

doc.setLineWidth(1);
doc.line(110, 20, 110, 60);

doc.setLineWidth(1.5);
doc.line(115, 20, 115, 60);

Here is a full example to understand in a better way:

var doc = new jsPDF();

doc.ellipse(40, 20, 10, 5);

doc.setFillColor(0,0,255);
doc.ellipse(80, 20, 10, 5, 'F');

doc.setLineWidth(1);
doc.setDrawColor(0);
doc.setFillColor(255,0,0);
doc.circle(120, 20, 5, 'FD');

Now, we are going to know about an interesting functionality over here - addHTML():

The below example will show you a preview of the html document that you've added this jsPDF script to generate pdf. This will generate the pdf as shown in the browsers.

var pdf = new jsPDF('p','pt','a4');

pdf.addHTML(document.body,function() {
 var string = pdf.output('datauristring');
 $('.preview-pane').attr('src', string);
});

The below example code will render the html and dispalys as plain text.

var doc = new jsPDF();

// We'll make our own renderer to skip this editor
var specialElementHandlers = {
 '#editor': function(element, renderer){
  return true;
 }
};

// All units are in the set measurement for the document
// This can be changed to "pt" (points), "mm" (Default), "cm", "in"
doc.fromHTML($('body').get(0), 15, 15, {
 'width': 170, 
 'elementHandlers': specialElementHandlers
});

We can also add Metadata to our Generating pdf:

var doc = new jsPDF();
doc.text(20, 20, 'This PDF has a title, subject, author, keywords and a creator.');

// Optional - set properties on the document
doc.setProperties({
 title: 'Title',
 subject: 'This is the subject',
 author: 'Author Name',
 keywords: 'generated, javascript, web 2.0, ajax',
 creator: 'Creator Name'
});

// Output as Data URI
doc.save('Test.pdf');

For the people who want a full script with an example:

  1. Add the following script to the HEAD:

<script src="http://mrrio.github.io/jsPDF/dist/jspdf.debug.js"></script>

2. Add HTML script to execute jsPDF code:

Customize this to pass the identifier or just change the #content to be the identifier you need.

<script>
    function demoFromHTML() {
        var pdf = new jsPDF('p', 'pt', 'letter');
        // source can be HTML-formatted string, or a reference
        // to an actual DOM element from which the text will be scraped.
        source = $('#content')[0];

        // 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.
        specialElementHandlers = {
            // element with id of "bypass" - jQuery style selector
            '#bypassme': function (element, renderer) {
                // true = "handled elsewhere, bypass text extraction"
                return true
            }
        };
        margins = {
            top: 80,
            bottom: 60,
            left: 40,
            width: 522
        };
        // all coords and widths are in jsPDF instance's declared units
        // 'inches' in this case
        pdf.fromHTML(
        source, // HTML string or DOM elem ref.
        margins.left, // x coord
        margins.top, { // y coord
            'width': margins.width, // max width of content on PDF
            'elementHandlers': specialElementHandlers
        },

        function (dispose) {
            // dispose: object with X, Y of the last line add to the PDF 
            //          this allow the insertion of new lines after html
            pdf.save('Test.pdf');
        }, margins);
    }
 </script>

3. Add your body content to generate as PDF:

<a class="button" href="javascript:demoFromHTML()">Generate PDF</a>

Here is a complete example to generate a pdf using jsPDF.

To Know more about our Django CRM(Customer Relationship Management) Open Source Package. Check Code