data-id=javascript-contexts-in-acrobat

JavaScript Contexts in Acrobat

JavaScript for Acrobat can be placed in a variety of locations, both external to the document, and within the document. This chapter discusses how to determine the appropriate location for a script, and how to create and access the scripts.

data-id=40979
data-id=the-concept-of-a-javascript-event

The concept of a JavaScript event

All scripts are executed in response to a particular event. There are several types of events:

These types of events may be initiated, or triggered, in a number of different ways, for example, in response to a mouse up, a mouse down, a keystroke, on focus, or on blur. These are referred to by the Acrobat JavaScript API Reference as the event names. Event types and names appear in pairs. For example, if an action is initiated by clicking a button, this would generate a Field type event, triggered by a mouse up event; consequently, we refer to such an event as a field/mouse up event.

The table that follows lists all event type/name combinations.

Event type/name combinations

Event type
Event names
App
Init
Batch
Exec
Bookmark
Mouse Up
Console
Exec
Doc
DidPrint, DidSave, Open, WillClose, WillPrint, WillSave
External
Exec
Field
Blur, Calculate, Focus, Format, Keystroke, Mouse Down, Mouse Enter, Mouse Exit, Mouse Up, Validate
Link
Mouse Up
Menu
Exec
Page
Open, Close
Screen
InView, OutView, Open, Close, Focus, Blur, Mouse Up, Mouse Down, Mouse Enter, Mouse Exit

An event manifests itself in JavaScript as an Event object. Complete documentation for the different event types of events and the ways in which they can be triggered can be found in the description of the Event object in the Acrobat JavaScript API Reference.

data-id=62945
data-id=about-contexts

About contexts

JavaScript for Acrobat can be placed at a variety of levels:

Each of these levels represents a context, or location, in which processing occurs. The list above is by no means a complete list of locations at which scripts can be placed.

The placement of a script at a given level determines its reusability. Folder level scripts are available within all documents, document level scripts are available to all form fields within a given document, field level scripts are visible to the form fields with which they are associated.

Note

For instructions on how to disallow changes to scripts or hide scripts, see Disallowing changes in scripts and Hiding scripts.

data-id=11693
data-id=folder-level

Folder level

Folder level scripts contain variable declarations and function definitions that may be generally useful to Acrobat, and are visible from all documents. Top level scripts, ones that are not contained in a function definition, are executed when the application is initialized.

There are two kinds of folder level scripts: App and User. For example, if you would like to add specialized menus and menu items to be available to all documents opened in Acrobat, you can store the code at the folder level.

Folder level scripts are placed in separate files that have the .js extension. App folder level scripts are stored in the Acrobat application’s JavaScripts folder, and user folder level scripts are stored in the user’s JavaScripts folder. These scripts are loaded when Acrobat starts execution, and are associated with the event object’s Application Initialization.App/Init) event.

Note

The locations of these folders can be found by executing the following lines in the JavaScript Debugger Console:

// for App folder scripts
app.getPath("app", "javascript");
// for User folder scripts
app.getPath("user", "javascript");

When Acrobat is installed on your machine, it provides you with several standard folder level JavaScript files, including JSByteCodeWin.bin (this file is a pre-compiled script that supports the forms and annotation plug-ins) and debugger.js ; these are in the App folder. Other JavaScript files in the App folder may be installed by third-party Acrobat plug-in developers.

The user folder may contain the files glob.js and config.js. The glob.js file is programmatically generated and contains cross-session global variables set using the global object’s setPersistent method. The config.js file is used to set user preferences or to customize the viewer UI by adding toolbar buttons or menu items. (See Adding toolbar buttons and menu items for more information on this topic.) Any file with an extension of .js found in the user folder is also loaded by Acrobat during initialization, after it has loaded the files found in the App folder, and after it has loaded the config.js and global.js files.

To create folder level scripts, use an external editor running in parallel to Acrobat. Note that the external editor cannot be invoked from Acrobat for folder level scripts.

data-id=63210
data-id=document-level

Document level

