PDF In-Depth

Automatic Insertion of Document-Level JavaScripts

May 11, 2001

Advertisement
Advertisement
 

Introduction

In an earlier article written for Planet PDF, I discussed a convenient technique for inserting document-level JavaScripts into a PDF file. That technique is useful if the PDF file has already been built and you want to reuse some standard scripts. If the document, however, has to be rebuilt from a source document (Microsoft Word or Adobe FrameMaker, for example), the scripts need to be re-introduced into the newly distilled document. If there are many revisions, this method becomes a bit tiresome.

Acrobat 5 provides a new technique for automatically introducing document-level JavaScripts into the freshly distilled document. The key to this new technique is the extended specification of FDF. As documented in Adobe's Technical Note 5409: "Portable Document Format -- Changes from Versions 1.3 to 1.4." In the section entitled "JavaScript and FDF," page 61 (page 63, base 0), the new specification indicates that FDF can now contain JavaScript. This JavaScript code can be either document-level JavaScript, or JavaScript that is executed when the FDF is imported into the document. It is the document-level specification that is of interest here.

Inserting JS into an FDF

Suppose we wish to insert a couple of functions at the document-level. First, write and test the functions you need. Next, insert them into an FDF file. This following example illustrates how to do this.

Example 1: dljs.fdf

%FDF-1.2
1 0 obj
<<
/FDF
  <<
   /JavaScript << /Doc 2 0 R >>
  >>
>>
endobj
2 0 obj
[ (myHello) (function myHello() {app.alert("Hello World")})
(myWelcome) 3 0 R
]
endobj
3 0 obj
<<
>>
stream
function myWelcome()
{
app.alert("A. C. Robat welcomes you!");
}
endstream
endobj
trailer
<<
/Root 1 0 R
>>
%%EOF

The above script defines two document-level functions, myHello() and myWelcome(), using the two styles defined in the specification. The /JavaScript key is added at the root level of the FDF, its value is a dictionary. This dictionary can contain a /Doc key (and its value), a /Before key (and value) or an /After key (and its value). The latter two will be discussed briefly later.

The value of the /Doc key can be an indirect reference to an array of document level JavaScripts containing an even number of elements. The even elements are script names (e.g., myHello and myWelcome) and the odd elements are strings or streams containing scripts.

IMPORTANT: Typically you would save your FDF file, I'll call mine dljs.fdf, to the folder into which you plan to save your PDF file.

The Insertion Mechanism

When you import this file into your PDF document using File > Import > Form Data from Acrobat 5's menu system, the scripts will be added in at the document level. This provides an alternate way of introducing document-level JavaScript that supersedes the technique described in my previous article cited above. However, the title of the article suggested the automatic insertion of scripts from an authoring document.

The key to automatic insertion of the JavaScript is the Acrobat JavaScript method Doc.importAnFDF(). Insert an open page action into your source document using either raw postscript pdfmark commands, or the EPS method. The second method is appropriate for, say, Microsoft Word or Adobe FrameMaker.

Consider the following code.

Example 2: importAnFDF.eps

%!PS-Adobe-3.0 EPSF-3.0
%%BoundingBox: 0 0 1 1

systemdict /pdfmark known not
   {userdict /pdfmark systemdict /cleartomark get put } if

[ {Page1} << /AA << /O << /S /JavaScript
/JS (if (typeof myHello == "undefined")\r
\tthis.importAnFDF("dljs.fdf");)
>> >> >>
/PUT pdfmark
%EOF

Save the above code as an EPS file, say, as importAnFDF.EPS. Insert this EPS file into the source document near the top of the file using appropriate methods for your authoring application.

This script will create an open page action action on the first page of the PDF document. If the function myHello is undefined, the Doc method this.importAnFDF("dljs.fdf") will import the FDF file dljs.fdf when the document is first opened in Acrobat, usually following the distillation step. Once imported, you can save the document, the document-level JavaScript will be saved as well. The next time the document is opened, the function myHello is already defined, so the open page action does nothing. If you wish, you can delete the open page action after the file has been saved with the JavaScripts contained within.

When Acrobat opens the document for the first time it must be able to find the dljs.fdf file; otherwise, an exception is thrown. Consequently, distiller must save the PDF file in the folder that contains dljs.fdf. An alternate strategy is to specify an absolute path to the FDF file as the argument for the importAnFDF() method.

Another Insertion Mechanism: Batch Processing

FDF can also be used to insert document-level JavaScript into each of a selection of PDF documents using the batch processing feature.

Create a new "Execute JavaScript" batch sequence, perhaps called "Insert DLJS." This batch sequence would have a single JavaScript line:

this.importAnFDF("/c/dljs.fdf");

where the argument of the importAnFDF is the device independent path to the FDF containing the document level JavaScript.

Running this batch on a selection of files would automatically insert the script defined in the FDF into each of the documents.

Note that if the name of a script being inserted is the same as the name of one of the scripts already present in one or more of the files, the new scripts will overwrite the scripts with the same script name.

The Before and After Keys

These two keys may be of use to some developers. We modify Example 1 above to include an /After key:

Example 3

%FDF-1.2
1 0 obj
<<
/FDF
  <<
   /JavaScript
      << 
         /Doc 2 0 R 
       /After (myWelcome();)
      >>
  >>
>>
endobj
2 0 obj
[ (myHello) (function myHello() {app.alert("Hello World")})
(myWelcome) 3 0 R
]
endobj
3 0 obj
<<
>>
stream
function myWelcome()
{
app.alert("A. C. Robat welcomes you!");
}
endstream
endobj
trailer
<<
/Root 1 0 R
>>
%%EOF

The /After (/Before) key will cause Acrobat to execute the script as referenced after (respectively, before) the FDF gets imported. Here, in Example 3, we execute the myWelcome() function after the FDF is imported; in this case, myWelcome is in memory, and can be executed.

The above illustration of /After is not very useful; these keys, however, can be useful for configuring an PDF by importing an FDF and executing the specified script. This may be specially useful for another new feature of Acrobat 5, namely, on-line commenting.

Concluding Comment

I have used these techniques in my own work, that of creating interactive quizzes, both multiple choice and fill in the blank In this type of application, many quizzes need to be generated, document-level JavaScript for marking and correcting the quizzes, must be inserted each time. Once set up properly, using the techniques outlined above, the JavaScripts are seamlessly and painlessly inserted into the document as it is opened in Acrobat. The new document is immediately ready for testing (quizzing! :-).

PDF In-Depth Free Product Trials Ubiquitous PDF

Debenu Quick PDF Library

Get products to market faster with this amazing PDF developer SDK. Over 900 functions and an equally...

Download free demo

Back to the past, 15 years ago! Open Publish 2002

Looking back to 2002, it's amazing how much of the prediction became a reality. Take a read and see what you think!

September 14, 2017
Platinum Sponsor





Search Planet PDF
more searching options...
Planet PDF Newsletter
Most Popular Articles
Featured Product

Debenu PDF Aerialist

The ultimate plug-in for Adobe Acrobat. Advanced splitting, merging, stamping, bookmarking, and link control. Take Acrobat to the next level.

Features

Adding a PDF Stamp Comment

OK, so you want to stamp your document. Maybe you need to give reviewers some advice about the document's status or sensitivity. This tip from author Ted Padova demonstrates how to add stamps with the Stamp Tool along with related comments.