Tuesday 17 February 2015

Capture HTML elements to PDF

Capture HTML elements to a PDF file is an interesting feature some projects may need. My need was to capture a dashboard full of widgets.

For this I used two javascript libraries:
- html2canvas which is able to capture DOM elements as images
- jspdf which is able to create PDF documents in javascript

The ideea behind can be resumed to a small code snippet:

var doc = new jsPDF('l', 'mm'); 

html2canvas($(elementId), {
          onrendered: function(canvas) {         
              var imgData = canvas.toDataURL('image/png'); 
              ....
              doc.addImage(imgData, 'PNG', x, y);
              ...
              doc.save('dashboard.pdf');
           }
}

We can search for the DOM element with a specific id, capture it as a png image and add it to a landscape PDF file, in this case with a unit measure in mm.

I added this feature to NextReports Charts library with an example in main-test.html.



Here I tested for creating a pdf file with the full dashboard on a landscape page and for creating a pdf file with every widget on a different page.

In first case I do the following:

            var list = $('#dashboard');
            var pdfSettings = new Object();
            pdfSettings.doc = doc;
            pdfSettings.elements = list;
            pdfSettings.title = "NextReports Dashboard";
            capturePdf(pdfSettings);

This will create a nice PDF page:


In second case I look for all canvas elements in my HTML:

            var list = $('canvas[id^="canvas"]');           
            var pdfSettings = new Object();
            pdfSettings.doc = doc;
            pdfSettings.elements = list;
            pdfSettings.position = 1;
            pdfSettings.title = "NextReports Dashboard";
            pdfSettings.showFooter = true;    
            capturePdf(pdfSettings); 

By default a footer message will show the current page:


Footer message can be modified by:

pdfSettings.footerText = "Generated by NextReports"; 

We need to specify the position as 1 because the method is recursive and position is incremented for every new page.

This solution has a drawback. html2canvas library can take a snapshot of what is visible, if there is a scroll involved and some components are not visible, they will not be captured. NextReports Server uses this pdf capture for dashboard elements. To make an entire dashboard visible inside PDF capture, users can play with application and browser features:

- NextReports Server has buttons to hide some components like dashboards explorer
- Browser F11 button makes it to be visible in full screen
- CTRL+mouse wheel will allow to zoom-in/zoom-out the browser content

Using such tricks we may be able to make our dashboard to fit the visible area and PDF capture to look good.