Document level scripts are variable and function definitions that are generally useful to a given document, but are not applicable outside the document.

var defaultUserColor = "red";

The variable defined above, which has an initial value of "red", may be changed as the user interacts with the document.

To create or access document level scripts in Acrobat, select Tools pane > JavaScript > Document JavaScript, which enables you to add, modify, or delete document level scripts. Document level scripts are executed after the document has opened, but before the first Page Open event (See Page level). They are stored within the PDF document.

You can also create Doc level scripts programmatically using the addScript method of the Doc object.

In addition to document level scripts, there are document action scripts that execute when certain document events occur. Such document events are

To access the JavaScript Editor for each of these document actions, select Tools pane > JavaScript > Set Document Action.

You can also create the document actions just described programmatically using the setAction method of the Doc object.

data-id=11553
data-id=page-level

Page level

Page level scripts are scripts that are executed when a particular page is either closed or opened.

Other actions, as listed in the Select Action Menu of the Page Properties dialog box, can be created, accessed and deleted in the same way.

Page level scripts can also be created programmatically using the setPageAction method of the Doc object.

data-id=35244
data-id=field-level

Field level

Field level scripts are associated or attached to an Acrobat form field. Field events occur as the user interacts with the field, either directly or indirectly. Field scripts are typically executed to validate, format, or calculate form field values. Like document level scripts, field level scripts are stored within the PDF document.

There are several ways to create or edit field level scripts. The most straightforward manner is to right-click the form field, select the Properties context menu item and choose the Actions tab. Choose Run a JavaScript for Select Action and choose how to trigger the script from the Select Trigger Menu.

Field level scripts can also be created programmatically using the setAction method of the Field object.

data-id=76421
data-id=privileged-versus-non-privileged-context

Privileged versus non-privileged context

Some JavaScript methods have security restrictions. These methods can be executed only in a privileged context which includes console, batch, and application initialization events. All other events (for example, page open and mouse-up events) are considered non-privileged. In the Acrobat JavaScript API Reference, methods with security restrictions are marked by an S in the third column of the quick bar.

The description of each security-restricted method indicates the events during which the method can be executed.

Beginning with Acrobat 6.0, security-restricted methods can execute in a non-privileged context if the document is certified by the document author for embedded JavaScript.

Security-restricted methods can also execute in a non-privileged context through the use of a trusted function introduced in Acrobat 7.0).

In Acrobat versions earlier than 7.0, menu events were considered privileged contexts. Beginning with Acrobat 7.0, execution of JavaScript through a menu event is no longer privileged. You can execute security-restricted methods through menu events in one of the following ways:

data-id=30303
data-id=executing-privileged-methods-in-a-non-privileged-context

Executing privileged methods in a non-privileged context

To illustrate the techniques required, let’s work with a specific method, app.browseForFile. According to the Acrobat JavaScript API Reference, this method can only be executed during batch or console events. This means that we are free to executed this method in the console, or to use it as a part of a batch sequence.

What happens when we execute this method in a non-privileged context? Create an Acrobat form button, and attach the following script as a mouse up JavaScript action.

var oRetn = app.browseForDoc({bSave: true});

After clicking the button, an exception is thrown; the console displays the following message:

NotAllowedError: Security settings prevent access to this property or method.
app.browseForDoc:1:Field Button1:Mouse Up

This shows that we have violated the documented security restriction.

If we really want this method in our workflow what do we need to do? We need to move this method to folder JavaScript and declare it as a trusted function. Why move it to the folder context? Because you can only declare a function trusted from a folder (console or batch) context.

Navigate to the user JavaScript folder and open the file config.js in your text editor. Paste the following script into config.js :

myTrustedBrowseForDoc = app.trustedFunction( function ( oArgs )
{
   app.beginPriv();
       var myTrustedRetn = app.browseForDoc( oArgs );
   app.endPriv();
   return myTrustedRetn;
});

For the syntax details of app.trustedFunction, see the JavaScript for Acrobat API Reference. Note that the privileged script must be enclosed by the app.beginPriv and app.endPriv pair.

