The goal
I have a web page that generates a report. The report is displayed in the modal pop-up DIV and I need to give user option to generate PDF version of the pop-up. App is heavily AJAXed and is using JSF/facelets on the background and lots of JQuery on the client. Matter of fact – the content of pop-up is not produced directly by the server but rather preview is generated, then user selects which rows in report table she needs and only then the pop-up is populated using partially filtered markup from the preview report. So, now you can forget what I just said and remember only that I want to generate PDF out of some HTML code on my page.
Design
- Capture HTML snippet and send it to the server
- Make valid XHTML out of HTML snippet
- Provide valid CSS
- Convert HTML/CSS to XSL-FO
- Generate PDF
- Prompt user to save generated PDF
As a side note – this method is best suitable for relatively small content – no more than few screens
Components
- JQuery (client)
- css2xslfo
- Apache FOP
Process
Capture HTML
This is done in your JavaScript on the client. In my case right in the report.xhtml page code.
$(document).ready(function(){
$('button#pdf').click(function(){
report.generatePdf({
trigger: $(this),
content : $('#genReportContent').html(),
css : ['/myapp/css/pdfExport.css']});
});
});
As you can see I’m passing innerHTML of element (DIV) with ID=genReportContent. I found it important to pass not the element itself since I need to do some further modifications to the submitted markup and I don’t want anything to change on the page as a result. This is a pretty typical JQuery syntax.
Also note that I’m passing in the button that triggered the event and location(s) of the external CSS files I want to use to format the HTML snippet. Now – you can choose to pass actual CSS files that are used to format the content on the originating page but I found out that having a dedicated stylesheet is probably a better idea.
Now to the actual generatePdf method:
/**
* Calls PdfServlet and passes generated report for PDF conversion
*/
generatePdf : function(options) {
var wrapper = $('
');
var div = $('
').html(options.content);
wrapper.append(div);
// remove any non-visible elements
wrapper.find('.removeInReport').remove();
wrapper.find('#footerCell').attr('colspan', '6');
var content = escape(wrapper.html());
// generate form and submit since ajax will not load binary
var form = $('
Posted in Web stuff.
– January 26, 2009
Ok, I am missing something, or I am doing it wrong. There seems to be holes either in the example or in my head. Can I download the whole thing?