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
JavaScript is a scripting language that is primarily used to add client-side functionality to an HTML page and to create dynamic web sites. It allows programmatic access to objects within the web browser. JavaScript is also available in PDF viewers such as Adobe Reader. There’s a JavaScript API for PDF documents that extends the core Client-Side JavaScript specification and gives you access to Acrobat and Adobe Reader objects. Initially, JavaScript 1.2 was used. Since Acrobat 5.0, the API is based on JavaScript 1.5. The most recent versions of Acrobat and Adobe Reader (since 8.0) use JavaScript 1.6. If you want to know more about the complete set of objects and functions, you can download the PDFs “Developing Acrobat Applications Using JavaScript” and the “JavaScript for Acrobat API Reference” from the adobe.com site. We’re going to use some of the objects listed in that reference to learn how to introduce JavaScript in a PDF document using iText.
Document-level JavaScript
Listing 1 is an example of a simple script that clears the JavaScript console window, makes it visible, and writes information about the viewer and its version number.
Listing 1 viewer_version.js
console.clear(); console.show(); console.println("Hello"); console.println("You are using: " + app.viewerType); console.println("The version of " + app.viewerType + " is: " + app.viewerVersion);
The console is an object that originally wasn’t available in Adobe Reader—only in Acrobat. It was introduced in Adobe Reader 7.0 to report errors and show messages. In our example, we print the value of the viewerType and viewerVersion property of the application (the app object) to the console.
Figure 1 JavaScript Console Window
Figure 1 shows that I’ve opened the document in Adobe Reader version 9.2. Listing 1 was added to an existing PDF document using the code in listing 2.
Listing 2 AddVersionChecker
PdfReader reader = new PdfReader(HelloWorld.RESULT); PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(RESULT)); stamper.addJavaScript(Utilities.readFileToString(RESOURCE)); stamper.close();
Note that what we’re doing in listing 1 and 2 isn’t very elegant. It works, but the addJavaScript() method should only be used to add JavaScript functions that can be called from a JavaScript action.
JavaScript actions
Suppose you had a day-to-day overview of all the movies that are screened at a festival. Let’s say the movies are sorted by date and time, but you’d like to offer extra functionality that allows the end user to search for the occurrence of a specific director in the document. See figure 2.
Figure 2 Search window in Adobe Reader
This can be achieved with the search object using code in listing 3.
Listing 3 find_director.js
function findDirector(name) { if (search.available) { search.query(name, "ActiveDoc"); } else { app.alert("The Search plug-in isn't installed."); } }
Note that we first check for the availability of the Search plug-in, because we mustn’t assume that the plug-in is installed in every PDF viewer. If the plug-in is missing, we inform the end user that searching for directors won’t work using the method app.alert(). This method is similar to the alert() method in plain JavaScript. The viewer application opens an alert box showing the String that is passed to the method.
FAQ
Why are some of the methods I’ve found in the API documentation not working? If you look for the query() method in the API documentation provided by Adobe, you’ll see that the method is marked with a red “S”. This means that the usage of the method can be restricted because of security reasons. Some methods only work in the full Acrobat application and not in the free Reader. Or, they are only supposed to work when the document is certified or reader enabled. Please check the “JavaScript for Acrobat API Reference” before reporting problems with JavaScript.
In listing 4, we’re calling the method shown in listing 3 from an action.
Listing 3 find_director.js
public void createPdf(String filename) ... PdfReader[] readers = { new PdfReader(baos.toByteArray()), A new PdfReader(NestedTables.RESULT) }; B Document document = new Document(); PdfCopy copy = new PdfCopy(document, new FileOutputStream(filename)); C document.open(); copy.addJavaScript(Utilities.readFileToString(RESOURCE)); 1 int n; for (int i = 0; i < readers.length; i++) { n = readers[i].getNumberOfPages(); for (int page = 0; page < n; ) { copy.addPage(copy.getImportedPage(readers[i], ++page)); } } document.close(); } public Paragraph createDirectorParagraph(PdfWriter writer, ResultSet rs) throws UnsupportedEncodingException, SQLException { String n = new String(rs.getBytes("name"), "UTF-8"); Chunk name = new Chunk(n); name.setAction(PdfAction.javaScript( 2 String.format("findDirector('%s');", n), writer)); 2 name.append(", "); name.append(new String(rs.getBytes("given_name"), "UTF-8")); return new Paragraph(name); }
A A new document with the search actions B The original document C Concatenates the two documents 1 Adds the js function to the document 2 Creates an action that uses the function
We add the function findDirector(name) as document-level JavaScript #1. We use that function in the first document in actions that are triggered when the end user clicks on the name of a director #2.
Summary
This article discussed some of the interactive features that can be added to a document. We found out that there are other types of actions besides link actions, for instance JavaScript actions. We’ve used this knowledge to create a search feature.