Save the file and restart Acrobat (folder JavaScript is read only at startup).

Now create a PDF with a single button on it. The script for that button is

try {
        var oRetn = myTrustedBrowseForDoc({bSave: true});
        console.println(oRetn.toSource());
} catch(e) {
    console.println("User cancelled Save As dialog box");
}

Clicking the button now executes the app.browseForDoc method without throwing the security exception.

In this example, we use the app.browseForDoc and the Doc.saveAs methods, both of which have security restrictions.

In config.js, paste both the myTrustedBrowseForDoc script listed above, and paste this script:

myTrustedSaveAs = app.trustedFunction( function ( doc, oArgs )
{
   app.beginPriv();
       var myTrustedRetn = doc.saveAs( oArgs );
   app.endPriv();
   return myTrustedRetn;
});

Note that the Doc object is passed to this trusted function. Now, revise the button described above to read as follows:

try {
   var oRetn = myTrustedBrowseForDoc({bSave: true});
   try {
           myTrustedSaveAs(this, { cPath: oRetn.cPath, cFS:oRetn.cFS });
       } catch(e) { console.println("Save not allowed, perhaps readonly."); }
   } catch(e) { console.println("User cancelled Save As dialog box");}

Now, the PDF document, through a mouse up button action, can open a Save As dialog box and save the current document.

data-id=40133
data-id=executing-privileged-methods-through-the-menu

Executing privileged methods through the menu

In versions of Acrobat previous to 7.0, executing JavaScript through a menu was non-privileged. This is no longer the case. To execute privileged JavaScript through a menu event there are now two choices:

  1. Ask the user to enable the Enable Menu Items JavaScript Execution Privileges option, in the JavaScript section of the Preferences.
  2. Use the trusted function approach discussed above.

In this section we discuss the first alternative.

Open config.js, found in the user’s JavaScript folder, and paste the following script:

app.addSubMenu({ cName: "New", cParent: "File", nPos: 0 })
app.addMenuItem({ cName: "Letter", cParent: "New", cExec: "app.newDoc();"});
app.addMenuItem({ cName: "A4", cParent: "New", cExec: "app.newDoc(420,595)"});

As usual, restart Acrobat so that the config.js file is read. Under the File menu, there is now a menu item named New, with a sub menu with two items, Letter and A4.

With the Enable Menu Items JavaScript Execution Privileges option not enabled, upon the execution of one of these menu items, either File > New > Letter or File > New > A4 are executed, an alert box appears declaring that “An internal error occurred”, and the console shows the following error message:

1:Menu Letter:Exec
NotAllowedError: Security settings prevent access to this property or method.
app.newDoc:1:Menu Letter:Exec

The problem is app.newDoc, a method that has a security restriction.

Now enable the Enable Menu Items JavaScript Execution Privileges option and execute the same menu item again, a new document is created, the menu operates as designed.

The above discussion shows what happens when you try to executed a privileged method through the menu system and how to work around the restrictions on privileged methods by enabling the Enable Menu Items JavaScript Execution Privileges option of the JavaScript section of the Preferences.

A note of caution. An Acrobat developer, cannot assume the user has enabled the JavaScript execution privileges options; indeed, in a corporate setting, enabling this option may not be allowed for security reasons. An Acrobat developer using JavaScript should perhaps use the trusted function approach, as discussed in Executing privileged methods in a non-privileged context, which necessarily implies the installation of folder JavaScript on the user’s system.

data-id=executing-privileged-methods-in-a-certified-document

Executing privileged methods in a certified document

Many of the JavaScript methods in Acrobat are restricted for security reasons, and their execution is only allowed during batch, console or menu events. This restriction is a limitation when enterprise customers try to develop solutions that require these methods and know that their environment is secure.

Three requirements must be met to make restricted JavaScript methods available to users.

For details on where you can obtain digital IDs and the procedures for using them to sign documents, see Acrobat Help.

For details, see Acrobat Help.

All trusted certificates can be accessed by selecting Certificates from Preferences > Signatures > Identities & Trusted Certificates > more in the Acrobat main menu.