This article is based on iText in Action, Second Edition, published on October, 2010. It is being reproduced here by permission from Manning Publications. Manning publishes MEAP (Manning Early Access Program,) eBooks and pBooks. MEAPs are sold exclusively through Manning.com. All pBook purchases include free PDF, mobi and epub. When mobile formats become available all customers will be contacted and upgraded. Visit Manning.com for more information. [ Use promotional code ‘java40beat’ and get 40% discount on eBooks and pBooks ]
also read:
- Java Tutorials
- Java EE Tutorials
- Design Patterns Tutorials
- Java File IO Tutorials
Introduction
Imagine the following situation: you have a catalogue with thousands of items stored in a database. People can purchase these items online using a PDF form. How will you create that form? Surely, you don’t want to embed your complete article database in a choice field inside your PDF. It would be much easier to provide browse or search functionality in an HTML page and then find a way to pass this data from the HTML pages to the PDF form.
Figure 1 shows an HTML page with a form and an embedded PDF document. The HTML form has two fields and a button. If you fill out a name and login and click the button, the values entered in the fields are passed as a message to the PDF document. The PDF document accepts these values and fills out the corresponding fields in the AcroForm.
Figure 1 JavaScript communication between HTML and PDFPassing the values in the opposite direction is also possible. If you change the name and login in the PDF form and click the button “POST TO HTML”, the entries are passed from the PDF form to the HTML form.
Listing 1 javascript.html
<html> <head> <script language="javascript"> function createMessageHandler() { 1 var PDFObject = document.getElementById("myPdf"); 1 PDFObject.messageHandler = { 1 onMessage: function(msg) { 1 document.personal.name.value = msg[0]; 1 document.personal.loginname.value = msg[1]; 1 }, 1 onError: function(error, msg) { 1 alert(error.message); 1 } 1 } 1 } 1 function sendToPdf() { 2 var PDFObject = document.getElementById("myPdf"); 2 if(PDFObject!= null){ 2 PDFObject.postMessage( 2 [document.personal.name.value, 2 document.personal.loginname.value]); 2 } 2 } 2 </script> </head> <body onLoad="createMessageHandler();"> <form name="personal"> A <table> A <tr> A <td>Name:</td> A <td><input type="Text" name="name"></td> A <td>Login:</td> A <td><input type="Text" name="loginname"></td> A <td><input type="Button" value="Send to PDF" A onClick="return sendToPdf();"></td> A </tr> A </table> A </form> A <object id="myPdf" type="application/pdf" data="javascript.pdf" B height="100%" width="100%"></object> B </body> </html> 1 JavaScript to get data from the PDF 2 JavaScript to send data to the PDF A The HTML form B Embedding the PDF as an object
Embedding a PDF document as an HTML object
Let’s start by looking at the HTML side of this functionality. Listing 1 shows the JavaScript that is needed to accept the data from the PDF and how to embed the PDF inside the HTML page.
In listing 1, the PDF is treated as an object. If we give it an id, for instance myPdf, we can create a variable using document.getElementById(“myPdf”). We use this variable in #1 to accept data from the PDF and, in #2, to send data to the PDF.
HTML-to-PDF communication
The JavaScript method sendToPdf() is triggered when the end user clicks the button in the HTML form. It passes a message to the PDF object. This message is of an array of String values. It will only be accepted if the PDF is “disclosed” and if there’s a message handler in place. The JavaScript code shown in listing 2 was added as an Open action to the document javascript.pdf.
Listing 2 post_from_html.js
this.disclosed = true; 1 if (this.external && this.hostContainer) { 2 function onMessageFunc( stringArray ) { 3 var name = this.myDoc.getField("personal.name"); 3 var login = this.myDoc.getField("personal.loginname"); 3 try{ 3 name.value = stringArray[0]; 3 login.value = stringArray[1]; 3 } 3 catch(e){ 3 onErrorFunc(e); 3 } 3 } 3 function onErrorFunc( e ) { 4 console.show(); 4 console.println(e.toString()); 4 } 4 try { if(!this.hostContainer.messageHandler); 5 this.hostContainer.messageHandler = new Object(); 5 this.hostContainer.messageHandler.myDoc = this; 5 this.hostContainer.messageHandler.onMessage = onMessageFunc; 5 this.hostContainer.messageHandler.onError = onErrorFunc; 5 this.hostContainer.messageHandler.onDisclose = function(){ 5 return true; 5 }; 5 } catch(e){ onErrorFunc(e); } } 1 Disclose the PDF document 2 Check if the PDF is opened in a host container 3 Function that handles incoming messages 4 Function that handles errors 5 Create the message handler
JavaScript communication between documents is only possible if the document is disclosed (#1). You also need to check if the document is opened in an external window. If so, you need access to the host container (#2). In this case, the host container is the web browser.
Note
The hostContainer property doesn’t work on the Mac OS system. Because of that limitation, this example may not work for you or for a segment of your customers.
The code in #5 creates a message handler for the host container. It also defines a function to handle messages (#3) and errors (#4). The method postMessage() in #2 of listing 2 passes a message to the onMessage method of the messageHandler. In our implementation, the first entry in the message array is used to fill in the field personal.name, the second entry to fill in the field personal.loginname. Now, let’s take a look at the communication in the opposite direction.
PDF-to-HTML communication
When an end user clicks on the “POST TO HTML” button in the PDF document, the following JavaScript snippet is executed.
Listing 3 post_to_html.js
if(this.hostContainer) { var names = new Array(); names[0] = this.getField("personal.name").value.toString(); names[1] = this.getField("personal.loginname").value.toString(); try{ this.hostContainer.postMessage(names); } catch(e){ app.alert(e.message); } }
In listing 3, we check if the PDF is opened in a host container. If it is, we put the values we want to transmit to the HTML JavaScript in an array and we use the postMessage() method of the host container. This message will only be accepted if there’s a message handler in place for the PDF object. This message handler is created in the createMessageHandler() (#1 in listing 1) that was triggered when the HTML page was loaded; see the onLoad attribute of the body tag. This method is similar to what we did in listing 2. The onMessage:function accepts an array of String values. In our implementation, these values are used to fill out fields in the HTML form.
This example was a little bit out of scope for learning about iText. You’ll find more information about HTML-to-PDF communication (and vice-versa) in the “JavaScript for Acrobat API Reference” (http://www.adobe.com/devnet/acrobat/javascript.html).
Summary
In this article, we’ve used a PDF form to demonstrate how to establish the communication between a PDF document and its host container, the web browser. We’ve sent messages back and forth between an HTML page and a PDF document.