Js Developer Guide
Js Developer Guide
Js Developer Guide
2006 Adobe Systems Incorporated. All rights reserved. Adobe Acrobat SDK 8.0 Developing Acrobat Applications Using JavaScript for Microsoft Windows and Mac OS. Edition 1.0, November 2006 If this guide is distributed with software that includes an end user agreement, this guide, as well as the software described in it, is furnished under license and may be used or copied only in accordance with the terms of such license. Except as permitted by any such license, no part of this guide may be reproduced, stored in a retrieval system, or transmitted, in any form or by any means, electronic, mechanical, recording, or otherwise, without the prior written permission of Adobe Systems Incorporated. Please note that the content in this guide is protected under copyright law even if it is not distributed with software that includes an end user license agreement. The content of this guide is furnished for informational use only, is subject to change without notice, and should not be construed as a commitment by Adobe Systems Incorporated. Adobe Systems Incorporated assumes no responsibility or liability for any errors or inaccuracies that may appear in the informational content contained in this guide. Please remember that existing artwork or images that you may want to include in your project may be protected under copyright law. The unauthorized incorporation of such material into your new work could be a violation of the rights of the copyright owner. Please be sure to obtain any permission required from the copyright owner. Any references to company names and company logos in sample material are for demonstration purposes only and are not intended to refer to any actual organization. Adobe, the Adobe logo, Acrobat, After Effects, FrameMaker, Illustrator, LiveCycle, Photoshop, PostScript and Reader are either registered trademarks or trademarks of Adobe Systems Incorporated in the United States and/or other countries. Apple and Mac OS are trademarks of Apple Computer, Inc., registered in the United States and other countries. JavaScript is a trademark or registered trademark of Sun Microsystems, Inc. in the United States and other countries. Microsoft and Windows are either registered trademarks or trademarks of Microsoft Corporation in the United States and/or other countries. All other trademarks are the property of their respective owners. Adobe Systems Incorporated, 345 Park Avenue, San Jose, California 95110, USA. Notice to U.S. Government End Users. The Software and Documentation are Commercial Items, as that term is defined at 48 C.F.R. 2.101, consisting of Commercial Computer Software and Commercial Computer Software Documentation, as such terms are used in 48 C.F.R. 12.212 or 48 C.F.R. 227.7202, as applicable. Consistent with 48 C.F.R. 12.212 or 48 C.F.R. 227.7202-1 through 227.7202-4, as applicable, the Commercial Computer Software and Commercial Computer Software Documentation are being licensed to U.S. Government end users (a) only as Commercial Items and (b) with only those rights as are granted to all other end users pursuant to the terms and conditions herein. Unpublished-rights reserved under the copyright laws of the United States. Adobe Systems Incorporated, 345 Park Avenue, San Jose, CA 95110-2704, USA. For U.S. Government End Users, Adobe agrees to comply with all applicable equal opportunity laws including, if appropriate, the provisions of Executive Order 11246, as amended, Section 402 of the Vietnam Era Veterans Readjustment Assistance Act of 1974 (38 USC 4212), and Section 503 of the Rehabilitation Act of 1973, as amended, and the regulations at 41 CFR Parts 60-1 through 60-60, 60-250, and 60-741. The affirmative action clause and regulations contained in the preceding sentence shall be incorporated by reference.
Contents
Contents ....................................................................................................................................... 3 List of Examples ......................................................................................................................... 10 Preface ........................................................................................................................................ 12
Whats in this guide? ...................................................................................................................................................................12 Who should read this guide? ...................................................................................................................................................12 About the sample scripts...........................................................................................................................................................12 Related documentation .............................................................................................................................................................13
Introduction ............................................................................................................................... 14
Overview..........................................................................................................................................................................................14 Reading the JavaScript for Acrobat API Reference ..........................................................................................................15 Object summary ...........................................................................................................................................................................16 app...............................................................................................................................................................................................16 Doc ..............................................................................................................................................................................................16 dbg ..............................................................................................................................................................................................17 console.......................................................................................................................................................................................17 global..........................................................................................................................................................................................17 util................................................................................................................................................................................................18 dialog..........................................................................................................................................................................................18 security.......................................................................................................................................................................................18 SOAP ...........................................................................................................................................................................................18 search .........................................................................................................................................................................................18 ADBC...........................................................................................................................................................................................19 event...........................................................................................................................................................................................19 JavaScript applications...............................................................................................................................................................19
Tools ........................................................................................................................................... 21
Using the JavaScript Debugger console..............................................................................................................................21 Opening the console ............................................................................................................................................................22 Executing JavaScript .............................................................................................................................................................22 Formatting code.....................................................................................................................................................................22 Enabling JavaScript ...............................................................................................................................................................22 Debugging with the JavaScript Console.......................................................................................................................24 Using a JavaScript editor ...........................................................................................................................................................24 Specifying the default JavaScript editor ..............................................................................................................................25 Using an external editor.............................................................................................................................................................26 Additional editor capabilities ............................................................................................................................................26 Specifying additional capabilities to your editor .......................................................................................................26 Saving and closing a file with a syntax error................................................................................................................28 Using the Debugger with Adobe Reader ............................................................................................................................28 Enabling the JavaScript Debugger ........................................................................................................................................29
Contents
4
Tools (Continued)
JavaScript Debugger...................................................................................................................................................................30 Main groups of controls.......................................................................................................................................................30 Debugger View windows....................................................................................................................................................31 Debugger buttons .................................................................................................................................................................32 Debugger Scripts window ..................................................................................................................................................33 Call Stack list ............................................................................................................................................................................35 Inspect details window ........................................................................................................................................................35 Coding styles and breakpoints ...................................................................................................................................37 Listing breakpoints .........................................................................................................................................................38 Using conditional breakpoints ...................................................................................................................................38 Starting the Debugger .........................................................................................................................................................38 Final notes ................................................................................................................................................................................39
Contents
5
Contents
6
Contents
7
Contents
8
12 Security.....................................................................................................................................163
Security essentials ..................................................................................................................................................................... 163 Methods for adding security to PDF documents .................................................................................................... 163 Passwords and restrictions........................................................................................................................................ 163 Certifying documents ................................................................................................................................................. 163 Encrypting files using certificates ........................................................................................................................... 165 Security policies ............................................................................................................................................................ 166 Secure forms................................................................................................................................................................... 166 Digitally signing PDF documents ........................................................................................................................................ 166 Signing a PDF document ................................................................................................................................................. 166 The security handler object............................................................................................................................................. 166 The SignatureInfo object ........................................................................................................................................... 167 Applying the signature............................................................................................................................................... 167 Clearing a digital signature from a signature field ........................................................................................... 168 Getting signature information from another user.................................................................................................. 168 Removing signatures......................................................................................................................................................... 168 Certifying a document ...................................................................................................................................................... 168 Validating signatures......................................................................................................................................................... 169 Setting digital signature properties with seed values........................................................................................... 169 Adding security to PDF documents.................................................................................................................................... 170 Adding passwords and setting security options ..................................................................................................... 170 Adding usage rights to a document ............................................................................................................................ 170 Encrypting PDF files for a list of recipients ................................................................................................................ 171 Encrypting PDF files using security policies .............................................................................................................. 173 Adding security to document attachments .............................................................................................................. 175
Contents
9
12 Security (Continued)
Digital IDs and certification methods ................................................................................................................................ 175 Digital IDs............................................................................................................................................................................... 176 About digital ID providers ......................................................................................................................................... 176 Creating a digital ID (default certificate security) ............................................................................................. 177 Using digital IDs (default certificate security)..................................................................................................... 179 Managing digital IDs (Windows certificate security) ....................................................................................... 179 Managing digital ID certificates..................................................................................................................................... 180 Sharing digital ID certificates ................................................................................................................................... 180 Building a list of trusted identities.......................................................................................................................... 181 Checking information on certificates .................................................................................................................... 181 Task based topics ...................................................................................................................................................................... 182 Disallowing changes in scripts....................................................................................................................................... 182 Hiding scripts........................................................................................................................................................................ 182
Index .........................................................................................................................................213
List of Examples
Example 2.1 Example 3.1 Example 4.1 Example 4.2 Example 4.3 Example 4.4 Example 4.5 Example 4.6 Example 4.7 Example 5.1 Example 5.2 Example 6.1 Example 6.2 Example 6.3 Example 6.4 Example 6.5 Example 6.6 Example 6.7 Example 6.8 Example 6.9 Example 8.1 Example 8.2 Example 8.3 Example 8.4 Example 8.5 Example 8.6 Example 8.7 Example 9.1 Example 9.2 Example 9.3 Example 9.4 Example 9.5 Example 9.6 Example 9.7 Example 10.1 Example 12.1 Test a regular expression in the JavaScript Debugger Console .....................................................................24 Executing privileged methods....................................................................................................................................46 Creating a document with content...........................................................................................................................50 Creating a new document from two other documents ....................................................................................51 Combining several PDF files ........................................................................................................................................51 Combining several files of different formats .........................................................................................................52 Extracting and saving pages........................................................................................................................................52 Saving form data to and reading form data from an attachment .................................................................53 Accessing an XML attachment using E4X...............................................................................................................54 Set up booklet printing for right-side binding of text and print ....................................................................64 Print booklet in duplex mode, printing only the front pages .........................................................................64 Custom script for a combo box ..................................................................................................................................78 Accessing a list from another field ............................................................................................................................80 Accessing individual radio button widgets ...........................................................................................................81 Counting the number of widgets in a radio button field..................................................................................81 Inputting numbers and checking the range in a text field...............................................................................84 Calculating the average of several text fields........................................................................................................85 Highlighting required fields.........................................................................................................................................86 Inserting navigation buttons on each page ..........................................................................................................89 Detecting and classifying XML forms in batch................................................................................................... 105 Customizing the number of repetitions for playback ..................................................................................... 127 Running openPlayer with settings and events as a rendition action ........................................................ 130 Play a clip in full screen............................................................................................................................................... 131 Playing a rendition in a screen annotation from a form button.................................................................. 132 Playing a media clip from a URL.............................................................................................................................. 132 Playing a media clip from a file................................................................................................................................ 133 Playing a sound clip from a URL.............................................................................................................................. 133 Adding a menu item.................................................................................................................................................... 135 Installing and uninstalling a toolbar...................................................................................................................... 136 Add navigation links to the document................................................................................................................. 142 Setting full screen preferences and resetting them......................................................................................... 146 Adding page transitions............................................................................................................................................. 147 Creating a rollover effect ........................................................................................................................................... 150 Toggling a PDF layer.................................................................................................................................................... 151 Gathering personal data using templates........................................................................................................... 155 Certification signature ................................................................................................................................................ 170
10
List of Examples
11
Assigning a name to a 3D annotation................................................................................................................... 208 Rotating a named object in a 3D model .............................................................................................................. 209 Setting the render mode of a 3D model .............................................................................................................. 210 Setting the background color of the canvas on activation ........................................................................... 211
Preface
This guide shows how you can use JavaScript to develop and enhance standard Adobe Acrobat workflows, such as:
Printing and viewing Spell-checking Stamping and watermarking Managing document security and rights Accessing metadata Facilitating online collaboration Creating interactive forms Customizing interaction with web Services Interacting with databases Accessing the 3D JavaScript engine
12
Preface
Related documentation 13
Related documentation
This document refers to the following sources for additional information about JavaScript and related technologies. The Acrobat documentation is available through the Acrobat Family Developer Center, http://www.adobe.com/go/acrobat_developer. For information about A guide to the documentation in the Acrobat SDK. Known issues and implementation details. Answers to frequently asked questions about the Acrobat SDK. New features in this Acrobat SDK release. A general overview of the Acrobat SDK. A guide to the sections of the Acrobat SDK that pertain to Adobe Reader. A guide to the sample code included with the Acrobat SDK. Configuring and administering a system for online collaboration using comment repositories, Acrobat and Adobe Reader. Detailed descriptions of JavaScript APIs for adding interactivity to 3D annotations within PDF documents. Detailed descriptions of JavaScript APIs for developing and enhancing workflows in Acrobat and Adobe Reader. A description of how to convert JavaScript for Acrobat for use in an Adobe LiveCycle Designer form. A detailed description of the PDF file format. Using JavaScript to perform repetitive operations on a collection of files. A description of Acrobat's digital signature capabilities, which document authors can use to create certified documents, signable forms, and custom workflows and appearances. See Acrobat SDK Documentation Roadmap Readme Developer FAQ Whats New Overview Developing for Adobe Reader Guide to SDK Samples Acrobat Online Collaboration: Setup and Administration JavaScript for Acrobat 3D Annotations API Reference JavaScript for Acrobat API Reference Converting Acrobat JavaScript for Use in LiveCycle Designer Forms PDF Reference Batch Sequences Acrobat 8.0 Security User Guide
Introduction
This chapter introduces the JavaScript for Acrobat scripting model and containment hierarchies (its objects), as well as the primary Acrobat and PDF capabilities related to JavaScript usage. Topic Overview Reading the JavaScript for Acrobat API Reference Object summary JavaScript applications Description See
A brief history of JavaScript, its origins in HTML, and its page 14 relevance to Acrobat Discusses important features of the JavaScript for Acrobat such as security restrictions on some of the methods, safe paths and privileged methods. A listing and short description of some objects that play an important role in JavaScript for Acrobat. page 15
page 16
Overview
JavaScript for Acrobat is an extension of core JavaScript, version 1.5 of ISO-16262, formerly known as ECMAScript, an object-oriented scripting language developed by Netscape Communications. JavaScript was created to offload web page processing from a server onto a client in web-based applications. Acrobat extends the core language by adding new objects and their accompanying methods and properties, to the JavaScript language. These Acrobat-specific objects enable a developer to manage document security, communicate with a database, handle file attachments, manipulate a PDF file so that it behaves as an interactive, web-enabled form, and so on. Because the Acrobat-specific objects are added on top of core JavaScript, you still have access to its standard classes, including Math, String, Date, and RegExp. PDF documents have great versatility since they can be displayed both within the Acrobat software as well as a web browser. Therefore, it is important to be aware of the differences between JavaScript used in a PDF file and JavaScript used in a web page:
JavaScript in a PDF file does not have access to objects within an HTML page. Similarly, JavaScript in a web page cannot access objects within a PDF file. In HTML, JavaScript is able to manipulate such objects as Window. JavaScript for Acrobat cannot access this particular object but it can manipulate PDF-specific objects.
Most people know Acrobat as a medium for exchanging and viewing electronic documents easily and reliably, independent of the environment in which they were created; however, Acrobat provides far more capabilities than a simple document viewer. You can enhance a PDF document so that it contains form fields to capture user-entered data as well as buttons to initiate user actions. This type of PDF document can replace existing paper forms, allowing employees within a company to fill out forms and submit them via PDF files, and connect their solutions to enterprise workflows by virtue of their XML-based structure and the accompanying support for SOAP-based web services.
14
Introduction
Reading the JavaScript for Acrobat API Reference 15
Acrobat also contains functionality to support online team review. Documents that are ready for review are converted to PDF. When a reviewer views a PDF document in Acrobat and adds comments to it, those comments (or annotations) constitute an additional layer of information on top of the base document. Acrobat supports a wide variety of standard comment types, such as a note, graphic, sound, or movie. To share comments on a document with others, such as the author and other reviewers, a reviewer can export just the comment "layer" to a separate comment repository. In either of these scenarios, as well as others that are not mentioned here, you can customize the behavior of a particular PDF document, implement security policies, interact with databases and web services, and dynamically alter the appearance of a PDF document by using JavaScript. You can tie JavaScript code to a specific PDF document, a particular page within a PDF document, or a form field or button in a PDF file. When an end user interacts with Acrobat or a PDF file displayed in Acrobat that contains JavaScript, Acrobat monitors the interaction and executes the appropriate JavaScript code. Not only can you customize the behavior of PDF documents in Acrobat, you can customize Acrobat itself. In earlier versions of Acrobat (prior to Acrobat 5), this type of customization could only be done by writing Acrobat plug-ins in a high-level language like C or C++. Now, much of that same functionality is available through Acrobat extensions to JavaScript. You will find that using JavaScript to perform a task such as adding a menu to Acrobats user interface is much easier than writing a plug-in. Using Acrobat Professional, you can create batch sequences for processing multiple documents, processing within a single document, processing for a given page, and processing for a single form field. For batch processing, it is possible to execute JavaScript on a set of PDF files, which enables tasks such as extracting comments from a comment repository, identifying spelling errors, and automatically printing PDF files.
The quick bar: In the JavaScript for Acrobat API Reference, each object, property and method has a quick bar, a one-row table of icons that provides a summary of the items availability and usage recommendations. Many lost hours of time can be avoided by paying attention to this quick bar. Refer to the JavaScript for Acrobat API Reference for details. Privileged context: This guide contains detailed information on executing JavaScript in a privileged context, beyond that provided in JavaScript for Acrobat API Reference, see Privileged versus non-privileged context on page 45. Safe path: Acrobat 6.0 introduced the concept of a safe path for JavaScript methods that write data to the local hard drive based on a path passed to it by one of its parameters. Generally, when a path is judged to be not safe, a NotAllowedError exception is thrown. See the JavaScript for Acrobat API Reference for more information about safe paths.
Note: Many sample scripts presented in this guide reference the local file system. These scripts generally use the path "/c/temp/", which is a safe path.
Introduction
Object summary 16
Object summary
The Acrobat extension to core JavaScript defines many objects that allow your code to interact with the Acrobat application, a PDF document, or form fields within a PDF document. This section introduces you to the primary objects used to access and control the application and document, the development environment itself, and general-purpose JavaScript functionality. Below is a short listing of some of the main objects used in the document and in the sample files. A brief description of each of the objects follow the table. Object
ADBC app console dbg dialog Doc event global search security SOAP util
Purpose Database connections and queries Acrobat JavaScript Debugger Debugger Modal dialog boxes PDF document JavaScript events Persistent and cross-document information Searching and indexing Encryption and digital signatures Web services JavaScript utility methods
app
The app object is a static object that represents the Acrobat application itself. It offers a number of Acrobat-specific functions in addition to a variety of utility routines and convenience functions. By interacting with the app object, you can open or create PDF and FDF documents, and customize the Acrobat interface by setting its viewing modes, displaying popup menus, alerts, and thermometers, displaying a modal dialog box, controlling time intervals, controlling whether calculations will be performed, performing email operations, and modifying its collection of toolbar buttons, menus, and menu items. You can also query app to determine which Adobe product and version the end user is using (such as Adobe Reader 8 or Acrobat Professional 7.0), as well as which printer names and color spaces are available.
Doc
The Doc object is the primary interface to the PDF document, and it can be used to access and manipulate its content. The Doc object provides the interfaces between a PDF document open in the viewer and the JavaScript interpreter. By interacting with the Doc object, you can get general information about the
Introduction
dbg 17
document, navigate within the document, control its structure, behavior and format, create new content within the document, and access objects contained within the document, including bookmarks, form fields, templates, annotations, and sounds. The following graphic represents the containment hierarchy of objects related to the Doc object.
annot
field
sound
bookmark
template
data
Accessing the Doc object from JavaScript can be done in a variety of ways. The most common method is using the this object, which is normally equivalent to the Doc object of the current underlying document.
dbg
You can use the dbg object, available only in Acrobat Professional, to control the JavaScript Debugger from a command line while the application is not executing a modal dialog box. The dbg object methods offer the same functionality as the buttons in the JavaScript debugger dialog box toolbar, which permit stepwise execution, setting, removing, and inspecting breakpoints, and quitting the debugger.
console
The console object is a static object that is used to access the JavaScript console for displaying debug messages and executing JavaScript. It is useful as a debugging aid and as a means of interactively testing code and is only available within Acrobat Professional.
global
The global object is used to store data that is persistent across invocations of Acrobat or shared by multiple documents. Global data sharing and notification across multiple documents is done through a subscription mechanism, which enables monitoring of global variables and reporting of their values to all subscribing documents. In addition, global can be used to store information that pertains to a group of documents, a situation that occurs when a batch sequence runs. For example, batch sequence code often stores the total number of documents to be processed as a property of global. If information about the documents needs to be stored in a Report object, it is assigned to a set of properties within global so it is accessible to the Report object.
Introduction
util 18
util
The util object is a static JavaScript object that defines a number of utility methods and convenience functions for number and date formatting and parsing. It can also be used to convert information between rich content and XML representations.
dialog
The dialog object is an object literal used by the app objects execDialog method to present a modal dialog box identical in appearance and behavior to those used across all Adobe applications. The dialog object literal consists of a set of event handlers and properties which determine the behavior and contents of the dialog box, and may be comprised of the following elements: push buttons, check boxes, radio buttons, list boxes, text boxes, popup controls, and containers and frames for sets of controls.
security
The security object is a static JavaScript object, available without restriction across all Acrobat applications including Adobe Reader, that employs a token-based security model to facilitate the creation and management of digital signatures and encryption in PDF documents, thus providing a means of user authentication and directory management. Its methods and properties are accessible during batch, console, menu, or application initialization events. The security object can be used to add passwords and set security options, add usage rights to a document, encrypt PDF files for a list of recipients, apply and assign security policies, create custom security policies, add security to document attachments, create and manage digital IDs using certificates, build a list of trusted identities, and check information on certificates.
SOAP
The SOAP object can be used to make remote procedure calls to a server and invoke web services described by WSDL, and supports both SOAP 1.1 and 1.2 encoding. Its methods are available from Acrobat Professional, Acrobat Standard, and for documents with form export rights open in Adobe Reader 6.0 or later. The SOAP object makes it possible to share comments remotely and to invoke web services in form field events. It provides support for rich text responses and queries, HTTP authentication and WS-Security, SOAP headers, error handling, sending or converting file attachments, exchanging compressed binary data, document literal encoding, object serialization, XML streams, and applying DNS service discovery to find collaborative repositories on an intranet. In addition the XMLData object can be used to evaluate XPath expressions and perform XSLT conversions on XML documents.
search
The search object is a static object that can be used to perform simple and advanced searches for text in one or more PDF documents or index files, create, update, rebuild, or purge indexes for one or more PDF documents, and search through document-level and object-level metadata. The search object has properties that can be used to fine-tune the query, such as a thesaurus, words with similar sounds, case-sensitivity, and settings to search the text both in annotations and in EXIF metadata contained in JPEG images.
Introduction
ADBC 19
ADBC
The ADBC object is used in conjunction with the connection and statement objects to interface with a database. These objects constitute Acrobat Database Connectivity (ADBC), and provide a simplified means of using ODBC calls to connect to a database and access its data. SQL statements are passed to the statement objects execute method in order to insert, update, retrieve, and delete data.
event
All JavaScript actions are executed when a particular event occurs. For each event, an event object is created. When an event occurs, the event object can be used to obtain and manage any information associated with the state of that particular event. An event object is created for each of the following type of events: Acrobat initialization, batch sequences, mouse events on bookmarks, JavaScript console actions, document print, save, open, or close actions, page open and close events, form field mouse, keystroke, calculation, format, and validation events, and menu item selection events.
JavaScript applications
JavaScript for Acrobat enables you to do a wide variety of things within Acrobat and Adobe Reader, and within PDF documents. The Acrobat extensions to JavaScript can help with the following workflows:
Create new PDF files Control the appearance and behavior of PDF files Convert PDF files to XML format Create and spawn templates Attach files to PDF documents Create, modify, and fill in dynamically changing, interactive forms Import and export form, attachment, and image data Save form data in XML, XDP, or Microsoft Excel format Email completed forms Make forms accessible to visually impaired users Make forms web-ready Migrate legacy forms to dynamic XFA Secure forms Set comment repository preferences Create and manage comments Approve documents using stamps Control and manage media players and monitors Add movie and sound clips Add and manage renditions Set multimedia preferences
Introduction
JavaScript applications 20
Create dialog boxes Add navigation to PDF documents Manage PDF layers Manage print production Perform searches for text in one or more documents Create, update, rebuild, and purge indexes Search document metadata Create and manage digital signatures Add and manage passwords Add usage rights Encrypt files Manage digital certificates Write JavaScript for Adobe Reader Enable collaboration Establish an ADBC connection Execute SQL statements Support for ADO (Windows only) Connection and method invocation HTTP authentication and WS-Security SOAP header support Error handling Handle file attachments Exchange compressed binary data Document literal encoding Serialize objects XML streams Apply DNS service discovery to find collaborative repositories on an intranet Perform XSLT conversions on XML documents Evaluate XPath expressions
Securing documents
XML
Tools
Acrobat provides an integrated development environment that offers several tools with which to develop and test JavaScript functionality. These tools are the JavaScript Editor, Console, and Debugger. In addition, Acrobat supports the use of third-party editors for code development. Topic Using the JavaScript Debugger console Description Covers the following topics:
See page 21
Opening the Console Executing JavaScript Formatting code Enabling JavaScript page 24 page 25 page 26 page 28 page 29 page 30
Using a JavaScript editor Specifying the default JavaScript editor Using an external editor Using the Debugger with Adobe Reader Enabling the JavaScript Debugger JavaScript Debugger
How to access and to use the JavaScript editor built into Acrobat. How to set the default JavaScript editor to an external text application. The use of an external editor to write JavaScript code. How to use the Debugger with Adobe Reader. Debugger preferences. The Debugger controls and their use.
21
Tools
Opening the console 22
Select Advanced > Document Processing > JavaScript Debugger, or Type Ctrl+J (Windows) or Command+J (Mac OS)
2. Select either Console or Script and Console from the debugger View list. To open and close the console with JavaScript code, use console.show() and console.hide() methods, respectively.
Executing JavaScript
The JavaScript console allows you to evaluate single or multiple lines of code. There are three ways to evaluate JavaScript code while using the interactive console:
To evaluate a portion of a line of code, highlight the portion and press either the Enter key on the numeric keypad or press Ctrl + Enter. To evaluate a single line of code, make sure the cursor is positioned on that line and press either the Enter key on the numeric keypad or press Ctrl + Enter. To evaluate multiple lines of code, highlight those lines and press either the Enter key on the numeric keypad or press Ctrl + Enter.
In all cases, the result of the most recent single JavaScript statement executed is displayed in the console.
Formatting code
To indent code in the JavaScript console, use the Tab key.
To indent four spaces to the right, position the cursor at the beginning of a single line or highlight the block of code, and press the Tab key. To indent four spaces to the left, position the cursor at the beginning of a single line or highlight a block of code and press Shift + Tab.
Enabling JavaScript
In order to use JavaScript, you must first verify that JavaScript has been enabled. In order to execute code from the console, you will also need to ensure that the JavaScript Debugger is enabled, since the Console window is a component within the JavaScript Debugger interface.
To enable JavaScript, the Debugger and the Console:
1. Launch Acrobat. 2. Select Edit > Preferences to open the Preferences dialog box. 3. Select JavaScript from the list of options on the left side of the dialog box. 4. Select Enable Acrobat JavaScript if it is not already selected.
Tools
Enabling JavaScript 23
5. In the Preferences dialog box, select Enable JavaScript Debugger After Acrobat is Restarted from the JavaScript Debugger options. 6. Select Enable Interactive Console. This option enables you to evaluate code that you write in the console window. 7. Select Show Console on Errors and Messages. This ensures that whenever you make mistakes, the console displays helpful information. 8. Click OK to close the Preferences dialog box. 9. Close and restart Acrobat.
To test the interactive Console:
1. Select Advanced > Document Processing > JavaScript Debugger to open the JavaScript Debugger. 2. In the debugger, select Console from the View window. The Console window appears. 3. Click Clear (the trash can icon), located at the bottom right of the Console, to delete any contents that appear in the window. 4. In the text window, type the following code:
var jsNum = 10;
5. With the mouse cursor positioned somewhere in this line of code, press Enter on the numeric keypad or press Ctrl + Enter. The JavaScript variable is created and is assigned a value of 10. The results are shown in the following graphic.
After each JavaScript statement executes, the console window prints out undefined, which is the return value of the statement. Note that the result of a statement is not the same as the value of an expression within the statement. In this case, the return value undefined does not mean that the value of jsNum is undefined; it just means that the entire JavaScript statements value is undefined. Note the use of the console.println() method to display the result in a more human-readable format.
Tools
Debugging with the JavaScript Console 24
testing and/or developing script snippets in the Console itself inserting console.println() commands to write information to the Console.
Example 2.1
The following script, which can be created in the JavaScript Console, illustrates the use of console.println(). The regular expression
var re = /(Professional|Pro)(\s+)(\d)/g
and the replacement function, myReplace(), are used to search the string, str, for the phrase "Professional 7" or "Pro 7", and to replace the string "7" with the string "8". The script is executed using the procedures described in Executing JavaScript on page 22. After testing and debugging, the script can be copied and pasted to the target location. Note the debugging loop inside the function myReplace() writes the arguments of the function to the Console. This helps in the development phase: the arguments are seen in the Console where you can verify that they are the ones expected. The loop can be deleted or commented out after testing.
function myReplace() { var l = arguments.length; for ( var i = 0; i < l; i++) console.println("arg" + i + " = " + arguments[i]) return arguments[1] + arguments[2] + "8"; } var str = "Acrobat Professional\n7 is a great application, " + "so I say on the 7th of May.\nOn a laptop Acrobat Pro 7.0 is on the go!" var re = /(Professional|Pro)(\s+)(\d)/g; var newStr = str.replace( re, myReplace); console.println("\nnewStr = " + newStr);
A more basic approach, however, is to think of a script as an action associated with a part of the document, such as a page, bookmark, or form field. As in the following example, you can select the object of interest and edit its particular script.
Tools
Specifying the default JavaScript editor 25
1. Right-click a document component such as a bookmark. This triggers a context menu. 2. Select Properties and choose the Actions tab. 3. Select Run a JavaScript from the Select Action drop-down list. 4. Click Add to open the JavaScript editor. 5. In the editor window, write the JavaScript code to run when the event that activates the code is created. 6. Click Close. If there are errors in your code, the JavaScript editor highlights the code line in question and displays an error message. Note: JavaScript actions have a scope associated with various levels of objects in a PDF document, such as a form field, a page, or the entire document. For example, a script at the document level would be available from all other scriptable locations within the document.
1. Choose Edit > Preferences (Ctrl+K) to open the Preferences dialog box. 2. Select JavaScript from the list of options on the left side of the dialog box. This brings up the Preferences dialog box. 3. In the JavaScript Editor section, select the editor you would like to use. The Acrobat JavaScript Editor option sets the built-in JavaScript editor as the default. The External JavaScript Editor option sets an external editor as the default. Note: For some external editors, Acrobat provides extra command line options for invoking the editor. For details, see Additional editor capabilities on page 26. Like the JavaScript Console, the built-in JavaScript Editor can be used to evaluate portions of JavaScript code. Select a line or block of code to be evaluated, and press the Enter key on the numeric keypad or Ctrl + Enter on the regular keyboard. When you execute script from within an JavaScript Editor window, results appear in the Console window. The Console window should be open prior to opening any JavaScript Editor window. The JavaScript Editor provides the same formatting options as those in the console window. For details, see Formatting code on page 22.
Tools
Using an external editor 26
You must save the file in order for Acrobat to detect the changes. Acrobat is inaccessible while the external editor is in use. JavaScript code cannot be evaluated within the external editor.
What are the command switches to tell the editor to always open a new instance? Switches vary depending on the editor and include such parameters as /NI and +new followed by the file name ("%f"). Note that the quotes are required, because the file name that Acrobat sends to the editor may contain spaces.
Tools
Specifying additional capabilities to your editor 27
Is there a way to instruct the editor to open a file and jump to a line number? Some line number command switches are -#, -L, +, and -l, each followed by the line number (%n). For most editors, the line number switch and %n should be enclosed in square brackets [...]. The text inside the square brackets will be used only when Acrobat requires that the editor jump to a specific line in order to correct a JavaScript syntax error. You can use an editor that does not support a line number switch; in this case, you will need to scroll to the appropriate line in the event of a syntax error.
For example, Acrobat recognizes the Visual SlickEdit editor as vs.exe and automatically supplies this command line template:
"C:\Program Files\vslick\win\vs.exe" "%f" +new [-#%n]
When Acrobat opens the default JavaScript editor, it makes the appropriate substitutions in the command line and executes it with the operating system shell. In the above case, if the syntax error were on line 43, the command line generated would appear as follows:
"C:\Program Files\vslick\win\vs.exe" "C:\Temp\jsedit.js" +new -#43
Note: To insert %, [, or ] as characters in the command line, precede each of them with the % escape character, thus using %%, %[, or %] respectively.
Editor Boxer ConTEXT CodeWright Emacs Epsilon Multi-Edit TextPad UltraEdit VEDIT
1. Open a script in your editor. 2. Add a syntax error. 3. Move the cursor to a line other than the one containing the syntax error. 4. Close and save the file. If a dialog box automatically appears prompting you to fix the syntax error, check whether it correctly specifies the line containing the error.
Tools
Saving and closing a file with a syntax error 28
Note: If you click No, Acrobat discards your file. Always click Yes. Acrobat expands the path to the editor to include the line number in the specified syntax. The editor opens and the cursor is placed on the appropriate line.
(This will break into the Debugger when exceptions occur.) Note: Since Adobe Reader does not provide access to the Debugger through its menu items or the Ctrl + J key sequence, the only ways to access the Debugger are to execute a JavaScript, cause an error, or customize the user interface (for example, you could add a button that runs a JavaScript causing the Debugger to appear).
Tools
Enabling the JavaScript Debugger 29
As you learned earlier when opening the JavaScript Console, which is integrated with the Debugger dialog box, the Debugger may be opening in Acrobat Professional by selecting Advanced > Document Processing > JavaScript Debugger. In addition, the Debugger automatically opens if a running script throws an exception or encounters a previously set break point. Note: The JavaScript Debugger cannot be used to analyze JavaScript stored in HTML pages viewed by web browsers or any other kind of scripting languages.
Turn this option off. Select Advanced > Document Processing > Document JavaScripts and delete the ACRO_Breakpoints script. Save the file.
This option provides three choices for actions when an exception is thrown: Ignore ignores the exception Trace displays a stack trace Break stops execution and displays a message window that gives you the option to start the debugger at the line where the exception occurred.
Tools
JavaScript Debugger 30
Meaning This option allows you to enter JavaScript commands in the console window. If this option is not checked and you click in the console window, the following message appears: The interactive console is not enabled. Would you like to enable it now? Click Yes to enable this option from within the Debugger. In Preferences you will now see this option checked.
This option opens the console window in the Debugger dialog box. Regardless of whether the Debugger is enabled, this option causes the Debugger dialog box to open when an error occurs and displays the error message to the console window.
JavaScript Debugger
You can open the JavaScript Debugger at any time by selecting the Acrobat menu item Advanced > Document Processing > JavaScript Debugger. Familiarize yourself with the parts of the window and the controls as described here before you attempt interactive debugging of a script. For information on the types and locations of scripts that may be debugged, see Accessing scripts in the Scripts window on page 33. The section Starting the Debugger on page 38 describes how to automatically start the Debugger for a script. Caution: In Windows, while the Debugger is open and a debugging session is in progress, Acrobat will be unavailable.
Tools
Debugger View windows 31
Tools
Debugger buttons 32
Debugger buttons
The following graphic shows the debugger buttons on the toolbar, and the table summarizes the functionality of each button, followed by detailed descriptions below.
Debugger buttons
Resume
Interrupt
Quit
Step over
Step into
Step out
Resume execution
When the script is stopped, the Resume Execution button cause the script to continue execution until it reaches one of the following:
The next script to be executed The next breakpoint encountered The next error encountered The end of the script
Interrupt
The Interrupt button halts execution of the current script. When clicked, it appears in red, which indicates that it has been activated and causes execution to stop at the beginning of the next script that is run. If this occurs, the Interrupt button is automatically deactivated and returns to its green color. It must be activated again in order to interrupt another script.
Quit
The Quit button terminates the debugging session and closes the Debugger.
Tools
Debugger Scripts window 33
Step over
The Step Over button executes a single instruction, and if it is a function call, it executes the entire function in a single step, rather than stepping into the function. For example, the position indicator (yellow arrow) in the Debugger is to the left of a function call, as shown below.
Execution is currently halted before the call to callMe. Assuming that there are no errors or breakpoints in callMe, clicking Step Over executes the entire callMe function, and advances the position indicator to the next script instruction following the function call. If the statement at the position indicator does not contain a function call, Step Over simply executes that statement.
Step into
The Step Into button executes the next statement, and if it is a function call, it proceeds to the first statement within the function. Note: It is not possible to step into native functions, since they have no JavaScript implementation. This applies to Acrobat native functions as well as core JavaScript functions.
Step out
The Step Out button executes the remaining code within the current function call and stops at the instruction immediately following the call. This button provides a convenient means of eliminating cumbersome, stepwise execution of functions that do not contain bugs. If you are not inside a function call and there are no errors, the Step Out button continues executing code to the end of the current script or until a breakpoint is encountered.
Scripts window
Tools
Debugger Scripts window 34
for the given function is available. As shown above in the graphic Scripts window, a function has been defined for a mouse-up action on a button named Button1. Click on the script icon to display its code. JavaScript can be stored in several places, which may be either inside or outside PDF files. The following sections describe their possible locations.
Form editing mode To switch to form editing mode, select Forms > Edit Form in Acrobat.
Folder-level scripts normally can be viewed and debugged but not edited in Acrobat. Console and batch processing scripts are not visible to the Debugger until they are executed. For this reason, you cannot set breakpoints prior to executing these scripts. You can access the scripts either using the Debug From Start option or by using the debugger keyword. See Starting the Debugger on page 38 for details.
Tools
Call Stack list 35
Call stack
You can select any function in the call stack. Doing so selects that stack frame, and its location is shown in the Inspect details window. When Local Variables is selected in the Inspect drop-down list, the variables specific to that active frame are displayed in the Inspect details window.
Tools
Inspect details window 36
Inspecting variables
The Inspect details window is a powerful tool that you can use to examine the current state of JavaScript objects and variables. It enables you to inspect any objects and properties in a recursive manner within the current stack frame in the debugging session. To inspect a variable, select Local Variables from the Inspect drop-down list, which displays a list of variable and value pairs in the Inspect details window. To place a value in a variable, highlight the variable in the details window (this activates the Edit button). Click the Edit button. An Edit Variable dialog box appears, allowing you to enter a new value for the variable as shown in the following graphic. A triangle next to a name indicates that an object is available for inspection. If you would like to view its properties, click the triangle to expand the object.
Watches
The Watches list enables you to customize how variables are inspected. Watches are JavaScript expressions evaluated when the debugger encounters a breakpoint or a step in execution. The Watches list provides you with the ability to edit, add, or delete watches using the three buttons just below the Inspect details window. All results are displayed in the Inspect details window in the order in which they were created.
To set a watch:
1. Select Watches from the Inspect drop-down list. 2. Click the New button. A dialog box prompts you for the JavaScript variable or expression to be evaluated.
To change the value of a watch:
1. Select the watch from the list. 2. Click the Edit button, which displays a dialog box prompting you to specify a new expression for evaluation.
To delete a watch:
1. Select the watch from the Inspect drop-down list. 2. Click the Delete button.
Tools
Inspect details window 37
Breakpoints
The Breakpoints option in the Inspect drop-down list enables you to manage program breakpoints, which in turn make it possible to inspect the values of local variables once execution is halted. A breakpoint may be defined so that execution halts at a given line of code, and conditions may be associated with them (see Using conditional breakpoints on page 38). When a breakpoint is reached, JavaScript execution halts and the debugger displays the current line of code. To add a breakpoint, click on the gray strip to the left of the code in the script view, which causes a red dot to appear. The lines at which breakpoints are permitted have small horizontal lines immediately to their left in the gray strip. To remove the breakpoint, click on the red dot, which subsequently disappears.
Style 2: Place the left curly brace on a separate line, for example
function callMe() { // curly brace is on a separate line var a = 0; }
If you would like to set a breakpoint at the function heading, use Style 1. Note that the JavaScript Debugger does not set a breakpoint at the function heading for Style 2. It is only possible to set a breakpoint from the line of code containing the left curly brace. This is illustrated in the graphic below. It is possible to set the breakpoint on the line below the function heading for callMe and on the line containing the function heading for testLoop. Setting a breakpoint at a function heading causes execution to stop at the first statement within the function.
Tools
Starting the Debugger 38
Listing breakpoints
To view the list of all breakpoints set for the debugging session, select the Breakpoints option from the Inspect drop-down list. You can edit and delete breakpoints using the button controls just beneath the Inspect details window, as shown in the graphic Inspect details window button controls on page 35.
1. Select Breakpoint from the Inspect drop-down list 2. Click Edit. A dialog box appears, prompting you to change the breakpoint condition
Tools
Final notes 39
Final notes
There are limitations to debugging scripts in Acrobat from inside a browser, because not all scripts contained in a PDF file may be available if the PDF file has not been completely downloaded. Debugging is not possible if a modal dialog box is running. This may occur when debugging a batch sequence. If a modal dialog box is running during a debugging session and the program stops responding, press the Esc key. Debugging scripts with an event initiated by either the app.setInterval or app.setTimeOut method may trigger the appearance of a series of recurring alert messages. If this occurs, press the Esc key after the modal dialog box has exited.
App When the Viewer is started, the Application Initialization Event occurs. Script files, called Folder Level JavaScripts, are read in from the application and user JavaScript folders. See Folder level on page 42 for additional details. Batch A batch event occurs during the processing of each document of a batch sequence. Bookmark This event occurs whenever a user clicks on a bookmark that executes a script. Console A console event occurs whenever a user evaluates a script in the console. See Executing JavaScript on page 22. Doc This event is triggered whenever a document level event occurs. For more information, see Document level on page 43. External This event is the result of an external access, for example, through OLE, AppleScript, or loading an FDF field This event is triggered when the user interacts with an Acrobat form, see Field level on page 44 for more information. Link This event is triggered when a link containing a JavaScript action is activated by the user. Menu A menu event occurs whenever JavaScript that has been attached to a menu item is executed. In Acrobat 5.0 and later, the user can add a menu item and associate JavaScript actions with it.
40
Page This event is triggered when the user changes pages in the document. See Page level on page 43 for more information. Screen This event is triggered when the user interacts with a multimedia screen annotation.
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 JavaScript for Acrobat 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 names
Init Exec Mouse Up Exec DidPrint, DidSave, Open, WillClose, WillPrint, WillSave Exec Blur, Calculate, Focus, Format, Keystroke, Mouse Down, Mouse Enter, Mouse Exit, Mouse Up, Validate Mouse Up Exec Open, Close 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 JavaScript for Acrobat API Reference.
About contexts
JavaScript for Acrobat can be placed at a variety of levels:
Folder level Scripts placed here respond to App type events. Document level Scripts placed here respond to Doc type events. Page level Scripts placed here respond to Page type events.
Field level Scripts placed here respond to Field type events. Batch level Scripts are placed here respond to Batch type events.
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 on page 182 and Hiding scripts on page 182.
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 applications JavaScripts folder, and user folder level scripts are stored in the users JavaScripts folder. These scripts are loaded when Acrobat starts execution, and are associated with the event objects 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 objects 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 on page 135 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.
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.
Variable definitions: Define variables at the document level to make them visible to any executing script. For example,
var defaultUserColor = "red";
The variable defined above, which has an initial value of "red", may be changed as the user interacts with the document.
Function definitions: Define functions at the document level that support the user interaction with the document. These functions may be utility functions for handling common tasks for string or number manipulation, or functions that execute lengthy scripts called by actions initiated by a user interacting with Acrobat form fields, bookmarks, page changes, and so on.
To create or access document level scripts in Acrobat, select Advanced > Document Processing > 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 on page 43). 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
Document Will Close This event is triggered before the document is closed. Document Will Save This event is triggered before the document is saved. Document Did Save This event is triggered after the document is saved. Document Will Print This event is triggered, before the document is printed. Document Did Print This event is triggered after the document is closed.
To access the JavaScript Editor for each of these document actions, select Advanced > Document Processing > Set Document Action. You can also create the document actions just described programmatically using the setAction method of the Doc object.
Page level
Page level scripts are scripts that are executed when a particular page is either closed or opened.
Page Open This event is triggered whenever a new page is viewed and after the drawing of the page has occurred. Page Close This event is triggered whenever the page being viewed is no longer the current page; that is, the user switched to a new page or closed the document. Page Close will occur before the Document Will Close event.
1. Click the Pages tab. 2. Right-click a thumbnail and select Page Properties. 3. Select the Actions tab from the Page Properties dialog box. 4. In the Select Trigger list, choose either Page Open or Page Close. 5. In the Select Action list, choose Run a JavaScript. 6. Click Add to open the JavaScript editor.
To access or delete a page level script:
1. Click the Pages tab. 2. Select the page by clicking the page thumbnail. 3. Right-click a thumbnail and select Page Properties. 4. Select the Actions tab from the Page Properties dialog box. 5. Select any of the actions listed in the Actions list. 6. Click Edit or Delete. 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.
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.
Batch level
A batch level script is a script that can be applied to a collection of documents, and operates at the application level. For example, you can define a batch script to print a series of documents or apply security restrictions to them. To create or edit a batch level script in Acrobat, select Advanced > Document Processing > Batch Processing. The document Batch Sequences, available from the Acrobat Family Developer Center, is a complete tutorial on how to write batch sequences using JavaScript.
By enabling the preferences item named Enable Menu Items JavaScript Execution Privileges. By executing a specific method through a trusted function (introduced in Acrobat 7.0). Trusted functions allow privileged codecode that normally requires a privileged context to executeto execute in a non-privileged context. For details and examples, see documentation of the app.trustedFunction method in the JavaScript for Acrobat API Reference.
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. Here is another, more complex, example.
Example 3.1
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.
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 on page 45, which necessarily implies the installation of folder JavaScript on the users system.
You must obtain a digital ID. You must sign the PDF document containing the restricted JavaScript methods using the digital ID. For details on where you can obtain digital IDs and the procedures for using them to sign documents, see Acrobat Help.
The recipient should trust the signer for certified documents and JavaScript. For details, see Acrobat Help.
All trusted certificates can be accessed by selecting Certificates from Advanced > Manage Trusted Identities in the Acrobat main menu.
Discusses methods for reading a document using page 49 JavaScript and surveys methods for modifying the document, by adding fields, links and even content. Combine multiple PDF documents. Combine multiple documents that are not necessarily PDF files. page 51 page 51
Combining PDF documents Combining and extracting files Creating file attachments
Programmatically attach a file to a PDF document. page 52 This includes examples of communicating with the attachments, and extracting data from and writing to the attachments. Covers methods for cropping and rotating pages. page 55 Techniques and methods for manipulating pages. page 56 Applying watermarks and backgounds using JavaScript methods. Use the saveAs method of the Doc object to convert a document to XML format. page 58 page 59
Cropping and rotating pages Extracting, moving, deleting, replacing, and copying pages Adding watermarks and backgrounds Converting PDF documents to XML format
This statement creates a blank PDF document and is used primarily for testing purposes.
49
Once this statement has been executed from the console, you can manipulate the page by invoking methods contained within the Doc object, as indicated in the following table. Details of these methods are found in the JavaScript for Acrobat API Reference.
Methods
newPage, insertPages, replacePages spawn addAnnot addField addIcon addLink addScript
Doc Doc
The Doc.newDoc() method cannot write text content to the newly created document. To do that, you need to use the Report object.
Example 4.1
The following example creates a PDF document, sets the font size, sets the color to blue, and writes a standard string to the document using the writeText method of the Report object. Finally, it opens the document in the viewer. See the JavaScript for Acrobat API Reference for details of this object, its properties and methods and for additional examples.
var rep = new Report(); rep.size = 1.2; rep.color = color.blue; rep.writeText("Hello World!"); rep.open("My Report");
The Report object has many useful applications. With it, for example, you can create a document that reports back a list of all form fields in the document, along with their types and values; another application is to summarize all comments in a document. The JavaScript for Acrobat API Reference has an example of the latter application in the Report object section.
Example 4.2
// Create a new PDF document: var newDoc = app.newDoc(); // Insert doc1.pdf: newDoc.insertPages({ nPage: -1, cPath: "/c/temp/doc1.pdf", }); // Insert doc2.pdf: newDoc.insertPages({ nPage: newDoc.numPages-1, cPath: "/c/temp/doc2.pdf", }); // Save the new document: newDoc.saveAs({ cPath: "/c/temp/myNewDoc.pdf"; }); // Close the new document without notifying the user: newDoc.closeDoc(true);
Example 4.3
In this example, a document is opened with an absolute path reference, then other PDF files in the same folder are appended to the end of the document. For convenience, the files that are appended are placed in an array for easy execution and generalization.
var doc = app.openDoc({ cPath: "/C/temp/doc1.pdf" }) aFiles = new Array("doc2.pdf","doc3.pdf"); for ( var i=0; i < aFiles.length; i++) { doc.insertPages ({ nPage: doc.numPages-1, cPath: aFiles[i], nStart: 0 }); }
Another problem is to combine several files of possibly different file types. In recent versions of Acrobat, the notion of a binder was introduced. There is a nice UI for combining files of different formats. How do you do it programmatically?
Example 4.4
In this example, an initial PDF file is opened, and all other files are appended to it.
doc = app.openDoc({ cPath: "/C/temp/doc1.pdf" }) // List of files of different extensions aFiles = new Array( "doc2.eps", "doc3.jpg", "doc4.pdf"); for ( var i=0; i < aFiles.length; i++) { // Open and convert the document newDoc = app.openDoc({ oDoc: doc, cPath: aFiles[i], bUseConv: true }) // Save the new PDF file to a temp folder newDoc.saveAs({ cPath: "/c/temp/tmpDoc.pdf" }); // Close it without notice newDoc.closeDoc(true); // Now insert that PDF file just saved to the end of the first document doc.insertPages ({ nPage: doc.numPages-1, cPath: "/c/temp/tmpDoc.pdf", nStart: 0 }); }
You can also programmatically extract pages and save them to a folder.
Example 4.5
Suppose the current document consists of a sequence of invoices, each of which occupies one page. The following code creates separate PDF files, one for each invoice:
var filename = "invoice"; for (var i = 0; i < this.numPages; i++) this.extractPages({ nStart: i, cPath : filename + i + ".pdf" });
These are the objects, properties and methods relevant to file attachments. Name
Doc.createDataObject() Doc.dataObjects
Description Creates a file attachment. Returns an array of Data objects representing all files attached to the document. Saves the file attachment to the local file system Acquires the Data object of a particular attachment. Attaches a file to the document. Removes a file attachment from the document. Returns the Doc object for an attached PDF file. Allows access to the contents of the file attachment associated with a Data object. Rights to the file attachment. Converts a stream from a string Converts a string from a stream.
Doc.exportDataObject()
Doc.getDataObject()
Doc.importDataObject() Doc.removeDataObject()
Doc.openDataObject()
Doc.getDataObjectContents()
Example 4.6
This example takes the response given in a text field of this document and appends it to an attached document. (Perhaps this document is circulating by email, and the user can add in their comments through a multiline text field.) This example uses four of the methods listed above.
var v = this.getField("myTextField").value; // Get the contents of the file attachment with the name "MyNotes.txt" var oFile = this.getDataObjectContents("MyNotes.txt"); // Convert the returned stream to a string var cFile = util.stringFromStream(oFile, "utf-8"); // Append new data at the end of the string cFile += "\r\n" + v; // Convert back to a stream oFile = util.streamFromString( cFile, "utf-8"); // Overwrite the old attachment this.setDataObjectContents("MyNotes.txt", oFile); // Read the contents of the file attachment to a multiline text field var oFile = this.getDataObjectContents("MyNotes.txt"); var cFile = util.stringFromStream(oFile, "utf-8"); this.getField("myTextField").value = cFile;
Beginning with Acrobat 8, the JavaScript interpreter includes E4X, the ECMA-357 Standard that provides native support of XML in JavaScript. See the document ECMAScript for XML (E4X) Specification for the complete specification of E4X. The next example illustrates the use of E4X and file attachments.
Example 4.7
The following script describes a simple database system. The database is an XML document attached to the PDF file. The user enters the employee ID into a text field, the JavaScript accesses the attachment, finds the employees record and displays the contents of the retrieved record in form fields. We have a PDF file, employee.pdf, with three form fields, whose names are employee.id, employee.name.first and employee.name.last. Attached to the PDF file is an XML document created by the following script:
// Some E4X code to create a database of info x = <employees/>; function popXML(x,id,fname,lname) { y = <a/>; y.employee.@id = id; y.employee.name.first = fname; y.employee.name.last = lname; x.employee += y.employee; } popXML(x,"334234", "John", "Public"); popXML(x,"324234", "Jane", "Doe"); popXML(x,"452342", "Davey", "Jones"); popXML(x,"634583", "Tom", "Jefferson");
Copy and paste this code into the console and execute it. Youll see the XML document as the output of this script. The output was copied and pasted into a document named employee.xml, and saved to the same folder as employee.pdf. You can attach employee.xml using the UI, but the script for doing so is as follows:
var thisPath = this.path.replace(/\.pdf$/, ".xml"); try { this.importDataObject("employees", thisPath); } catch(e) { console.println(e) };
Of the three form fields in the document employee.pdf, only employee.id has any script. The following is a custom keystroke script:
if (event.willCommit) { try { // Get the data contents of the "employees" attachment var oDB = this.getDataObjectContents("employees"); // Convert to a string var cDB = util.stringFromStream(oDB); // Use the eval method to evaluate the string, you get an XML variable var employees = eval(cDB); // Retrieve record with the id input in the employee.id field var record = employees.employee.(@id == event.value); // If the record is an empty string, or there was nothing entered... if ( event.value != "" && record.toString() == "" ) { app.alert("Record not found"); event.rc = false; }
// Populate the two other fields this.getField("employee.name.first").value = record.name.first; this.getField("employee.name.last").value = record.name.last; } catch(e) { app.alert("The DB is not attached to this document!"); event.rc = false; } }
Cropping pages
The Doc object provides methods for setting and retrieving the page layout dimensions. These are the setPageBoxes and getPageBox methods. There are five types of boxes available:
See Section 10.10.1 of the PDF Reference version 1.7 for a discussion of these types of boxes. The setPageBoxes method accepts the following parameters:
cBox the type of box nStart the zero-based index of the beginning page nEnd the zero-based index of the last page rBox the rectangle in rotated user space
For example, the following code crops pages 2-5 of the document to a 400 by 500 pixel area:
this.setPageBoxes({ cBox: "Crop", nStart: 2, nEnd: 5, rBox: [100,100,500,600] });
For example, the following code retrieves the crop box for page 3:
var rect = this.getPageBox("Crop", 3);
Rotating pages
You can use JavaScript to rotate pages in 90-degree increments in the clockwise direction relative to the normal position. This means that if you specify a 90-degree rotation, no matter what the current orientation is, the upper portion of the page is placed on the right side of your screen. The Doc objects setPageRotations and getPageRotation methods are used to set and retrieve page rotations. The setPageRotations method accepts three parameters:
nStart the zero-based index of the beginning page nEnd the zero-based index of the last page nRotate 0, 90, 180, or 270 are the possible values for the clockwise rotation
In the following example, pages 2 and 5 are rotated 90 degrees in the clockwise direction:
this.setPageRotations(2,5,90);
To retrieve the rotation for a given page, invoke the Doc object getPageRotation method, which requires only the page number as a parameter. The following code retrieves and displays the rotation in degrees for page 3 of the document:
var rotation = this.getPageRotation(3); console.println("Page 3 is rotated " + rotation + " degrees.");
These methods enable you to customize the page content within and between documents. Suppose you would like to remove pages within a document. Invoke the Doc objects deletePages method, which accepts two parameters:
nStart the zero-based index of the beginning page nEnd the zero-based index of the last page
For example, the following code deletes pages 2 through 5 of the current document:
this.deletePages({nStart: 2, nEnd: 5});
Suppose you would like to copy pages from one document to another. Invoke the Doc object insertPages method, which accepts four parameters:
nPage the zero-based index of the page after which to insert the new pages cPath the device-independent path of the source file nStart the zero-based index of the beginning page nEnd the zero-based index of the last page
For example, the following code inserts pages 2 through 5 from mySource.pdf at the beginning of the current document:
this.insertPages({ nPage: -1, cPath: "/C/temp/mySource.pdf", nStart: 2, nEnd: 5 });
You can combine these operations to extract pages from one document and move them to another (they will be deleted from the first document). The following code will extract pages 2 through 5 in mySource.pdf and move them into myTarget.pdf :
// The operator, this, represents myTarget.pdf // First copy the pages from the source to the target document this.insertPages({ nPage: -1, cPath: "/C/temp/mySource.pdf", nStart: 2, nEnd: 5 }); // Now delete the pages from the source document var source = app.openDoc({cPath:"/C/temp/mySource.pdf"}); source.deletePages({nStart: 2, nEnd: 5});
To replace pages in one document with pages from another document, invoke the target documents replacePages method, which accepts four parameters:
nPage The zero-based index of the page at which to start replacing pages cPath The device-independent pathname of the source file nStart The zero-based index of the beginning page nEnd The zero-based index of the last page
In the following example, pages 2 through 5 from mySource.pdf replace pages 30 through 33 of myTarget.pdf :
// This represents myTarget.pdf this.replacePages({ nPage: 30, cPath: "/C/temp/mySource.pdf", nStart: 2, nEnd: 5 });
To safely move pages within the same document, it is advisable to perform the following sequence: 1. Copy the source pages to a temporary file. 2. Insert the pages in the temporary file at the new location in the original document. 3. Delete the source pages from the original document. The following example moves pages 2 through 5 to follow page 30 in the document:
// First create the temporary document: var tempDoc = app.newDoc("/C/temp/temp.pdf"); // Copy pages 2 to 5 into the temporary file tempDoc.insertPages({ cPath: "/C/temp/mySource.pdf", nStart: 2, nEnd: 5 }); // Copy all of the temporary file pages back into the original: this.insertPages({ nPage: 30, cPath: "/C/temp/temp.pdf" }); // Now delete pages 2 to 5 from the source document this.deletePages({nStart: 2, nEnd: 5});
In the next example, the addWatermarkFromFile method is used to add the second page of watermark.pdf as a watermark to the first 10 pages of the current document. It is rotated counterclockwise by 45 degrees, and positioned one inch down and two inches over from the top left corner of each page:
this.addWatermarkFromFile({ cDIPath: "/C/temp/watermark.pdf", nSourcePage: 1, nEnd: 9, nHorizAlign: 0, nVertAlign: 0, nHorizValue: 144, nVertValue: -72, nRotation: 45 });
It is also possible to use the addWatermarkFromText method to create watermarks. In this next example, the word Confidential is placed in the center of all the pages of the document, and its font helps it stand out:
this.addWatermarkFromText( "Confidential", 0, font.Helv, 24, color.red );
Print Production
This chapter will provide you with an in-depth understanding of the ways in which you can manage print production workflows for PDF documents. Topic Setting print options Printing PDF documents Silent printing Printing comments and forms Booklet printing Setting advanced print options Description See
Gives brief descriptions of the printParams object, used to page 60 set print options. Discusses printing a document using the print method of the Doc object. Print document with little user interaction. Setting the print job to print just forms. Use the print method to create a booklet. Various options for doing this are discussed. page 62 page 63 page 64 page 64
Discusses how to set the print job to some of the advanced page 65 print options: marks and bleeds, PostScript printing, setting output and font options.
PrintParams properties
Property
binaryOK bitmapDPI booklet colorOverride colorProfile constants downloadFarEastFonts fileName
Description Binary printer channel is supported. DPI used for bitmaps or rasterizing transparency. An object used to set properties of booklet printing. Uses color override settings. Color profile based on available color spaces. Wrapper object for printParams constants. Sends Far East fonts to the printer.
fileName is used when printing to a file instead of a printer.
60
Print Production
Setting print options 61
Property
firstPage flags fontPolicy gradientDPI interactive lastPage nUpAutoRotate nUpNumPagesH
Description The first zero-based page to be printed. A bit field of flags to control printing options. Used to determine when fonts are emitted. The DPI used for rasterizing gradients. Sets the level of interaction for the user. The last zero-based page to be printed. Auto rotate pages during multiple pages per sheet printing. Number of pages to lay out horizontally during multiple pages per sheet printing. Number of pages to lay out vertically during multiple pages per sheet printing. Determines whether a page boundary is drawn and printed during multiple pages per sheet printing. Determines how the multiple pages are laid out on the sheet for multiple pages per sheet printing. How pages will be handled (fit, shrink, or tiled). Even, odd, or all pages are printed. Sends pages as large bitmaps. Determines whether form fields and comments will be printed. The name of the destination printer. The level of PostScript emitted to the printer. A bit field of flags for outlines, clips, and overprint. Prints pages in reverse order. Labels each page of tiled output. Output marks to cut the page and where overlap occurs. The number of points that tiled pages have in common. The amount that tiled pages are scaled. The degree to which high level drawing operators are preserved. Determines whether the printer Color Rendering Dictionary is used. Determines whether Type 1 fonts will be converted.
nUpNumPagesV
nUpPageBorder
nUpPageOrder
pageHandling pageSubset printAsImage printContent printerName psLevel rasterFlags reversePages tileLabel tileMark tileOverlap tileScale transparencyLevel userPrinterCRD useT1Conversion
Print Production
Printing PDF documents 62
In addition to the properties of the printParams object, the app objects printColorProfiles and printerNames properties provide a list of available color spaces and printer names, respectively. When printing a document, any comments and form fields of the document may or may not print, depending on the settings of the individual annotations. The print property of the Annotation and Field objects is used to set whether an individual annotation is printed.
Description Determines whether to print annotations. Determines whether to print each page as an image. Determines whether to print in reverse page order. Determines whether the page is shrunk to fit the imageable area of the printed page. Suppresses the Cancel dialog box while the document is printed. Determines whether to present a user interface to the user. The zero-based index of the last page. The zero-based index of the beginning page. The printParams object containing the printing settings. Note: The printParams parameter is available in Acrobat 6.0 or later. If this parameter is passed, any other parameters are ignored.
In the first example below, pages 1-10 of the document are sent to the default printer, printed silently without user interaction, and are shrunk to fit the imageable area of the pages:
this.print({ bUI: false, bSilent: true, bShrinkToFit: true, nStart: 1, nEnd: 10 });
The syntax above is used for versions of Acrobat previous to 6.0. For Acrobat 6.0 or later, the recommend method is to pass a printParams object to the Doc.print method. All the subsequent examples use this method.
Print Production
Silent printing 63
To print the document to a PostScript file, obtain the printParams object by invoking the Doc object getPrintParams method. Set its printerName property to the empty string, and set its fileName property to a string containing the device-independent path of the PostScript file to which it will be printed, as shown in the following example:
var pp = this.getPrintParams(); pp.printerName = ""; // File name must be a safe path pp.fileName = "/C/temp/myPSDoc.ps"; this.print(pp);
If you would like send the file to a particular printer, you can specify the printer by setting the printerName property of the printParams object, as shown in the following example:
var pp = this.getPrintParams(); pp.interactive = pp.constants.interactionLevel.automatic; pp.printerName = "Our office printer"; this.print(pp);
Silent printing
There are various ways to print a document without requiring user interaction. One way is to use the Doc object print method and set the bSilent attribute to true, as the following example shows.
this.print({bUI: false, bSilent: true, bShrinkToFit: true});
Beginning with version 7.0, non-interactive printing can only be done in batch and console events. Using the printParams object, this is the script for printing silently:
var pp = this.getPrintParams(); pp.interactive = pp.constants.interactionLevel.silent; this.print(pp);
If you would like to print without requiring user interaction, and would like the progress monitor and Cancel dialog box to be removed when printing is complete, use the interactive property as shown in the following example:
var pp = this.getPrintParams(); pp.interactive = pp.constants.interactionLevel.automatic;
There are many options you can choose without requiring user interaction. For example, you can select the paper tray:
var fv = pp.constants.flagValues; pp.flags |= fv.setPageSize;
These coding approaches may be used in menus or buttons within a PDF file, may exist at the folder or batch levels, and are available through Acrobat or Adobe Reader 6.0 or later. For more information, see the JavaScript for Acrobat API Reference, as well as the Acrobat SDK samples SDKSilentPrint.js and SDKJSSnippet1.pdf.
Print Production
Printing comments and forms 64
Booklet printing
Beginning with Acrobat 8.0, you can print booklets. To do so, begin by getting the printParams object:
var pp = this.getPrintParams();
Use the booklet property of printParams to set the specialized printing parameters for booklet printing. pp.booklet is an object with properties:
binding determines the paper binding direction and the page arrange order duplexMode determines the duplex printing mode subsetFrom determines the first booklet sheet to be printed. Independently from the general
All the properties above take integers for their values. The value for binding is set through the properties of the constants.bookletBindings object of printParams, as illustrated in the following example.
Example 5.1
The constants.bookBindings object has four properties: Left (the default), Right, LeftTall and RightTall. The value for duplexMode is set through the properties of the constants.bookletDuplexModes object of printParams
Example 5.2
pp.pageHandling = pp.constants.handling.booklet; pp.booklet.duplexMode = pp.constants.bookletDuplexModes.FrontSideOnly; this.print(pp); constants.bookletDuplexModes has three properties: BothSides, FrontSideOnly and BackSideOnly. For printers that print only on one side, use FrontSideOnly first then reinsert the printed pages and print again with BacksideOnly to complete a manual duplex printing.
Print Production
Setting advanced print options 65
In addition, you can set the psLevel property of the printParams object to specify the level of PostScript emitted to PostScript printers. If the printer only supports PostScript level 1, set the printParams objects printAsImage property to true.
printed. This can be used to optimize the balance between memory and speed constraints.
Print Production
Setting advanced print options 66
In the following example, all the fonts are emitted at the beginning of the print job, and freed once the job is finished:
var pp = this.getPrintParams(); pp.fontPolicy = pp.constants.fontPolicy.jobStart; this.print(pp);
You can also control whether Type 1 fonts will be converted to alternative font representations, by setting the useT1Conversion property of the printParams object. There are three values that can be used:
auto let Acrobat decide whether to disable the conversion, based on its internal list of printers that
Finally, it is possible to send Far East fonts to the printer by setting the printParams objects downloadFarEastFonts property to true.
Discusses the various properties and methods of Acrobat page 67 forms, and how to process user interaction. Includes such tasks as highlighting required fields, setting a field with a hierarchal naming scheme, setting tab and calculation order. page 86
Introduction to XML forms architecture (XFA) Making forms accessible Using JavaScript to secure forms
Gives on overview of XML forms and discusses the use of page 99 JavaScript for Acrobat in an XML context. Guidelines for making an Acrobat form accessible. page 107
Discusses techniques for encrypting a document for a list page 110 of recipients.
Forms essentials
You can extend the capability of your forms by using JavaScript to automate formatting, calculations, and data validation. In addition, you can develop customized actions assigned to user events. Finally, it is possible for your forms to interact with databases and web services.
67
contained within the form fields. In addition, all calculations, validations, and formatting are specified and managed within the DOM and XML processes. Static XML forms were supported in Acrobat 6.0, and dynamic XML forms are now supported in Acrobat 7.0. Both types are created using LiveCycle Designer. A static XML form presents a fixed set of text, graphics, and field areas at all times. Dynamic XML forms are created by dividing a form into a series of subforms and repeating subforms. They support dynamically changing fields that can grow or shrink based on content, variable-size rows and tables, and intelligent data import/export features.
The creation of a new form, whether done through the Acrobat layout tools or LiveCycle Designer, or programmatically through JavaScript, will require that you consider the following:
How the form fields will be positioned. Which form fields will be associated in collections so that their properties can be set with consistency and efficiency. How size, alignment, and distribution of form fields within the document will be determined. When and how to set up duplicate form fields so that when the user types information into one form field, that information automatically appears in the duplicate form fields. When to create multiple form fields for array-based access and algorithms. The tab order of form fields.
You can use JavaScript to create a form field by invoking the addField method of the Doc object, which returns a Field object. This method permits you to specify the following information:
The field name. This may include hierarchical syntax in order to facilitate logical groupings. For example, the name myGroup.firstField implies that the form field firstField belongs to a group of fields called myGroup. The advantage of creating logical hierarchies is that you can enforce consistency among the properties of related form fields by setting the properties of the group, which automatically propagate to all form fields within the group. One of the seven field type values listed above, surrounded by quotes. The page number where the form field is placed, which corresponds to a zero-based indexing scheme. Thus, the first page is considered to be page 0. The location, specified in rotated user space (the origin is located at the bottom left corner of the page), on the page where the form field is placed. The location is specified through the use of an array of four values. The first two values represent the coordinates of the upper left corner, and the second two values represent the coordinates of the lower right corner: [upper-left x, upper-left y, lower-right x, lower-right y].
For example, suppose you would like to place a button named myButton on the first page of the document. Assume that the button is one inch wide, one inch tall, and located 100 points in from the left side of the page and 400 points up from the bottom of the page (there are 72 points in 1 inch). The code for creating this button would appear as follows:
var var var var var name = "myButton"; type = "button"; page = 0; location = [100, 472, 172, 400]; myField = this.addField(name, type, page, location);
This approach to creating form fields is applicable to all fields, but it should be noted that radio buttons require special treatment. Since a set of radio buttons represents a set of mutually exclusive choices, they belong to the same group. Because of this, the names of all radio buttons in the same group must be identical. In addition, the export values of the set of radio buttons must be set with a single statement, in which an array of values are assigned by the exportValues property of the Field object. For example, suppose we would like to create a set of three radio buttons, each 12 points wide and 12 points high, all named myRadio. We will place them on page 5 of the document, and their export values will be Yes, No, and Cancel. They can be created as shown in the code given below:
var name = "myRadio"; var type = "radiobutton"; var page = 5; var rb = this.addField(name, type, page, [400, 442, 412, 430]); this.addField(name, type, page, [400, 427, 412, 415]); this.addField(name, type, page, [400, 412, 412, 400]); rb.exportValues=["Yes", "No", "Cancel"];
Field properties
A form field has certain properties that determines its appearance, printability, orientation, and the actions performed when the user interacts with it. Some properties are common to all form fields, while others are particular to certain types of fields. The properties of a field can be set not only through the UI, but also programmatically with JavaScript. The most basic property of every form field is its name, which provides the reference necessary for subsequent access and modification. The key to setting the properties of a field is to first acquire the Field object of that field using its name; this is done using the getField method of the Doc object:
var f = this.getField("myField");
The getField method takes as its argument the field name of the target field. The Field object can be obtained using other methods as well, for example, the addField method returns the Field object of the field it just created. General properties that apply to all form fields include the display rectangle, border style, border line thickness, stroke color, orientation, background color, and tooltip. In addition, you can choose whether it should be read only, have the ability to scroll, and be visible on screen or in print. There are also specific settings you can apply to text characteristics, button and icon size and position relationships, button appearance when pushed, check box and radio button glyph appearance, and the number and selection options for combo box and list box items. All formatting options are listed and described in the following table.
Field properties
Property display rectangle border style stroke color border thickness orientation background color tooltip read only scrolling display Description Position and size of field on page. Rectangle border appearance. Color of bounding rectangle. Width of the edge of the surrounding rectangle. Rotation of field in 90-degree increments. Background color of field (gray, transparent, RGB, or CMYK). Short description of field that appears on mouse-over. Whether the user may change the field contents. Whether text fields may scroll. Whether visible or hidden on screen or in print. Field properties
rect borderStyle strokeColor lineWidth rotation fillColor
userName
readonly
doNotScroll display
Property text
Description Font, color, size, rich text, comb format, multiline, limit to number of characters, file selection format, or password format.
Field properties
textFont, textColor, textSize, richText, richValue, comb, multiline, charLimit, fileSelect, password alignment buttonAlignX, buttonAlignY buttonFitBounds, buttonScaleHow, buttonScaleWhen highlight style numItems editable multipleSelection
Text layout in text fields. Alignment of icon on button face. Relative scaling of an icon to fit inside a button face. Appearance of a button when pushed. Glyph style for checkbox and radio buttons. Number of items in a combo box or list box. Whether the user can type in a combo box. Whether multiple list box items may be selected.
Button fields
We will begin by creating a button named myButton:
var f = this.addField("myButton", "button", 0, [200, 250, 250, 400]);
In most cases, however, a form field, such as this button, is created through the UI. If the field already exists, get the Field object as follows:
var f = this.getField("myButton");
To create a blue border along the edges of its surrounding rectangle, we will set its strokeColor property:
f.strokeColor = color.blue;
In addition, you can select from one of the following choices to specify its border style: solid (border.s), beveled (border.b), dashed (border.d), inset (border.i), or underline (border.u). In this case we will make the border appear beveled by setting its borderStyle property:
f.borderStyle = border.b;
To set the line thickness (in points) of the border, set its lineWidth property:
f.lineWidth = 1;
To set its background color to yellow, we will set its fillColor property:
f.fillColor = color.yellow;
To specify the text that appears on the button, invoke its buttonSetCaption method:
f.buttonSetCaption("Click Here");
To create a tooltip that appears when the mouse hovers over the button, set its userName property:
f.userName = "This is a button tooltip for myButton.";
In addition to the text, it is also possible to specify the relative positioning of the icon and text on the buttons face. In this case, we will set the layout so that the icon appears to the left of the text:
f.buttonPosition = position.iconTextH;
To specify whether the button should be visible either on screen or when printing, set its display property:
f.display = display.visible;
To set the buttons appearance in response to user interaction, set its highlight property to one of the following values: none (highlight.n), invert (highlight.i), push (highlight.p), or outline (highlight.o). In this example, we will specify that the button appears to be pushed:
f.highlight = highlight.p;
It is possible to specify the scaling characteristics of the icon within the button face. You can determine when scaling takes place by setting the buttons buttonScaleWhen property to one of the following values: always (scaleWhen.always), never (scaleWhen.never), if the icon is too big (scaleWhen.tooBig), or if the icon is too small (scaleWhen.tooSmall). In this case, we will specify that the button always scales:
f.buttonScaleWhen = scaleWhen.always;
You can also determine whether the scaling will be proportional by setting the buttonScaleHow property to one of the following values: buttonScaleHow.proportional or buttonScaleHow.anamorphic. In this case, we will specify that the button scales proportionally:
f.buttonScaleHow = buttonScaleHow.proportional;
To guarantee that the icon scales within the bounds of the rectangular region for the button, set the buttonFitBounds property:
f.buttonFitBounds = true;
You can specify the alignment characteristics of the icon by setting its buttonAlignX and buttonAlignY properties. This is done by specifying the percentage of the unused horizontal space from the left or the vertical space from the bottom that is distributed. A value of 50 would mean that 50 percent of the unused space would be distributed to the left or bottom of the icon (centered). We will center our icon in both dimensions:
f.buttonAlignX = 50; f.buttonAlignY = 50;
Now that you have prepared the space within the button for the icon, you can import an icon into the document and place it within the buttons area. There are two methods for importing an icon for a button face and associating it with a button
Use the buttonImportIcon method of the Field object, this imports and associates in one step:
var retn = f.buttonImportIcon("/C/temp/myIcon.pdf"); if ( retn != 0 ) app.alert("Icon not imported");
If the argument of buttonImportIcon is empty, the user is prompted to choose an icon. This approach works for Adobe Reader.
Import the icon using the importIcon method of the Doc object, then associate the icon with the button using the buttonSetIcon method of the Field object.
this.importIcon({ cName: "myIconName", cDIPath: "/C/temp/myIcon.pdf", nPage: 0}); var myIcon = this.getIcon("myIconName"); f.buttonSetIcon(myIcon);
If the cDIPath parameter is specified, which is the case in this example, the importIcon method can only be executed in batch and console events; however, this restrictions can be bypassed using the techniques discussed in Executing privileged methods in a non-privileged context on page 45. When cDIPath is not specified, the script works for Adobe Reader. To rotate the button counterclockwise, set its rotation property:
f.rotation = 90;
Finally, you will undoubtedly wish to associate an action to be executed when the button is clicked. You can do this by invoking the setAction method of the Field object, which requires a trigger (an indication of the type of mouse event) and an associated script. The possible triggers are MouseUp, MouseDown, MouseEnter, MouseExit, OnFocus, and OnBlur. The following code displays a greeting when the button is clicked:
f.setAction("MouseUp", "app.alert('Hello');" );
userName readonly display rotation strokeColor fillColor lineWidth borderStyle textSize textColor
In the case of textFont, however, the font is always set to Adobe Pi.
The style property of the Field object is used to set the appearance of the check symbol that appears when the user clicks in the check box. Permissible values of the style property are check (style.ch), cross (style.cr), diamond (style.di), circle (style.ci), star (style.st), and square (style.sq). For example, the following code causes a check to appear when the user clicks in the check box:
f.style = style.ch;
The export value of the check box can be set using the exportValues property of the Field object. For example, the code below associates the export value "buy" with the check box:
var f = this.getField("myCheckBox"); f.exportValues=["buy"];
If there are several check box fields, you can indicate that one particular form field is always checked by default. To do this, you must do two things:
Invoke the defaultIsChecked method of the Field object. Note that since there may be several check boxes that belong to the same group, the method requires that you specify the zero-based index of the particular check box. Reset the field to ensure that the default is applied by invoking the resetForm method of the Doc object.
checkThisBox used to check a box isBoxChecked used test whether a check box is checked isDefaultChecked use to test whether the default setting is the one selected by user
You can specify whether the users custom text will be checked for spelling by setting its doNotSpellCheck property. The following code indicates that the spelling is not checked:
f.doNotSpellCheck = true;
A combo box can interact with the user in one of two ways: either a selection automatically results in a response, or the user first makes their selection and then takes a subsequent action, such as clicking a Submit button.
In the first case, as soon as the user clicks on an item in the combo box, an action can automatically be triggered. If you would like to design your combo box this way, then set its commitOnSelChange property to true. Otherwise, set the value to false. The following code commits the selected value immediately:
f.commitOnSelChange = true;
To set the export values for the combo box items, invoke its setItems method, which can be used to set both the face and export values. In this case, the face (or appearance) value (the value that appears in the combo box) is the first value in every pair, and the export value is the second. The following code results in the full state names appearing in the combo box (as the face or appearance values), and abbreviated state names as their corresponding export values:
f.setItems( ["Ohio", "OH"], ["Oregon", "OR"], ["Arizona", "AZ"] );
In many cases, it is desirable to maintain a sorted collection of values in a combo box. In order to do this, you will need to write your own sorting script. Recall that the JavaScript Array object has a sort method that takes an optional argument which may be a comparison function. This means that you must first define a compare function that accepts two parameters. The function must return a negative value when the first parameter is less than the second, 0 if the two parameters are equivalent, and a positive value if the first parameter is greater. In the following example, we define a compare function that accepts two parameters, both of which are user/export value pairs, and compares their user values. For example, if the first parameter is ["Ohio", "OH"] and the second parameter is ["Arizona", "AZ"], the compare function returns 1, since "Ohio" is greater than "Arizona":
function compare (a,b) { if (a[0] < b[0]) return -1; // index 0 means user value if (a[0] > b[0]) return 1; return 0; }
Create a temporary array of values and populate it with the user/export value pairs in your combo box field. The following code creates the array, iterates through the combo box items, and copies them into the array:
var arr = new Array(); var f = this.getField("myCombobox"); for (var i = 0; i < f.numItems; i++) arr[i] = [f.getItemAt(i,false), f.getItemAt(i)];
At this point you can invoke the sort method of the Array object and replace the items in the combo box field:
arr.sort(compare); // Sort the array using your compare method f.setItems(arr);
If the formatting category is set to None, then processing the combo box is easy. Whereas the combo box does not process its own change in value, another form element can easily read the current setting of the combo box. For example, if the name of the combo box is myComboBox, then the following code gets the current value:
var f = this.getField("myComboBox"); var valueCombo = f.value;
The variable valueCombo contains the export value of the combo box. You cannot, by the way, get the face value, if the export value is different from the face value. When the formatting category is set to Custom, there are two types of formatting scripts, Custom Keystroke Script and Custom Format Script. The Custom Keystroke Script has the following general form:
if (event.willCommit) { // Script that is executed when the choice is committed } else { // Script that is executed when the choice changes, or, if the // combox box is editable, when text is typed in. }
With regard to the Custom Keystroke Script, there are three event properties that can be read: value, change and changeEx. To illustrate these event properties, lets use the state combo box, defined above. Here is the Custom Keystroke Script:
if (event.willCommit) { console.println("Keystroke: willCommit") console.println("event.value = " + event.value); console.println("event.change = " + event.change); console.println("event.changeEx = " + event.changeEx); } else { console.println("Keystroke: not Committed") console.println("event.value = " + event.value); console.println("event.change = " + event.change); console.println("event.changeEx = " + event.changeEx); }
The results of this script are listed below. Assume the combo box is set on a face value of "Arizona" and you change the combo box to read "Ohio". Additional comments are inserted.
// Select Ohio, but not committed. Note that the value of event.value is still // set to "Arizona", but event.change is now set to the face value of the new // choice, and event.changeEx is set to the export value of the new selection. Keystroke: not Committed event.value = Arizona event.change = Ohio event.changeEx = OH // The choice is committed. Note that the value of event.value is now "Ohio" // and that event.change and event.changeEx are empty. Keystroke: willCommit event.value = Ohio event.change = event.changeEx =
The only difference between the above sequence of events when f.commitOnSelChange=false versus f.commitOnSelChange=true is that in the first case, after the user makes a (new) choice from the combo box (and the not committed script is executed), the user must press the Enter key or click on a white area outside the field to commit the change, at this point, the "willCommit" script will execute. When f.commitOnSelChange=true, these two blocks of code will execute one after the other, with the not committed code executing first. A combo box can also be editable. An editable combo box is one where the user is allowed to type in, or paste in, a selection. A combo box can be made editable by checking Allow User to Enter Custom Text in the Options tab of the Combo Box Properties dialog box. For JavaScript, the editable field property is used, as in the following example.
var f = this.getField("myComboBox"); f.editable = true;
The above output was captured in the console from a combo box that was not editable. The output is the same when the user selects one of the items in the combo box; when the user types in a selection, the output looks like this, assuming the user has already typed in the string "Te"and is now typing in "x":
/* Note that when the selection is not committed, event.changeEx is empty. You can test whether the user is typing in by using the conditional test if ( event.changeEx == "" ) {<type/paste in>} else {<select from list>} Note also that the value of event.value is "Te" and the value of event.change is "x"; the previous keystrokes and the current keystroke, respectively. When the user pastes text into the combo box, the length of event.change will be larger than one, if(event.change.length > 1 ) {<pasted text>} else {<typed text>} */ Keystroke: not Committed event.value = Te event.change = x event.changeEx = // ...Additional keystrokes to spell "Texas" // Once committed, this output is the same as when the combo box is not // editable. Keystroke: willCommit event.value = Texas event.change = event.changeEx =
Example 6.1
Suppose now you want to make the combo box editable, and ask to user to pick a state from the pop-up combo box, or to type in a state. You want to format the state entered by the user so that the first letter is capitalized, and the rest are lower case. The following script is used for the Custom Keystroke Script of the combo box:
if (event.willCommit) { // Test to be sure there something more than white spaces. if ( event.rc = !( event.value.replace(/\s/g,"") == "" )) { // On commit, split event.value into an array, convert to lower case // and upper case for the first letter. var aStr = event.value.split(" "); for ( var i=0; i<aStr.length; i++){
aStr[i] = aStr[i].charAt(0).toUpperCase() +aStr[i].substring(1,aStr[i].length).toLowerCase(); } // Join the separate words together, and return as the new value. event.value = aStr.join(" "); } } else { // User is typing in something, make sure it is a letter or space var ch = event.change; if ( ch.length==1 ) event.rc = (ch==" ") || (ch>="a" && ch<="z") || (ch>="A" && ch<="Z"); }
Format the combo box so that is reads "State of Ohio", for example. Custom format script:
event.value = "State of " + event.value;
If the user has pasted into the editable combo box, you can catch any non-letters or spaces with the validation script. A regular expression is used to see if there is something different from a letter or space. Custom validation script:
event.rc = !/[^a-zA-Z ]+/.test(event.value);
These various events, Keystroke, Format and Validate, define the rc property of the event object. In the above code, the event.rc is used to signal that the input is acceptable (true) or not acceptable (false). In this way, the input can be checked, validated, and formatted, or, at some stage, can be canceled by setting event.rc = false. Full documentation of the objects used in the above sample script can be found in the JavaScript for Acrobat API Reference.
The List Box Properties dialog box has a Selection Change tab, this corresponds to the "Keystroke" trigger of the combo box or text field. To enter script to process a change in the status of the list box, you can either use the UI, or you can install your script, like so,
f.setAction( "Keystroke", "myListboxJavascript();" );
In the above, the action is to simply call a JavaScript function, defined, perhaps, as document JavaScript.
The manner in which you process a selection change is the same as the combo box, with one exception.
// Note that unlike the combo box, the value of event.value is the export value // of the field, not the face value as it is with the combo box. Keystroke: not committed event.value = FL event.change = Arizona event.changeEx = AZ // When we commit, the value of event.value is the face value, not the export // value. Keystroke: willCommit event.value = Arizona event.change = event.changeEx =
You can allow the user to make multiple selections from a list box by checking the Multiple Selection check box in the Options tab of the List Box Properties dialog box, or you can make this selection using JavaScript:
var f = this.getField("myListBox"); f.multipleSelection=true;
It is not possible to detect multiple selection using a Selection Change script; however, multiple selection can be detected from another form field, such as a button. To get and set multiple values of the list box, use the currentValueIndices property of the Field object. The following example illustrates the techniques.
Example 6.2
This example accesses the list box which allows multiple selections. It simply reads the current value and reports to the console. When the current value of the list box is a single selection, currentValueIndices returns a number type (the index of the item selected); when there are multiple selections, currentValueIndices returns an array of indices.
var f = this.getField("myListBox"); var a = f.currentValueIndices; if (typeof a == "number") // A single selection console.println("Selection: " + f.getItemAt(a, false)); else {// Multiple selections console.println("Selection:"); for (var i = 0; i < a.length; i ++) console.println(" " + f.getItemAt(a[i], false)); }
The field method getItemAt is used to get the face values of the list, using the index value returned by currentValueIndices. Other relevant field properties and methods not mentioned in this section are numItems, insertItemAt, deleteItemAt and setItems. The JavaScript for Acrobat API Reference documents all these methods and supplies many informative examples.
Suppose the export values are export0, export1, export2, and export3. This is the simplest case, all choices are mutually exclusive; the behavior does not depend on whether Buttons With the Same Name and Value are Selected in Unison is checked. Now suppose the export values of the four radio buttons are export0, export1, export2, and export2. If f.radiosInUnison=false, the four buttons behave as in the simplest case above. If f.radiosInUnison=true, then there are only three mutually exclusive buttons; clicking either of the two radios with export value export2 will select both of them, while clicking the radio button with export value of export0 will select only that button.
Example 6.3
This example illustrates how you can programmatically access the individual radio buttons in the same radio group (all having the same name). Assume the command name is myRadio and there are four widgets in the field.
var f = this.getField("myRadio"); // Get the second widget, change its appearance and add an action var g = this.getField(f.name+".1"); g.strokeColor = color.red; g.setAction("MouseUp", "app.alert('Export value is ' + this.getField('myRadio').value)");
Some properties of the Field object, such as value, apply to all widgets that are children of that field. Other properties, such as strokeColor and setAction, are specific to individual widgets. See the section on the Field object in the JavaScript for Acrobat API Reference for a complete list of Field properties accessible at the widget level.
Example 6.4
Sometimes the number of widgets in a radio button field is unknown. The code below counts the number of widgets.
var f = this.getField("myRadio") var nWidgets=0; while(true) { if ( this.getField(f.name + "." + nWidgets) == null ) break; nWidgets++; } console.println("There are " + nWidgets + " widgets in this radio field");
Signature fields
Signature fields have the usual properties, as listed under the General and Appearance tabs of the Digital Signature Properties dialog box. These can be set in the standard way, by the UI or through JavaScript, as in this example:
var f = this.getField("Signature1); f.strokeColor = color.black;
When the signature field is signed, you may want to execute some script in response to this event. The script can be entered through the Signed tab of the Digital Signature Properties dialog box, or through the setAction method of the Field object. You can set the action of a signature field by invoking its setAction method and passing in the Format trigger name as the first parameter. When the user signs the form, you can reformat other form fields with the script you pass in to the setAction method. Once a document is signed, you may wish to lock certain form fields within the document. You can do so by creating a script containing a call to the signature fields setLock method and passing that script as the second parameter to the signature fields setAction method. The setLock method requires a Lock object, which you will obtain by invoking the form fields getLock method. Once you obtain the Lock object, set its action and fields properties. The action property can be set to one of 3 values: "All" (lock all fields), "Exclude" (lock all fields except for these), or "Include" (lock only these fields). The fields property is an array of fields. For example, suppose you created a signature and would like to lock the form field whose name is myField after the user signs the document. The following code would lock myField:
var f = this.getField("Signature1"); var oLock = f.getLock(); oLock.action = "Include"; oLock.fields = new Array("myField"); f.setLock(oLock);
To actually sign a document, you must do two things: choose a security handler, and then invoke the signature fields signatureSign method. The following code is an example of how to choose a handler and actually sign the document:
var f = this.getField("Signature1"); var ppklite = security.getHandler("Adobe.PPKLite"); var oParams = { cPassword: "myPassword", cDIPath: "/C/signatures/myName.pfx" // Digital signature profile }; ppklite.login(oParams); f.signatureSign(ppklite, { password: "myPassword", location: "San Jose, CA", reason: "I am approving this document", contactInfo: "userName@adobe.com", appearance: "Fancy" } ); //End of signature ppklite.logout()
Text fields
The text field has many of the same properties as buttons and combo boxes. In addition, it offers the following specialized properties shown in the following table. (The table assumes that f is the field object of a text field.)
Description Justify text Limit on number of characters in area Comb of characters subject to limitation set by charLimit Set a default text string Permit scrolling of long text Set spell checking Format field as a file path Allow multiple lines in the area Use special formatting to protect the users password Set rich text formatting
Example
f.alignment = "center"; f.charLimit = 40; f.comb = true;
f.defaultValue = "Name: "; f.doNotScroll = true; f.doNotSpellCheck = true; f.fileSelect = true; f.multiline = true; f.password = true;
richText
f.richText = true;
When the user enters data into a text field, the usual event object can be queried to process the keystrokes, the behavior is similar to the combo box. In the output below, assume the user has already typed in the "Te" and types in the letter "x":
// The value of event.value is the current text in text field, event.change has // the current keystroke. Note that event.changeEx is always empty, and is not // relevant to the text field. Keystroke: not Committed event.value = Te event.change = x event.changeEx = Keystroke: willCommit event.value = Texas event.change = event.changeEx =
Use the Custom Keystroke Script to intercept user keystrokes and process them. For example, the following script changes all input to upper case: Custom Keystroke Script:
if (!event.willCommit) event.change = event.change.toUpperCase();
Validation scripts
You can enforce valid ranges, values, or characters entered in form fields. The main reason to use validation is to ensure that users are only permitted to enter valid data into a form field. Validation is used whenever the user enters text into a form field, for text fields and for editable combo boxes. Enter the validation script through the Validation tab of the Text Field Properties dialog box, or through the setAction method of the Field object. In the latter case, pass Validate as the first parameter, as follows:
var f = this.getField("myText"); f.setAction("Validate", "myValidateRange(true, -1, true, 5)");
Example 6.5
This is a simple example of a Custom Keystroke Script for inputting a number, and a simple validation script for checking the range of the number. Custom Keyboard Script:
if ( event.willCommit ) { var value = ""+event.value.replace(/\s*/g,""); if ( value != "" ) { if (!isFinite(value)) { app.beep(0); event.rc = false; } } } else if ( event.change == " " ) event.change = "";
which checks whether the value entered is strictly between -1 and 5. The validation script calls the following document JavaScript:
function myRangeCheck(bGreater, nGreater, bLess, nLess) { value = event.value; if ( bGreater && ( value <= nGreater ) ) { app.alert("Value must be greater than " + nGreater); app.beep(); event.rc = false; return; } if ( bLess && ( value >= nLess ) ) { app.alert("Value must be less than " + nLess); app.beep(); event.rc = false; return; } }
Calculation script
Calculation options make it possible to automate mathematical calculations associated with form fields. To apply a calculation to a form field action, enter the script through the Calculate tab of the Text Field Properties dialog box. On this tab there are three options: 1. The value is the sum(+)/product(x), average/minimum/maximum of a specified collection of fields. 2. The value is the result of simplified field notation. 3. The value is the result of a Custom Calculation Script. Options (1) and (2) are entered through the UI, option (3) is entered through the UI or through the setAction method of the Field object. If you use the setAction method, pass "Calculate" as the first parameter, and pass a script containing a call to a calculation script as the second parameter. The calculation script makes all necessary calculations, perhaps drawing values from other text fields, then reports the calculated value to the field by setting event.value.
Example 6.6
The script presented here calculates the average of several text fields. If one of the fields has no value, it is not figured into the average. The example assumes all fields require a number for their value. The following script is entered as a custom calculation script:
var aNumFields = new Array("Text1.0", "Text1.1", "Text1.2","Text1.3", "Text1.4"); myAverageFunction(aNumFields);
The script above simply calls the myAverageFunction, it is this function that calculates the average of the array of fields passed as its argument, and sets event.value. The function is placed in the document as document JavaScript.
function myAverageFunction(aNumFields) { // n = number of fields that have a numerical value var n=0, sum = 0; for ( var i=0; i<aNumFields.length; i++) { var v = this.getField(aNumFields[i]).value; if ( v != "" ) { n++; sum += v; } } if ( n == 0 ) event.value = ""; else event.value = sum/n; }
Task-based topics
In this section, common problems/tasks are presented, including such topics as highlighting required fields, positioning form fields, duplicating form fields, importing and exporting form data and global variables.
Example 6.7
Create two buttons in a document containing form fields. One button has the JavaScript mouse up action
showRequired();
that will highlight all required fields, the other button has the following mouse up action
restoreRequired();
that restores the fields to the appearance state they were in before the showRequired() function executed. The script that follows is a document-level JavaScript that defines the functions called by the two buttons.
var oFieldNames = new Object(); // used to save the appearance of the fields function showRequired() { // Search through all fields for those that are set to required, excluding // any button fields. for ( var i=0; i < this.numFields; i++) { var fname = this.getNthFieldName(i); var f = this.getField(fname); if ( (f.type != "button") && f.required) { // Save appearance data in oFieldNames oFieldNames[fname]={ strokeColor: f.strokeColor, fillColor: f.fillColor}; // Assign a red boundary color, and fill color f.strokeColor=color.red; f.fillColor=app.runtimeHighlightColor; } } } // Now restore the fields. function restoreRequired() { if ( typeof oFieldNames == "object") { for ( var o in oFieldNames ) { var f = this.getField(o); f.strokeColor=oFieldNames[o].strokeColor; f.fillColor=oFieldNames[o].fillColor; } } oFieldNames = new Object(); }
If you would like a combo box to be enabled for typing, set its editable property to true, as shown in the following code:
f.editable = true;
The above code changes the text color of each of the two fields to red. By changing the field names, a hierarchy of fields within the document can be created. For example, "Name.First" and "Name.Last" forms a tree of fields. The period (.) separator in Acrobat forms denotes a hierarchy shift. "Name" in these fields is the parent; "First" and "Last" are the children. Also, the field "Name" is an internal field because it has no visible appearance. "First" and "Last" are terminal fields that appear on the page. Acrobat form fields that share the same name also share the same value. Terminal fields can have different presentations of that data. For example, they can appear on different pages, be rotated differently, or have a different font or background color, but they have the same value. Therefore, if the value of one presentation of a terminal field is modified, all others with the same name are updated automatically. To repeat the above example using the naming scheme of "Name.First" and "Name.First", the code is
var f = this.getField("Name"); f.textColor=color.red;
This changes the text color of both fields to red. Of course, if you with to give the two fields different text colors, then you reference each field individually,
var f = this.getField("Name.First"); f.textColor = color.red; var f = this.getField("Name.Last"); f.textColor = color.blue;
Each presentation of a terminal field is referred to as a widget. An individual widget does not have a name but is identified by index (0-based) within its terminal field. The index is determined by the order in which the individual widgets of this field were created (and is unaffected by tab-order).
You can determine the index for a specific widget by using the Fields navigation tab in Acrobat. The index is the number that follows the # sign in the field name shown. (In Acrobat 6.0 or later, the widget index is displayed only if the field has more than one widget.) You can double-click an entry in the Fields panel to go to the corresponding widget in the document. Alternatively, if you select a field in the document, the corresponding entry in the Fields panel is highlighted. Beginning with Acrobat 6.0, getField can be used to retrieve the Field object of one individual widget of a field. This notation consists of appending a period (.) followed by the widget index to the field name passed. When this approach is used, the Field object returned by getField encapsulates only one individual widget. You can use the Field objects returned this way anywhere you would use a Field object returned by passing the unaltered field name. For example, suppose you have four text fields all with the same name of "myTextField". Executing the following code changes the text color of all four fields to red.
this.getField("myTextField").textColor=color.red;
To change the text color of an individual field, you would execute the following code:
this.getField("myTextField.1").textColor=color.blue;
This code changes the text color of the text in the second field, the one labeled as "myTextField#1" in the Fields navigation tab, to blue. The technique of referencing individual widgets is especially useful with radio button fields, see Radio button fields on page 81 for additional discussion and examples. Some properties of the Field object, such as value, apply to all widgets that are children of that field. Other properties, such as textColor and setAction, are specific to individual widgets. See the section on the Field object in the JavaScript for Acrobat API Reference for a complete list of Field properties accessible at the widget level.
Creating forms
In this section you learn how to create a form field using the Doc object addField method. Topics include: Topics Positioning form fields Duplicating form fields Creating multiple form fields Page page 88 page 89 page 90
In this example, we will position a 1 inch by 2 inch form field 0.5 inches from the top of the page and 1 inch from the left side:
// 1 inch = 72 points var inch = 72; // Obtain the page coordinates in Rotated User Space var aRect = this.getPageBox({nPage: 2}); // Position the top left corner 1 inch from the left side aRect[0] += 1 * inch; // Make the rectangle 1 inch wide aRect[2] = aRect[0] + 1*inch; // The top left corner is 0.5 inch down from the top of the page aRect[1] -= 0.5*inch; // Make the rectangle 2 inches tall aRect[3] = aRect[1] - 2*inch; // Draw the button var f = this.addField("myButton", "button", 2, aRect);
Normally, when you create a form field, you do so using the UI; creating a form field using the addField has limited applications because the exact positioning of the field on the page (and relative to its content) is usually not known. The addField method is useful in situations when you either know the positioning of the field, or you can acquire that information from another method; Example 6.8 on page 89 illustrates the use of addField when the positioning of the fields are known in advance.
Example 6.8
The script that follows can be executed in the console, or it can be used as batch sequence JavaScript. Additional customizations are possible.
var var var var var var aPage = this.getPageBox(); w = 45; // Width of each button h = 12 // Height of each button nNavi = 4; // Number of buttons to be placed g = 6; // Gap between buttons totalWidth = nNavi * w + (nNavi - 1) * g; // total width of navi bar = aPage[2] - aPage[0]; offset to center navi bar (widthPage - totalWidth) / 2; 12; // vertical offset from bottom
for (var nPage = 0; nPage < this.numPages; nPage++) { // Create the fields var pp = this.addField("PrevPage", "button", nPage, [ hoffset, voffset, hoffset + w, voffset + h ] ); pp.buttonSetCaption(pp.name); pp.fillColor=color.ltGray; pp.setAction("MouseUp", "this.pageNum--"); var np = this.addField("NextPage", "button", nPage, [ hoffset + w + g, voffset, hoffset + 2*w + g, voffset + h ] ); np.buttonSetCaption(np.name); np.fillColor=color.ltGray; np.setAction("MouseUp", "this.pageNum++"); var pv = this.addField("PrevView", "button", nPage, [ hoffset + 2*w + 2*g, voffset, hoffset + 3*w + 2*g, voffset + h ] ); pv.buttonSetCaption(pv.name); pv.fillColor=color.ltGray; pv.setAction("MouseUp", "app.goBack()"); var nv = this.addField("NextView", "button", nPage, [ hoffset + 3*w + 3*g, voffset, hoffset + 4*w + 3*g, voffset + h ] ); nv.buttonSetCaption(nv.name); nv.fillColor=color.ltGray; nv.setAction("MouseUp", "app.goForward()"); }
To set the tab order on each page of the document, you would execute a script like this:
for (var i = 0; i < this.numPages; i++) this.setPageTabOrder(i, "rows");
The equivalent MIME types for all posted form data are shown in the following table.
To send the exported FDF data automatically, pass false to the first parameter, and specify the cTO, cCc, cBcc, cSubject, and cMsg fields (all of which are optional), as shown in the code below:
this.mailForm(false, ); this.mailForm({ bUI: false, cTo: "recipient@example.com", cSubject: "You are receiving mail", cMsg: "A client filled in your online form and " + "submitted the attached data." })
Unless this command is executed in a privileged context, see Privileged versus non-privileged context on page 45, the mail client will appear to the user.
To convert a Date object into a string, the printd method of the util object is used. Unlike the built-in conversion of the Date object to a string, printd allows an exact specification of how the date should be formatted.
/* Example of util.printd */ var d = new Date(); // Create a Date object containing the current date /* Create some strings from the Date object with various formats with ** util.printd */ var s = [ "mm/dd/yy", "yy/m/d", "mmmm dd, yyyy", "dd-mmm-yyyy" ]; for (var i = 0; i < s.length; i++) { /* Print these strings to the console */ console.println("Format " + s[i] + " looks like: " + util.printd(s[i], d)); }
Note: You should output dates with a four digit year to avoid ambiguity.
Unlike the date constructor (new Date(...)), scand is rather forgiving in terms of the string passed to it. Note: Given a two digit year for input, scand resolves the ambiguity as follows: if the year is less than 50 then it is assumed to be in the 21st century (i.e. add 2000), if it is greater than or equal to 50 then it is in the 20th century (add 1900). This heuristic is often known as the Date Horizon.
Date arithmetic
It is often useful to do arithmetic on dates to determine things like the time interval between two dates or what the date will be several days or weeks in the future. The JavaScript Date object provides several ways to do this. The simplest and possibly most easily understood method is by manipulating dates in terms of their numeric representation. Internally, JavaScript dates are stored as the number of milliseconds (one thousand milliseconds is one whole second) since a fixed date and time. This number can be retrieved through the valueOf method of the Date object. The Date constructor allows the construction of a new date from this number.
/* Example of date arithmetic. */ /* Create a Date object with a definite date. */ var d1 = util.scand("mm/dd/yy", "4/11/76"); /* Create a date object containing the current date. */ var d2 = new Date(); /* Number of seconds difference. */ var diff = (d2.valueOf() - d1.valueOf()) / 1000; /* Print some interesting stuff to the console. */ console.println("It has been " + diff + " seconds since 4/11/1976"); console.println("It has been " + diff / 60 + " minutes since 4/11/1976"); console.println("It has been " + (diff / 60) / 60 + " hours since 4/11/1976"); console.println("It has been " + ((diff / 60) / 60) / 24 + " days since 4/11/1976"); console.println("It has been " + (((diff / 60) / 60) / 24) / 365 + " years since 4/11/1976");
When checked, the default, each time a global variable is written to, the origin which set it is remembered. Only origins that match can then access the variable.
For files, this means only the file that set it, having the same path it had when the variable was set, can access the variable. For documents from URLs it means only the host which set it can access the variable. There is an important exception to the restrictions described above, global variables can be defined and accessed in a privileged context, in the console, in a batch sequence and in folder JavaScript. A global variable set at the folder level can be accessed at the folder level, or from within the console.
When not checked, documents from different origins are permitted to access the variable; this is the behavior previous to version 8.0.
Additional discussion and examples, see Global object security policy on page 98.
The life of this variable ends when the application is closed. In versions of Acrobat previous to 8.0, any document open in Acrobat (or Adobe Reader) had access to any global variable and its value. This same behavior can be maintained in version 8 provided the item Enable Global Object Security Policy, found in the JavaScript section of the Preference, is unchecked. When checked, however, which is the default, a global variable is restricted to only that document that created the global variable in the case of viewing PDF files in Acrobat or Adobe Reader, or to only those documents that come from the same web host where the global variable was set. See the JavaScript for Acrobat API Reference for a more detailed description of this policy.
In future sessions, the variable will still exist with its previous value intact. Beginning with Acrobat version 8, there is a new security policy for global variables that applies to global persistent variables as well. See the description above of this policy for more details.
Then, when your document (Document B) wants to access the value of interest from the other form (Document A), it can subscribe to the variable in question:
global.subscribe("xyz_value", ValueUpdate);
In this case, ValueUpdate refers to a user-defined function that is called automatically whenever xyz_value changes. If you were using xyz_value in Document B as part of a field called MyField, you might define the callback function this way:
function ValueUpdate( newValue ) { this.getField("MyField").value = newValue;}
Beginning with version 8.0 of Acrobat, there is a new security policy for global variables that applies to global variables. For the above solution to work, the Enable Global Object Security Policy, found in the JavaScript section of the Preferences, is unchecked, or both documents must be served from the same web host. See the previous description of this policy for more details.
The path for docA.pdf is the origin saved with the global.x variable; consequently, docA.pdf can access this variable:
console.println("global.x = " + global.x);
To set this global from docA.pdf, we execute global.x = 3, for example, in any context. To have a document with a different path get and set this global variable, the getting and setting must occur in a trusted context, with a raised level of privilege. The following scripts are folder JavaScript.
myTrustedGetGlobal = app.trustedFunction ( function() { app.beginPriv(); var y = global.x; return y app.endPriv(); }); myTrustedSetGlobal = app.trustedFunction ( function(value) { app.beginPriv(); global.x=value; app.endPriv(); });
Another document, docB.pdf can access the global.x variable through the above trusted functions:
// Mouse up button action from doc B console.println("The value of global.x is " + myTrustedGetGlobal());
Once global.x has been set from docB.pdf, the origin is changed; docA.pdf cannot access global.x directly unless it is through a trusted function:
// Execute a mouse up button action from docA.pdf console.println("The value of global.x is " + myTrustedGetGlobal());
To make a custom color, just declare an array containing the color-space type and channel values you want to use.
Dynamic XFA indicates that the content will be defined later after binding to a template. This also means that the following is possible:
Form fields may be moved or resized. Form fields automatically grow or shrink according to the amount of text added or removed. As a form field grows, it can span multiple pages. Repeating subforms may be spawned as needed, and page contents shifted accordingly. Elements on the page are shown or hidden as needed.
To take advantage of the rich forms functionality offered by the XFA plug-in, use Adobe LiveCycle Designer to create or edit the templates, and save your forms in the XML Data Package format (XDP) or as a PDF document. Use XDP if the data is processed by server applications, and PDF if the data is processed by Acrobat.
Dynamic tooltips
XFA forms support dynamic tooltips, including support for individual radio buttons in a group.
Description Returns the node represented by the alias for this model. Returns all nodes with the same name or class. Returns xfa. Returns all nodes with the same class name. Returns the position of this node in the collection of nodes having the same class name. Returns the class name of the object. Returns the current node (needed for resolveNode and resolveNodes). Returns the ID of the current node. Returns the position of this node in the collection of nodes having the same name. Returns true if this is a container object. Returns true if the node has a null value. Returns the XFA model for this node. Returns the name of this node. Returns a list of child nodes for this node. Returns the namespace for this node (or XFAModel). Retrieves or sets the child that has the XFA::oneOfChild relationship to its parent. Retrieves the parent of this node. Retrieves the SOM expression for this node. Retrieves the current node (starting node for resolveNode and resolveNodes).
Description Performs an XSL transformation of the current node Sets the value of the node, and creates one if necessary Clears the current list of errors Clones a node (and its subtree if specified) Creates a new XFA node based on a valid classname Retrieves a specified attribute value Retrieves a specified property element Determines if two namespaces are equivalent Checks if a specific property has been defined for the node Loads and appends the current XML document to the node Obtains the node corresponding to the SOM expression Obtains the XFATreeList corresponding to the SOM expression Saves the current node to a string Sets a specified attribute value Sets a specified property element
The XFA DOM model contains a root object that consists of either a treeList or a Tree. A treeList consists of a list of nodes (which is why it is sometimes called a NodeList). A Tree consists of a hierarchical structure of nodes, each of which may contain content, a model, or a textNode. The following properties and methods are available in a treeList object: Properties:
length
Methods:
append, insert, item, namedItem, remove
The following properties and methods are available in a Tree object: Properties:
all, classAll, classIndex, index, name, nodes, parent, somExpression
Methods:
resolveNode, resolveNodes
Each Node element represents an element and its children in the XML DOM. To obtain a string representation of the node, invoke its saveXML method. To apply an XSL transform (XSLT) to the node and its children, invoke its applyXSL method. The following properties and methods are available in a Node object: Properties:
id, isContainer, isNull, model, ns, oneOfChild
Methods:
applyXSL, assignNode, clone, getAttribute, getElement, isPropertySpecified, loadXML, saveXML, setAttribute, setElement
There are two approaches to accessing content in an XML stream. In the first approach, XFA syntax may be used to manipulate the XML DOM. In the second approach, you can use standard XPath syntax. The XMLData object provides two methods useful for manipulating XML documents: applyXPath and parse. The applyXPath permits the manipulation of an XML document via an XPath, and the parse method creates an object representing an XML document tree. Both of these return an XFA object. The first approach involves the usage of the parse method of the XFAData object for accessing and manipulating XML streams. The second approach involves the usage of the applyXPath method of the XFAData object. Both approaches are illustrated below. In this first example, the usage of the parse method is illustrated below. We create our XML data using an Acrobat 8.0 specific feature, E4X (ECMA-357).
// Create the XML stream using E4X var myXML = <purchase> <product> <price>300</price> <name>Media Player</name> </product> <product> <price>49.95</price> <name>case</name> </product> </purchase> // Now convert to a string so we can use XMLData.parse() var parseString = myXML.toXMLString() // Now create the DOM var x = XMLData.parse(parseString);
Now verify the price has changed by executing the loop listed above. This is the output to the console:
---------------------Name: Media Player Price: 400 ---------------------Name: case Price: 49.95 ----------------------
This next example accomplishes the same task through the applyXPath method:
// Create the XML stream using E4X var myXML = <purchase> <product> <price>300</price> <name>Media Player</name> </product> <product> <price>49.95</price> <name>case</name> </product> </purchase> // Now convert to a string so we can use XMLData.parse() var parseString = myXML.toXMLString() // Now create the DOM var x = XMLData.parse(parseString,false); // Set up the XPath expression var xPathExpr = "//purchase/product[name='iPod']/price"; // Now get the media player price var price = XMLData.applyXPath(x, xPathExpr); // Give the media player price a new price price.value = "400";
For additional details on the use of JavaScript within XML forms created by LiveCycle Designer, see the document Converting Acrobat JavaScript for Use in LiveCycle Designer Forms, available through the Acrobat Family Developer Center.
Example 6.9
The following script can be used as a batch sequence to find all PDF documents, from a given collection, that are XML forms documents (created by LiveCycle Designer). The script reports the file name to the console along with its classification as a dynamic or static XML form, or an Acrobat form.
// This script assumes you are using Acrobat 8.0. console.println("Document name: " + this.documentFileName); // The xfa object is undefined in an Acrobat form. if ( typeof xfa == "object" ) { if ( this.dynamicXFAForm ) console.println(" This is a dynamic XML form."); else console.println(" This is a static XML form."); if ( this.XFAForeground ) console.println(" This document has imported artwork"); } else console.println(" This is an Acrobat Form.");
To take advantage of XFA functionality, you can save your forms in the XML Data Package format (XDP). This simply requires the usage of the conversion ID for XDP, as shown in the code below:
this.saveAs("myDoc.xml", "com.adobe.acrobat.xdp");
Global submit
Suppose you have a document that contains multiple attachments, from which you would like to compile information for submission to a server in XML format. You can create a global submit button whose mouse up action contains a script that collects the data from each of the attachments and creates a unified collection in XML format. To do this, you will need to invoke the Doc object openDataObject method in order to open the attachments, followed by its submitForm method to upload the combined XML data to the server. The following example merges the data from several XML form attachments and submits it to a server:
var oParent = event.target; // Get the list of attachments: var oDataObjects = oParent.dataObjects; if (oDataObjects == null) app.alert("This form has no attachments!"); else { // Create the root node for the global submit: var oSubmitData = oParent.xfa.dataSets.createNode( "dataGroup", "globalSubmitRootNode" ); // Iterate through all the attachments: var nChildren = oDataObjects.length; for (var iChild = 0; iChild < nChildren; i++) { // Open the next attachment: var oNextChild = oParent.openDataObject( oDataObjects[iChild].name ); // Transfer its data to the XML collection: oSubmitData.nodes.append( oNextChild.xfa.data.nodes.item(0) ); close the attachment// oNextChild.closeDoc(); }
// Submit the XML data collection to the server oParent.submitForm({ cURL: "http://theserver.com/cgi-bin/thescript.cgi", cSubmitAs: "XML", oXML: oSubmitData }); }
Text-to-speech
In order for text-to-speech engines to be able to work with your document, it must be structured. You can create structured documents using Adobe FrameMaker 7.0 or Adobe FrameMaker SGML 6.0 running in structured mode. To access the text-to-speech engine with JavaScript, use the TTS object, which has methods to render text as digital audio and present it in spoken form to the user. For example, the following code displays a message stating whether the TTS engine is available:
console.println("TTS available: " + tts.available);
The next code sample illustrates how to enumerate through all available speakers, queue a greeting into the TTS object for each one, and present the digital audio version of it to the user:
for (var i=0; i < tts.numSpeakers; i++) { var cSpeaker = tts.getNthSpeakerName(i); console.println("Speaker[" + i + "] = " + cSpeaker); tts.speaker = cSpeaker; tts.qText("Hello"); tts.talk(); }
The properties and methods of the TTS object are summarized in the following two tables, TTS properties and TTS methods, see JavaScript for Acrobat API Reference for more details.
TTS properties
Property
available numSpeakers pitch speaker speechRate volume
Description Returns true if the text-to-speech engine is available. Returns the number of speakers in the engine. The baseline pitch between 0 and 10. A speaker with desired tone quality. The rate in words per minute. The volume between 0 and 10.
TTS methods
Method
getNthSpeakerName pause qSilence qSound qText reset resume stop talk
Description Retrieves the Nth speaker in the current text-to-speech engine. Pauses the audio output. Queues a period of silence into the text. Inserts a sound cue using a .wav file. Inserts text into the queue. Stops playback, flushes the queue, and resets all text-to-speech properties. Resumes playback on a paused TTS object. Stops playback and flushes the queue. Sends queue contents to a text-to-speech engine.
Tagging annotations
Tagged files provide the greatest degree of accessibility, and are associated with a logical structure tree that supports the content. Annotations can be dynamically associated with a new structure tree that is separate from the original content of the document, thus supporting accessibility without modifying the original content. The annotation types supported for accessibility are:
Text, FreeText, Line, Square, Circle, Polygon, Polyline, Highlight, Underline, Squiggly, Strikeout, Stamp, Caret, Ink, Popup, FileAttachment, Sound
To add an accessible tag, select Advanced > Accessibility and choose Add Tags to Document.
Document metadata
The metadata for a document can be specified using File > Properties > Description. When a document is opened, saved, printed, or closed by a screen reader, the document title is spoken to the user. If the title has not been specified in the document metadata, then the file name is used. Often, file names are abbreviated or changed, so it is advised that the document author specify a title. For example, if a document has a file name of IRS1040.pdf, a good document title would be Form 1040: U.S. Individual Income Tax Return for 2006. In addition, third-party screen readers usually read the title in the window title bar. You can specify what appears in the window title bar by using File > Properties > Initial View and in the Window Options, choose to Show either the file name or document title. Providing all of the additional metadata associated with a document (Author, Subject, Keywords) also makes it more easily searchable using Acrobat Search and Internet search engines.
Short description
Every field that is not hidden must contain a user-friendly name (tooltip). The tooltip is accessible through the UI or through the Field object userName property. The tooltip name is spoken when a user acquires the focus to that field and should give an indication of the fields purpose. For example, if a field is named name.first, a good short description would be First Name. The name should not depend on the surrounding context. For instance, if both the main section and spouse section of a document contain a First Name field, the field in the spouse section might be named Spouse's First Name. This description is also displayed as a tooltip when the user positions the mouse over the field.
Reading order
The reading order of a document is determined by the Tags tree. In order for a form to be used effectively by a visually impaired user, the content and fields of a page must be included in the Tags tree. The Tags tree can also indicate the tab order for the fields on a page.
The properties and methods of the security object are described in the following two tables.
Security properties
Property
handlers validateSignaturesOnOpen
Description Returns an array of security handler names User preference to be automatically validated when document opens
Security methods
Method
chooseRecipientsDialog chooseSecurityPolicy
Description Opens a dialog box to choose a list of recipients Displays a dialog box to allow a user to choose from a list of security policies, filtered according to the options. Saves a Certificate object to a local disk Obtains a security handler object Returns the list of security policies currently available, filtered according to the options specified. Reads in a Certificate object from a local disk
importFromFile
See the JavaScript for Acrobat API Reference for documentation on these properties and methods.
page 115
Managing comments
Methods of managing comments: gathering and sorting, page 119 importing and exporting, and saving to an Excel spreadsheet. Describes the Hanko approval workflow, used for Japanese document workflow. page 122
Annotation types
Each annotation has a JavaScript type. In the paragraphs that follow, the relation between each UI name and its corresponding type is delineated. UI tool name Sticky Note tool Text Box tool Highlight Text tool Type
Text FreeText HighLight
112
UI tool name Cross-Out Text tool Underline Text tool Stamp tool Cloud tool. Polygon tool Arrow tool Rectangle tool Pencil Tool Oval Tool Attach a File as a Comment tool Record Audio Comment tool Polygon Line tool
Type
StrikeOut Underline Stamp Polygon Line Square Ink Circle FileAttachment Sound PolyLine
When the user makes a comment using the UI, the name of the comment is randomly assigned. As a consequence, unless the annotation is created with the addAnnot method, in which the name of the annot can be assigned at the time of creation, the name is not typically known to the developer. In normal workflows, the problem is to gather all comments in a document and process them in some way. The tool for doing this is getAnnots. The method returns an array of Annotation objects based on the search parameters, all of which are optional:
nPage - The page number to search for annotations, if not provided, the whole document is searched. nSortBy - The method used to sort the search results, these include page, author, and modification
date.
bReverse - If true, the array is reverse-sorted. nFilterBy - Get anntotations satisfying certain criteria, such as getting only those annotations that
can be printed, that can be viewed, or that can be edited. Additional discussion can be found in Sorting comments on page 120. See the JavaScript for Acrobat API Reference for full descriptions of these parameters.
The following code retrieves all annotations in the document, and sorts them by author name:
var annots = this.getAnnots({ nSortBy: ANSB_Author }); console.println("\nAnnot Report for document: " + this.documentFileName); if ( annots != null ) { console.show(); console.println("Number of Annotations: " + annots.length); var msg = " %s in a %s annot said: \"%s\""; for (var i = 0; i < annots.length; i++) console.println(util.printf(msg, annots[i].author, annots[i].type, annots[i].contents)); } else console.println(" No annotations in this document.");
Refer to the JavaScript for Acrobat API Reference for full descriptions of the properties specified above. All annotations can be constructed in this way, in the case of sound and file attachment annotations, there is no JavaScript method for associating a recording with a sound annotation or a file with a file attachment.
The object literal, myProps, can be used again to change the properties of a collection of annotations, perhaps ones returned by the getAnnots, as discussed in Getting annotation data on page 113.
Email the document to all reviewers, and import the returned comments into the original document. Set up an automated email-based review. Set up an automated browser-based review through the use of a shared server. Initiate an email-based approval workflow. Initiate an JavaScript-based review. Page page 115 page 116 page 116 page 118 page 119
Online collaboration essentials topics Reviewing documents with additional usage rights Emailing PDF documents JavaScript-based collaboration driver Spell-checking in comments and forms Approval
The following code allows full and unrestricted access to the entire document for one set of users (importantUsers), and allows high quality printing for another set of users (otherUsers):
var sh = security.getHandler("Adobe.PPKMS"); var dir = sh.directories[0]; var dc = dir.connect(); dc.setOutputFields({oFields:["certificates","email"]}); var importantUsers = dc.search({oParams:{lastName:"Smith"}}); var otherUsers = dc.search({oParams:{lastName:"Jones"}}); this.encryptForRecipients({ oGroups:[ { userEntities: importantUsers,
permissions: { allowAll: true } }, { userEntities: otherUsers, permissions: { allowPrinting: "highQuality" } } ], bMetaData: true }); eMailList = ""; for ( var i=0; i < importantUsers.length; i++) eMailList += (importantUsers[i].email + ","); for ( var i=0; i<otherUsers.length; i++) eMailList += (otherUsers[i].email + ","); // Now email the secured document. this.mailDoc({ cTo: eMailList, cSubject: "For your eyes only", cMsg: "Please review for the meeting on Friday." })
Note: For Windows systems, the default mail program must be MAPI-enabled.
The addStateModel method is used to add a new state model to Acrobat describing the possible states for an annot object using the model, and the removeStateModel method removes the model, though it does not affect previously created annot objects. Their usage is shown in the code below:
// Add a state model, this script can be placed at the folder level to // install a custom state model for enterprise users, for example. try{ var myStates = new Object; myStates["initial"] = {cUIName: "Havent reviewed it"}; myStates["approved"] = {cUIName: "I approve"}; myStates["rejected"] = {cUIName: "Forget it"}; myStates["resubmit"] = {cUIName: "Make some changes"}; Collab.addStateModel({ cName: "ReviewStates", cUIName: "My Review", oStates: myStates, cDefault: "initial" }); } catch(e){console.println(e);} // Now transition all annots to the "rejected" state. var myAnnots = this.getAnnots(); for ( var i=0; i<myAnnots.length; i++ ) myAnnots[i].transitionToState("ReviewStates", "rejected"); // Now remove the state model. try {Collab.removeStateModel("ReviewStates");} catch(e){console.println(e);}
You can also use the SOAP objects connect, request, and response methods to create customized commenting and review within browser-based workflows. You can do this by setting up a SOAP-based annotation store on the server using the Collab objects addAnnotStore and setStoreSettings methods. The Collab objects addAnnotStore method requires three parameters:
cIntName The internal name for the annotation store. cDispName The display name for the annotation store. cStore The definition for the new Collab store class.
The new Collab store class must contain the following definitions for the functions used to add, delete, update, and enumerate through the array of annotations:
enumerate Communicates with the web service to request the array of annotations stored on the
server. It is used when the PDF document is loaded for online review, or when the user clicks Upload or Send on the Commenting toolbar.
complete Passes the annotation data to the collaboration server so that it can be updated. update Uploads new and modified annotations to the server.
The class SDKSampleSOAPAnnotStore, as shown in the sample code below, is defined in sdkSOAPCollabSample.js in the Acrobat SDK, and contains complete definitions of the three functions described above.
The sample code below provides a standard example of how to use the SOAP and Collab objects to customize your online collaborative review. Note that all of the reviewers must have a copy of the JavaScript collaboration store code. In Acrobat 7.0 and later, the Custom collaboration store type allows you to put the JavaScript on the server. The store type used is CUSTOM, and the setting is a URL to the JavaScript file:
// Here is the URL for a SOAP HTTP service: var mySetting = "http://sampleSite/comments.asmx?WSDL"; // Here is the internal name for the collaborative store: var myType = "mySOAPCollabSample"; // Set the connection settings for the SOAP collab store: Collab.setStoreSettings(mySetting, myType); // Set the default collab store: Collab.defaultStore = myType; // Add the collab store to the Acrobat Collab servers: if (typeof SOAPFileSys == "undefined") Collab.addAnnotStore( myType, "SOAP Sample", { // Annot store instantiation function is required: create: function(doc, user, settings) { if (settings && settings != "") return new SDKSampleSOAPAnnotStore( doc, user, settings ); else return null; } } );
Approval
Approval workflows may include an automated process in which a PDF document is automatically sent via email to a recipient for their approval. For example, this may be accomplished through the usage of the Doc objects mailDoc method. The user may then use a standard approval stamp, use a custom stamp, or use a Hanko stamp to create a secure digital signature.
Managing comments
In this section, you will look in a more detailed way at the method of managing the comments in a document. Topics covered as listed below: Topics Selecting, moving, and deleting comments Using the comments list Exporting and importing comments Comparing comments in two PDF documents Aggregating comments for use in Excel Extracting comments in a batch process Page page 119 page 120 page 121 page 121 page 121 page 122
To move a comment, use the corresponding setProps method of the Annotation object to specify a new location or page. To delete the comment, invoke the corresponding destroy method of the Annotation object. In the code sample below, all the free text comments on page 2 of the document are deleted:
for (var i=0; i<myAnnotList.length; i++) if (myAnnotList[i].type == "FreeText") myAnnotList[i].destroy();
Sorting comments
To sort comments, use getAnnots method of the Doc object and specify a value for the nSortBy parameter. Permissible values of nSortBy are
ANSB_None Do not sort. ANSB_Page Sort by page number. ANSB_Author Sort by author. ANSB_ModDate Sort by modification date. ANSB_Type Sort by annotation type.
In addition, you can specify that the sorting be performed in reverse order by submitting the optional bReverse parameter to the method. The code sample given below shows how to obtain a list of comments from page 2 of the document, sorted in reverse order by author:
this.syncAnnotScan(); var myAnnotList = this.getAnnots({ nPage: 2, nSortBy: ANSB_Author, bReverse: true });
To import comments from an FDF or XFDF into a file, invoke the importAnFDF or importAnXFDF methods of the Doc object.
The above code will work if executed in the console. If executed from a non-privileged context, the secondDoc.pdf must be disclosed for app.openDoc to return its Doc object. Disclosed means that the code this.disclosed=true is executed when the document is opened, either as an open page action, or as part of a top level execution of document scripts. See the documentation of app.openDoc in the JavaScript for Acrobat API Reference for details.
Description Primary object for media control, settings, and renditions. Time or frame position within a media clip. A multimedia event fired by a Rendition object. A collection of multimedia event objects. An instance of a multimedia player. A location representing a frame or time value in a media clip. All the markers in the currently loaded media clip. Error information when a Rendition object is rejected. A media selection object used to create the MediaSettings object. An object containing settings used to create a MediaPlayer object. A display monitor used for playback.
124
Object
Monitors PlayerInfo PlayerInfoList Rendition ScreenAnnot
Description An array of display monitors connected to the users system. An available media player. An array of PlayerInfo objects. Information needed to play a media clip. A display area used for media playback.
The following code sample shows how to obtain a list of all available MP3 players and print them to the console:
var mp = app.media.getPlayers("audio/MP3"); for (var i = 0; i < mp.length; i++) { console.println("\nmp[" + i + "] Properties"); for (var p in mp[i]) console.println(p + ": " + mp[i][p]); }
To filter the list of players using the select method of the PlayerInfoList object, you can supply an optional object parameter which can contain any combination of id, name, and version properties, each of which may be either a string or a regular expression. For example, the following code obtains the QuickTime media player:
var mp = app.media.getPlayers().select({id: /quicktime/i});
In addition, the getOpenPlayers method of the doc.media object returns an array of all currently open MediaPlayer objects. With this array, you can stop or close all players, and manipulate any subset of the open players. The following example stops all running players in the document:
var players = doc.media.getOpenPlayers(oDoc); for (var i in players) players[i].stop();
In addition to the app.media properties and methods, a MediaSettings object, which is used to create a MediaPlayer object, contains many properties related to the functional capabilities of players. These are described in the following table.
Description Determines whether to play the media clip automatically when the player is opened. Resolves any relative URLs used in the media clip. Specifies the background color for the media player window. Specifies the background opacity for the media player window. Defines the ending time or frame for playback. The contents of the media clip (MediaData object). The number of seconds required for playback. An object containing the location and size properties of a floating window used for playback. A value indicating whether and how the content should be resized to fit the window. Defines the rectangle containing the display monitor used for playback. The category of display monitor used for playback (such as primary, secondary, best color depth, etc.) The document page number used in case a docked media player is used. Indicates that the media can play from beginning to end, and then in reverse from the end to the beginning. The list of available players for this rendition. The playback speed. The number of times the playback repeats. Indicates whether the media player controls will be visible. Defines the starting time or frame for playback. Indicates whether the media player will be visible. The playback volume. An enumeration obtained from App.media.WindowType indicating whether the media player window will be docked or floating.
layout
monitor monitorType
page palindrome
The example that follows illustrates the use of these properties to control how the media file is played. Other examples can be found in Integrating media into documents on page 128, as well as in the JavaScript for Acrobat API Reference.
Example 8.1
This minimal example is a custom script from the Actions tab in the Multimedia Properties panel of a screen annotation. To override the parameters specified by the UI of the screen annotation, the args parameter is passed.
// Obtain the MediaSettings object, and store its repeat value var nRepeat = event.action.rendition.getPlaySettings().repeat; nRepeat =(nRepeat == 1) ? 2 : 1; // Set the new repeat value when opening the media player var args = { settings: {repeat: nRepeat} }; app.media.openPlayer(args);
Monitors
The Monitors object is a read-only array of Monitor objects, each of which represents a display monitor connected to the users system. It is available as a property of the app object, and you can write customized JavaScript code to iterate through this array to obtain information about the available monitors and select one for a full-screen or popup media player. It is possible to apply filtering criteria to select a monitor. For example, you can select the monitor with the best color, or if there are multiple instances, additionally select the monitor with the greatest color depth. These criteria are methods of the Monitor object, and are listed in the following table.
Description Returns the monitors with the greatest color depth. Returns the smallest monitors with minimum specified dimensions. Creates a new monitor representing the entire virtual desktop. Returns the monitors containing the greatest amount of the document. Returns the monitors having the highest rank according to a ranking function supplied as a parameter. Returns the monitors with the greatest area in pixels. Returns the monitors overlapping the least with a given rectangle. Returns the monitors overlapping the most with a given rectangle. Returns the monitors displaying the least amount (or none) of the document. Returns the primary monitor. Returns all monitors except for the primary one.
Method
select tallest widest
Description Returns monitors filtered by monitor type. Returns the monitors with the greatest height in pixels. Returns the monitors with the greatest width in pixels.
In addition to the capabilities within the Monitors object, the Monitor object provides the properties shown in the following table.
Description The color depth of the monitor in bits per pixel. Returns true if the monitor is the primary one. The boundaries of the monitor in virtual desktop coordinates. The monitors workspace boundaries in virtual desktop coordinates.
The example below illustrates how to obtain the primary monitor and check its color depth:
var monitors = app.monitors.primary(); if (monitors.length > 0) console.println("Color depth: " + monitors[0].colorDepth);
The next example illustrates how to obtain the monitor with the greatest color depth, with a minimum specified depth of 24:
var monitors = app.monitors.bestColor(24); if (monitors.length > 0) console.println("Found the best color depth over 24!");
The next example illustrates how to obtain the monitor with the greatest width in pixels, and determines whether it is the primary monitor:
var monitors = app.monitors.widest(); var isIsNot = (monitors[0].isPrimary) ? " is " : " is not "; console.println("Widest monitor" + isIsNot + "the primary.");
1. Open a document and change to the page on which you wish to place a screen annotation. 2. Display the Editing toolbar by selecting View > Toolbars > Advanced Editing. 3. Select either the Movie tool or the Sound tool from the Advanced Editing toolbar, as appropriate. 4. Marquee-select the desired movie screen area for your sound. 5. In the Add Movie or Add Sound dialog box, click the Browse button and browse for your media file. 6. From the toolbar, select the Hand tool, and click the screen annotation. The media file will play. This is the default behavior of a new screen annotation. Select the Object tool on the Editing toolbar and double click on your screen annotation to bring up the Multimedia Properties dialog box. The dialog box has three tabs, Settings, Appearance and Actions. See Acrobat help for detailed descriptions of these tabs. The Actions tab of the Multimedia Properties dialog box is the same as that for any Acrobat form field. Of particular interest are the Play Media (Acrobat 6 or Later Compatible) and the Run a JavaScript actions. These are extensively discussed below. Select the Object tool from the Editing tool bar and double click on the screen annotation to bring up the Multimedia Properties dialog box again, and choose the Actions tab. Note that in the Actions window, a Mouse Up trigger is listed, and the action is Play Media (Acrobat 6 or Later Compatible). Highlight the Action, click the Edit button below. You now see the Play Media (Acrobat 6 or Later Compatible) dialog box. At the top of this dialog box there is a menu Operation to Perform. The operations are
The operation should be set to Play from Beginning, the default operation for a new screen annotation. The other operations of Play, Stop, Pause, and Resume can be used with buttons so that the user can pause and resume the media clip. In this chapter, however, we are most interested in the Custom JavaScript option, and you will learn how to play a media clip and to add event listeners. When using a button to play a media clip, there are two possible actions to be selected from the Button Properties dialog box.
In the first case, a media clip can be played by setting the UI to play the selected clip, or by executing a custom JavaScript the rendition to be used. In second case, that of Run a JavaScript, is used when setting the action of a form field, such as a button. Both these cases are discussed in the paragraphs that follow.
1. Create a screen annotation by embedding a movie into your document, as described on page 129. 2. In the Actions tab of the Multimedia Properties dialog box, click Play Media (Acrobat 6 or Later Compatible) for a mouse up trigger, and click the Edit button. 3. In the Play Media (Acrobat 6 or Later Compatible) dialog box, select Custom JavaScript from the Operations to Perform menu, and click the Specify JavaScript button. 4. In the Select Rendition dialog box, choose the rendition you want to control, and click Next. The JavaScript editor appears with the following text:
/* var player = */ app.media.openPlayer({ /* events, settings, etc. */ });
This is a rough template for starting your clip, the text suggests that you can define events and settings. Custom JavaScript like this is referred to as a rendition action. A minimal example for playing the clip is
app.media.openPlayer();
Close all dialog boxes and select the Hand tool. The movie plays when you click the screen annotation. Additional examples follow.
Example 8.2
For a rendition action, the event object carries certain multimedia specific information, for example, event.action.annot is the annotation object to be used to play the media, and event.action.rendition is the rendition to be played. In this example, we set the number of times this media is to play to three, and we install some event listeners.
// Get the rendition. var rendition = event.action.rendition; // Get the play settings for this rendition var settings = rendition.getPlaySettings(); // Change the repeat property to 3. settings.repeat = 3; // Create some event listeners for this action. var events = new app.media.Events( { onPlay: function() { console.println( "Playing..." ); }, onClose: function() { console.println( "Closing..." ); }, }); // Set these into an args object, with property names expected by // openPlayer. args = { events: events, settings: settings }; // Play the media with specified argument. app.media.openPlayer(args);
The app.media.openPlayer method calls app.media.createPlayer, then calls the method MediaPlayer.open, which, by default, begins playback of the media. In the next example, the createPlayer method is used, and playback is delayed to add in some listener events. Compare the techniques of the previous example with the next.
Example 8.3
The script below is for a rendition action. The movie clip is played in full screen with the UI controls visible. An event listener is added that causes an alert box to appear when the clip is closed.
// Get the rendition chosen in a Select Rendition dialog box. // We need the rendition to change its settings. var rendition = event.action.rendition; // Get the play settings for this rendition var settings = rendition.getPlaySettings(); // Make the window type to be full screen. settings.windowType=app.media.windowType.fullScreen; // Play the clip only once. settings.repeat = 1; // Show the UI of the player settings.showUI = true; // Form an args object to pass to createPlayer. var args = { settings: settings }; // Get the returned MediaPlayer object var player = app.media.createPlayer(args); // Use the MediaPlayer object to add an onClose event. player.events.add({ onClose: function() { app.alert("That's the end of the clip. Any questions?") } }); // Now, open the player, which begins playback, provided // player.settings.autoPlay is true (the default). If // player.settings.autoPlay is false, we would have to // use player.play(); player.open()
Example 8.4
This script is for a Run a JavaScript action of a form button. It gets a media clip and plays it in a screen annotation.
// Get the screen annotation with a title of myScreen var annot= this.media.getAnnot ({ nPage: 0,cAnnotTitle: "myScreen" }); // Get the rendition present in this document with a rendition name of // myClip var rendition = this.media.getRendition("myClip"); // Get the set of default settings for this rendition. var settings = rendition.getPlaySettings(); // Play the clip in a docked window. settings.windowType=app.media.windowType.docked; // Set the arguments to be passed to openPlayer, the rendition, the //annotation and the settings. var args = { rendition: rendition, annot: annot, settings: settings }; // Open the the media player and play. app.media.openPlayer( args );
The above example assumes that myClip is embedded in the document. In the next two examples, techniques for playing media from the local hard drive and from a URL are illustrated.
Example 8.5
This example references a media clip on the Internet and plays it in a floating window.
var myURLClip = "http://www.example.com/myClips/myClip.mpg"; var args = { URL: myURLClip, mimeType: "video/x-mpg", doc: this, settings: { players: app.media.getPlayers("video/x-mpg"), windowType: app.media.windowType.floating, data: app.media.getURLData( myURLClip,"video/x-mpg" ), floating: { height: 400, width: 600 } } } var settings = app.media.getURLSettings(args) args.settings = settings; app.media.openPlayer(args);
Here is the same example with the media on the local hard drive.
Example 8.6
The problem with playing a file from the local hard drive is locating it. This example assumes the media clip is in the same folder as the document.
// Get the path to the current folder. var folderPath = /.*\//i.exec(this.URL); // Form the path to the clip. var myURLClip = folderPath+"/myClip.mpg"; var args = { URL: myURLClip, mimeType: "video/x-mpg", doc: this, settings: { players: app.media.getPlayers("video/x-mpg"), windowType: app.media.windowType.floating, data: app.media.getURLData( myURLClip,"video/x-mpg" ), floating: { height: 400, width: 600 } } } var settings = app.media.getURLSettings(args) args.settings = settings; app.media.openPlayer(args);
Playing sound clips is handled in the same way, as the following example shows.
Example 8.7
var myURLClip = "http://www.example.com/myClips/dream.mp3"; var args = { URL: myURLClip, mimeType: "audio/mp3", doc: this, settings: { players: app.media.getPlayers("audio/mp3"), windowType: app.media.windowType.floating, floating: {height: 72, width: 128}, data: app.media.getURLData(myURLClip, "audio/mp3"), showUI: true }, }; var settings = app.media.getURLSettings(args); args.settings = settings; app.media.openPlayer(args);
If you add alternate versions of the media clip, these become new renditions that can serve as alternates in case the default choice cannot be played. It is then possible to invoke the rendition objects select method to obtain the available media players for each rendition. There are several types of settings that can be specified for a given rendition: media settings, playback settings, playback location, system requirements, and playback requirements. You can use JavaScript to customize some of these settings through the rendition object. There are several properties to which you have read-only access when editing a rendition. These are listed in the following table.
Description The alternate text string for the rendition. The document that contains the rendition. Returns the file name or URL of an external media clip. A MediaRendition object or a rendition list. The name of the rendition.
In addition to these properties, you can invoke the rendition objects getPlaySettings method, which returns a MediaSettings object. As you learned earlier in Specifying playback settings, you can adjust the settings through this object. You can also invoke its testCriteria method, with which you can test the rendition against any criteria specified in the PDF file, such as minimum bandwidth.
The fundamental methods of working with layers of content page 150 (Optional Content Groups).
Example 9.1
The intention of this menu is to add a button set to the toolbar; the button set will only appear on the toolbar if there is no document open in the window. Once the button set is installed on the toolbar, the menu item is only enabled if there is a document open in the window. This code is placed in the user JavaScript folder and uses a variable atbtoolbuttons to detect if this menu item should be marked. It is set to marked if atbtoolbuttons is defined and is false.
var atbtoolbuttons; app.addMenuItem({ cName: "atbToolButtonSet", cUser: "My Menu", cParent: "Tools", cMarked: "event.rc = ( (typeof atbtoolbuttons != 'undefined') && !atbtoolbuttons )", cEnable: "event.rc = (event.target == null);", cExec: "loadATBToolButton();", nPos: 0 });
There is brief example of app.addSubMenu and app.addMenuItem, see Executing privileged methods through the menu on page 47.
135
Example 9.1 installs a menu item under the main Tools menu. When executed, the menu calls the function loadATBToolButton(). This function loads the custom toolbar set, the definition of which follows.
Example 9.2
If this function is called with atbtoolbuttons set to false, it means the toolbar is already installed, and the function uninstalls the toolbar set; otherwise, the toolbar set is installed. The method app.addToolButton is used to add a toolbar button, and app.removeToolButton is used to remove a toolbar button. For Acrobat 8, this script assumes that the Enable Global Object Security Policy is enabled in the JavaScript section of the Preferences, see the discussion in Enable the global object security policy on page 96. The function loadATBToolButton is a trusted function because it executes privileged methods, such as app.getPath and app.openDoc. The icons for the toolbar buttons are contained in icon_toolbar.pdf, which resides in the same folder as this script. The document contains two named icons with the names of myIcon1 and myIcon2. Note that according to the JavaScript for Acrobat API Reference, the icon size is restricted to 20 by 20 pixels. If an icon of larger dimensions is used, an exception is thrown.
var loadATBToolButton = app.trustedFunction( function () { if ( typeof atbtoolbuttons == "undefined" ) atbtoolbuttons = true; else { if (!atbtoolbuttons) { app.removeToolButton("atbToolButton1"); app.removeToolButton("atbToolButton2"); atbtoolbuttons = true; return; } } if ( atbtoolbuttons ) { app.beginPriv(); // Get the path to the user JavaScript folder var atbPath=app.getPath({cCategory: "user", cFolder: "javascript"}); try { // Try opening the icon doc as in hidden mode, and retrieve its doc // object. var doc=app.openDoc({ cPath: atbPath+"/icon_toolbar.pdf", bHidden: true}); } catch (e) { console.println("Could not open icon file"); return;} // Get the icon stream for myIcon1 from the hidden doc var oIcon = util.iconStreamFromIcon(doc.getIcon("myIcon1")); // Add a tool button using this icon app.addToolButton({ cName: "atbToolButton1", oIcon: oIcon, cExec: "atbTask1();", cTooltext: "My toolbar button 1", nPos: 0 });
// Now get myIcon2 from the hidden document. oIcon = util.iconStreamFromIcon(doc.getIcon("myIcon2")); // and install this toolbar button as well app.addToolButton({ cName: "atbToolButton2", oIcon: oIcon, cExec: "atbTask2()", cTooltext: "My toolbar button 2", nPos: 0 }); // Close our hidden document containing the icons. doc.closeDoc(); app.endPriv(); // Set this variable to signal that the toolbars are installed. atbtoolbuttons = false; } })
Thumbnails
This section discusses how to embed thumbnail images in a PDF document and how to add page actions.
To add a thumbnail for just one page, just provide a value for nStart. The following example adds a thumbnail for page 7:
this.addThumbnails({nStart: 7});
To add thumbnails from page 0 to a specified page, just provide a value for nEnd. The following example adds thumbnails for pages 0-7:
this.addThumbnails({nEnd: 7});
To add thumbnails for all the pages in the document, omit both parameters:
this.addThumbnails();
To remove a set of thumbnails, invoke the Doc objects removeThumbnails method, which accepts the same parameters as the addThumbnails method. For example, to remove the thumbnails for pages 2 to 5, use the following code:
this.removeThumbnails({nStart: 2, nEnd: 5});
The advantage of this approach is that you can dynamically build JavaScript strings to be used in the method call.
Bookmarks
You can use JavaScript to customize the appearance and behavior of the bookmarks that appear in the Bookmarks navigation panel. Every PDF document has an object known as the bookmarkRoot, which is the root of the bookmark tree for the document. It is possible to recursively add and modify levels of bookmarks underneath the root. Each node is a bookmark object which can have any number of children. Acrobat makes the bookmarkRoot object available as a property of the Doc object. This root node contains a property called children, which is an array of bookmark objects. The bookmark object has the properties shown in the table Bookmark properties below, and the methods shown in the table Bookmark methods on page 139.
Bookmark properties
Property
children color doc name open parent style
Description Returns the array of child objects for the current node. Specifies the color for the bookmark. The Doc object for the bookmark. The text string appearing in the navigational panel. Determines if children are shown. The parent bookmark. Font style.
Bookmark methods
Method
createChild execute insertChild
Description Creates a new child bookmark. Executes the Mouse Up action for the bookmark. Inserts a bookmark as a new child for this bookmark (this may be used to move existing bookmarks). Removes the bookmark and all its children. Sets a Mouse Up action for the bookmark.
remove setAction
Creating bookmarks
To create a bookmark, it is necessary to navigate through the bookmark tree and identify the parent of the new node. Begin by accessing the bookmarkRoot, which is a property of the current document representing the top node in the bookmark tree:
var myRoot = this.bookmarkRoot;
Assume there are no bookmarks in the document. To create a new bookmark, invoke the Bookmark object createChild method to which you can submit the following parameters: cName (the name to appear in
the navigation panel), cExpr (an optional JavaScript to be executed when the bookmark is clicked), and nIndex (an optional zero-based index into the children array). The following code creates a bookmark that displays a greeting when clicked. Note that the omission of the nIndex value means that it is placed at position 0 in the children array:
myRoot.createChild("myBookmark", "app.alert('Hello!');");
To move grandChild so that it becomes a child of the root, invoke the Bookmark object insertChild method, and provide a reference to grandChild as a parameter:
var grandChild = myRoot.children[0].children[0]; myRoot.insertChild(grandChild, 1);
Managing bookmarks
You can use JavaScript to change the name, color, and style properties of a bookmark. Note that the style property is an integer: 0 means normal, 1 means italic, 2 means bold, and 3 means bold-italic. The code below changes the name to New Name, the color to red, and the font style to bold:
var myRoot = this.bookmarkRoot; var myChild = myRoot.children[0]; myChild.name = "New Name"; myChild.color = color.red; myChild.style = 2;
In addition to adding new or existing bookmarks as you learned in Creating bookmarks, you can also delete a bookmark and its children by invoking its remove method. The following line of code removes all bookmarks from the document:
this.bookmarkRoot.remove();
To print out the hierarchy to the console, you can keep track of levels as shown in the following code. Note its recursive nature:
function DumpBookmark(bm, nLevel){ // Build indents to illustrate the level var s = ""; for (var i = 0; i < nLevel; i++) s += " "; // Print out the bookmarks name: console.println(s + "+-" + bm.name); // Recursively print out the bookmarks children: if (bm.children != null) for (var i = 0; i < bm.children.length; i++) DumpBookmark(bm.children[i], nLevel+1); } // Open the console to begin: console.clear(); console.show(); // Recursively print out the bookmark tree DumpBookmark(this.bookmarkRoot, 0);
Links
JavaScript provides support for the addition, customization, or removal of links within PDF documents. These links may be used to access URLs, file attachments, or destinations within the document. The Doc object contains methods for adding, retrieving, and removing links. These include the methods listed in the table Doc object link methods. This is used in conjunction with the link object, which contains properties as well as a setAction method for customizing the appearance and behavior of a given link. Its properties are listed in the table Link properties. In addition, the app object contains a property called openInPlace, which can be used to specify whether cross-document links are opened in the same window or in a new one.
Description Adds a new link to a page. Converts text instances to web links with URL actions. Retrieves the links within a specified area on a page. Opens a web page. Goes to a named destination within the document. Removes the links within a specified area on a page. Removes web links created with the Acrobat user interface.
Link properties
Property
borderColor borderWidth highlightMode rect
Description The border color of the bounding rectangle. The border width of the surrounding rectangle. The visual effect when the user clicks the link. The rotated user space coordinates of the link.
To remove web links that were authored in Acrobat, invoke the Doc object removeWeblinks method. It accepts two optional parameters: nStart and nEnd represent the beginning and end of an inclusive range of page numbers. The following examples illustrate how to remove web links from different page ranges in the document:
// Remove the web links from pages 2 through 5: this.removeWeblinks({nStart: 2, nEnd: 5}); // Remove the web links from page 7 this.removeWeblinks({nStart: 7}); // Remove the web links from pages 0 through 7: this.removeWeblinks({nEnd: 7}); // Remove all the web links in the document: this.removeWeblinks();
Example 9.3
In this example, navigational links are added to the lower left and right corners of each page in the document. The left link opens the previous page, and the right link opens the next page:
var linkWidth = 36, linkHeight = 18; for (var i = 0; i < this.numPages; i++) { // Create the coordinates for the left link:
var lRect = [0, linkHeight, linkWidth, 0]; // Create the coordinates for the right link: var cropBox = this.getPageBox("Crop", i); var offset = cropBox[2] - cropBox[0] - linkWidth; var rRect = [offset, linkHeight, linkWidth + offset, 0]; // Create the Link objects: var leftLink = this.addLink(i, lRect); var rightLink = this.addLink(i, rRect); // Calculate var nextPage var prevPage if (prevPage the previous and next page numbers: = (i + 1) % this.numPages; = i - 1; < 0) prevPage = this.numPages - 1;
// Set the link actions to go to the pages: leftLink.setAction("this.pageNum = " + prevPage); rightLink.setAction("this.pageNum = " + nextPage); // Customize the link appearance: leftLink.borderColor = color.red; leftLink.borderWidth = 1; rightLink.borderColor = color.red; rightLink.borderWidth = 1; }
To remove a known link object from a given page, retrieve its bounding rectangle coordinates and invoke the Doc object removeLinks method. In the following example, myLink is removed from page 2 of the document. In the script below, it is assumed that myLink is a Link object:
var linkRect = myLink.rect; this.removeLinks(2, linkRect);
To remove all links from the document, simply use the crop box for each page, as shown in the code below:
for (var page = 0; page < this.numPages; page++) { var box = this.getPageBox("Crop", page); this.removeLinks(page, box); }
Opening links
To open a web page for a given link, invoke the Link object setAction method, and pass in a script containing a call to the Doc object getURL method. For example, suppose you have created a Link object named myLink. The following code opens http://www.example.com:
myLink.setAction("this.getURL('http://www.example.com')");
To open a file that resides in a known location on your local hard drive, use the app object openDoc method. The following example opens myDoc.pdf when myLink is clicked:
myLink.setAction("app.openDoc('/C/temp/myDoc.pdf');");
The file myDoc.pdf can be attached to a PDF document by executing the following script in the console:
var thisPath = "/c/temp/myDoc.pdf"; this.importDataObject({cName:"myDoc.pdf", cDIPath: thisPath })
Using destinations
To go to a named destination within a document, embed a script in the call to the Link object setAction method. The script contains a call to the Doc object gotoNamedDest method. The following example goes to the destination named as myDest in the current document when myLink is clicked:
myLink.setAction("this.gotoNamedDest('myDest');");
The following example opens a document, then goes to a named destination within that document. The example assumes the document being opened by openDoc is disclosed and can be used for a link action.
// Open a new document var myDoc = app.openDoc("/c/temp/myDoc.pdf"); // Go to a destination in this new doc myDoc.gotoNamedDest("myDest"); // Close the old document this.closeDoc();
Beginning with Acrobat 8, there is an additional parameter, cDest, for the app.openDoc method to set the destination. With this parameter, the target document need not be disclosed. For example,
app.openDoc({ cPath: "/c/temp/myDoc.pdf", cDest: "myDest" }); this.closeDoc();
Button appearance
Type
none invert push outline
Keyword
highlight.n highlight.i highlight.p highlight.o
For example, the following code makes the button appear pushed when clicked:
// Set the highlight mode to push var f = this.getField("myButton"); f.highlight = highlight.p;
As you learned earlier, the link object also has a highlight property. There are other ways in which you can creatively address the issue of highlighting. For example, you can change the background color of the button when clicked, by including a line of code in the script passed into its setAction method.
In the following example, the button displays a greeting and changes its background color to blue when the mouse enters its area:
var script = "app.alert('Hello!');"; script += "var myButton = this.getField('myButton');"; script += "myButton.fillColor = color.blue;"; f.setAction("MouseEnter", script);
The above script can also be entered through the UI as well. This idea can be applied to the bookMark objects color property, as well as the link objects borderColor property. In both cases, similar code to that shown in the example above can be used in the scripts passed into their setAction methods. For bookMark objects, you can change the text or font style through its name and style properties. For example, the following code adds the word VISITED to myBookmark and changes the font style to bold:
myBookmark.name += " - VISITED"); myBookmark.style = 2;
Setting up a presentation
There are two viewing modes for Acrobat and Adobe Reader: full screen mode and regular viewing mode. Full screen mode is often appropriate for presentations, since PDF pages can fill the entire screen with the menu bar, toolbar, and window controls hidden. You can use JavaScript to customize the viewing mode when setting up presentations. The app object fs property may be used to set the viewing mode. (Media clips can also be played in full screen, see Example 8.3 on page 131.)
Example 9.4
You want the document to be viewed in full screen, but as a courtesy, you want to restore the screen preferences of the user back to the original settings. Place the following script as document JavaScript, it will be executed once and only once upon loading the document.
// Save the settings we plan to change. var _clickAdvances = app.fs.clickAdvances; var _defaultTransition = app.fs.defaultTransition; var _escapeExits = app.fs.escapeExits; // Change these settings now. app.fs.clickAdvances=true; app.fs.defaultTransition = "UncoverLeft"; app.fs.escapeExits=true; // Now, go into full screen. app.fs.isFullScreen=true;
To restore the settings, place the following code in the Will Close section of the Document JavaScripts, located at Advanced > Document Processing > Set Document Actions.
// Restore the full screen preferences that we changed. app.fs.clickAdvances = _clickAdvances; app.fs.defaultTransition = _defaultTransition; app.fs.escapeExits = _escapeExits;
You can use JavaScript to customize how page transitions occur for any pages within a document. This is accomplished through the Doc objects setPageTransitions and getPageTransitions methods. The setPageTransitions method accepts three parameters:
nStart the zero-based index of the beginning page nEnd the zero-based index of the last page aTrans a page transition array containing three values: nDuration the time a page is displayed before automatically changing cTransition the name of the transition to be applied nTransDuration the duration in seconds of the transition effect
The name of the transition to be applied can be chosen from a comprehensive list made available through the FullScreen object transitions property. To obtain the list, type the following code into the console:
console.println("[" + app.fs.transitions + "]");
In addition, you can set up a default page transition through the FullScreen object defaultTransition property, as Example 9.4 on page 146 demonstrates.
Example 9.5
In the following example, page transitions are applied to pages 2 through 5. Each page displays for 10 seconds, and then an automatic transition occurs for one second:
this.setPageTransitions({ nStart: 2, nEnd: 5, aTrans: { nDuration: 10, cTransition: "WipeLeft", nTransDuration: 1 } }); // Set the viewing mode to full screen app.fs.isFullScreen = true;
The Doc object layout property allows you to specify page layout by assigning one of the following values:
For example, the script this.layout = "SinglePage" puts the document into single page viewing. To set up the magnification, assign a value to the Doc object zoom property. For example, the following code sets up a magnification of 125%:
this.zoom = 125;
You can also set the zoom type by assigning one of the settings, shown in the following table, to the Doc objects zoomtype property:
ZoomType settings
Zoom type
NoVary FitPage FitWidth FitHeight FitVisibleWidth Preferred ReflowWidth
Property value
zoomtype.none zoomtype.fitP zoomtype.fitW zoomtype.fitH zoomtype.fitV zoomtype.pref zoomtype.refW
The following example sets the zoom type of the document to fit the width:
this.zoomType = zoomtype.fitW;
To specify the page to which the document initially opens (or to simply change the page), set the Doc object pageNum property. If the following code is included in the script used in the document Open event, the document automatically opens to page 30:
this.pageNum = 30;
Finally, you can choose whether menu items and toolbar buttons will be visible by invoking the following methods of the app object:
hideMenuItem Removes a specific menu item hideToolbarButton Removes a specific toolbar button
For example, if the following code is placed in a folder-level script, the Hand toolbar button is removed when Acrobat or Adobe Reader is started:
app.hideToolbarButton("Hand");
Numbering pages
You can customize the page numbering schemes used throughout a document. There are three numbering formats:
decimal (often used for normal page ranges) roman (often used for front matter such as a preface) alphabetic (often used for back matter such as appendices)
The Doc object getPageLabel and setPageLabels methods can be used to control and customize the appearance of numbering schemes within a PDF document. The getPageLabel method accepts the zero-based page index and returns a string containing the label for a given page. The setPageLabels method accepts two parameters: nPage is the zero-based index for the page to be labeled, and aLabel is an array of three values representing the numbering scheme. If aLabel is not supplied, the method removes page numbering for the specified page and any others up to the next specified label. The aLabel array contains three required values:
cStyle the style of page numbering as shown in the following table cPrefix the string used to prefix the numeric portion of the page label nStart the ordinal with which to start numbering the pages
Description Decimal numbering Upper case Roman numbering Lower case Roman numbering Upper case alphabetic numbering Lower case alphabetic numbering
For example, the code shown below labels 10 pages within a document using the following scheme: i, ii, iii, 1, 2, 3, 4, 5, Appendix-A, Appendix-B:
// Pages 0-2 will have lower case roman numerals i, ii, iii: this.setPageLabels(0, ["r", "", 1]); // Pages 3-7 will have decimal numbering 1-5: this.setPageLabels(3, ["D", "", 1]); // Pages 8-9 will have alphabetic numbering: this.setPageLabels(8, ["A", "Appendix-", 1]); // The page labels will be printed to the console: var labels = this.getPageLabel(0); for (var i=1; i<this.numPages; i++) labels += ", " + this.getPageLabel(i); console.println(labels);
It is also possible to remove a page label by omitting the aLabel parameter, as shown in the code below (which assumes the existence of the labels in the previous example:
// The labels for pages 3-7 will be removed: this.setPageLabels(3);
Creating buttons
Though buttons are normally considered form fields, you can add them to any document. A button may be used for a variety of purposes, such as opening files, playing sound or movie clips, or submitting data to a web server. As you learned earlier, you can place text and images on a button, making it a user-friendly interactive portion of your document. To show or hide portions of graphic buttons, use the Mouse Enter and Mouse Exit events or other types of control mechanisms to manage the usage of the Field object buttonSetIcon method.
Example 9.6
The following code shows one icon when the mouse enters the button field, and a different icon when the mouse exits:
// Mouse enter script. var f = event.target; f.buttonSetIcon(this.getIcon('oneIcon')); // Mouse exit script. var f = event.target; f.buttonSetIcon(this.getIcon('otherIcon'));
The getOCGs method returns an array of OCG objects or null, if there are none; consequently, in situations in which it is uncertain if there are any OCGs on the page, you need to test the return value for null:
var ocgArray = this.getOCGs(3); if ( ocgArray != null ) { <some action script> }
Example 9.7
This example is a Mouse Up action for a button. The action is to toggle the visibility of a particular layer. The methodology is to get the array of OCGs on the page, search through them to find the particular layer of interest, and finally, to toggle its state property, which determines the visibility of the layer, see OCG properties on page 151.
var ocgLayerName = "myLayer"; var ocgArray = this.getOCGs(this.pageNum); for ( var i=0; i < ocgArray.length; i++) { if ( ocgArray[i].name == ocgLayerName ) { ocgArray[i].state = !ocgArray[i].state; break; } }
OCG properties
Property
initState intent locked name state
Description Determines whether the OCG object is on or off by default The intent of the OCG object (View or Design) Whether the on/off state can be toggled through the user interface The text string seen in the user interface for the OCG object The current on/off state of the OCG object
The initState property can be used to set the default state for an optional content group. In the following example, myLayer is set to on by default:
myLayer.initState = true;
The intent property, which is an array of values, can be used to define the intent of a particular optional content group. There are two possible values used in the array: View and Design. A Design layer is created for informational purposes only, and does not affect the visibility of content. Its purpose is to represent a document designers structural organization of artwork. The View layer is intended for interactive use by document consumers. If View is used, the visibility of the layer is affected.
In the following example, the intent of all the OCG objects in the document is set to both values:
var ocgs = this.getOCGs(); for (var i=0; i<ocgs.length; i++) ocgs[i].intent = ["View", "Design"];
The locked property is used to determine whether a given layer can be toggled through the user interface. In the following example, myLayer is locked, meaning that it cannot be toggled through the user interface:
myLayer.locked = true;
The state property represents the current on/off state for a given OCG. In the following example, all the OCGs are turned on:
var ocgs = this.getOCGs(); for (var i=0; i<ocgs.length; i++) ocgs[i].state = true;
The name property represents the text string seen in the user interface that is used to identify layers. In the following example, the Watermark OCG is toggled:
var ocgs = this.getOCGs(); for (var i=0; i<ocgs.length; i++) if (ocgs[i].name == "Watermark") ocgs[i].state = !ocgs[i].state;
Reordering layers
It is possible to determine the order in which layers are displayed in the user interface by invoking the Doc object getOCGOrder and setOCGOrder methods. In the following example, the display order of all the layers is reversed:
var ocgOrder = this.getOCGOrder(); var newOrder = new Array(); for (var i=0; i<ocgOrder.length; i++) newOrder[i] = ocgOrder[ocgOrder.length - i - 1]; this.setOCGOrder(newOrder);
10
Acrobat Templates
This chapter will help you understand the role of templates in PDF form structures, and the options and implications related to their use. You will also learn about the parameters for the template object methods. Topics The role of templates in PDF form architecture Spawning templates Description Discusses templates as a way of dynamically creating additional pages to hold form data. Methods and techniques of working with templates. Page page 153 page 153
There are two steps required to generate pages based on a template contained in the document: 1. Select a template from the Doc object templates property, which is an array of template objects. 2. Spawn a page invoking the template object spawn method. The following code adds a new page at the end of the current document that is based on the first template contained in the document:
var myTemplateArray = this.templates; var myTemplate = myTemplateArray[0]; myTemplate.spawn(this.numPages, false, false);
Spawning templates
In this section you will learn how to spawn a page and about the naming convention for any form fields residing on a template page. Finally, a detailed example is presented.
153
Acrobat Templates
Dynamic form field generation 154
In this next example, the same template will be spawned 10 times, will overlay on to pages 0 through 9 (bOverlay will be true), and the field names will be unique on each page (bRename will be true):
// Obtain the template: var t = this.templates; var T = t[0]; // Prevent file size inflation by using the XObject. Do this by // spawning once, saving the result (an XObject), and passing // the resultant XObject to the oXObject parameter in // the subsequent calls to the spawn method: var XO = T.spawn(0, true, true); for (var i = 1; i < 10; i++) T.spawn(i, true, true, XO);
Acrobat Templates
Template syntax and usage 155
In this next example, we will retrieve the template named myTemplate, overlay it onto pages 5 through 10 (bOverlay will be true), and use the same field names on each page (bRename will be false):
// Obtain the template name "myTemplate": var t = this.getTemplate("myTemplate"); // Prevent file size inflation: var XO = t.spawn(5, true, false); // Spawn the remaining pages: for (var i = 6; i <= 10; i++) t.spawn(i, true, false, XO);
Acrobat Templates
Template syntax and usage 156
Now for the last page. On this page we have a series of four fields that summarizes the information entered in the template pages. These fields give the total number of dependents; the spouses name, age, and gender; and each of the childrens names, genders and ages. The following script is placed as a Page Open event for the last page, the one that contains the summary information.
if ( this.pageNum != 1 ) { // Number of dependents = number of pages - 3 var numDependents = this.numPages - 3 this.getField("dependents").value = numDependents; var totalincome = 0; // Get the head of household's income var income = this.getField("P1.datapage.income").value; totalincome += income; // Spouse's name and gender is on P2 if ( numDependents > 0 ) { var gender = this.getField("P2.datapage.gender").value; var age = this.getField("P2.datapage.age").value; var spouseStr = this.getField("P2.datapage.name").value +" (" + gender +", " + age + ")"; this.getField("spouse").value = spouseStr income = this.getField("P2.datapage.income").value; totalincome += income; } if ( numDependents > 1 ) { var nChildren = numDependents - 1; var l = nChildren + 3; var childStr = ""; for ( var i=3; i < l; i++) { var childName = this.getField("P"+i+".datapage.name").value; var gender = this.getField("P"+i+".datapage.gender").value; var age = this.getField("P"+i+".datapage.age").value; childStr += (childName + " (" + gender +", "+ age +"); "); var income = this.getField("P"+i+".datapage.income").value; totalincome += income; } this.getField("children").value = childStr; } this.getField("totalincome").value = totalincome; }
In the script above, the field names of the spawned templates have been renamed. To extract the information contained in these template pages, the field names have to be built. Knowledge of the naming convention used by templates, as well as the structure of the document and the placement of the templates in the document is essential.
11
Search properties
Property
attachments available docInfo docText docXMP bookmarks ignoreAccents ignoreAsianCharacterWidth indexes jpegExif markup matchCase
Description Searches PDF attachments along with the base document. Determines if searching is possible. Searches document metadata information. Searches document text. Searches document XMP metadata. Searches document bookmarks. Ignores accents and diactrics in search. Matches Kana characters in query. Obtains all accessible index objects. Searches EXIF data in associated JPEG images. Searches annotations. Determines whether query is case-sensitive.
157
Property
matchWholeWord maxDocs proximity proximityRange refine stem wordMatching
Description Finds only occurrences of complete words. Specifies the maximum number of documents returned. Uses proximity in results ranking for AND clauses. Specifies the range of proximity search in number of words. Uses previous results in query. Uses word stemming in searches. Determines how words will be matched (phrase, all words, any words, Boolean query).
Search methods
Method
addIndex getIndexForPath query removeIndex
Description Adds an index to the list of searchable indexes. Searches the index list according to a specified path. Searches the document or index for specified text. Removes an index from the list of searchable indexes.
The simplest type of search is applied to the text within the PDF document. For example, the following code performs a case-insensitive search for the word Acrobat within the current document:
search.query("Acrobat", "ActiveDoc");
For example, the following code matches the phrases My Search or Search My:
search.wordMatching = "MatchAllWords"; search.query("My Search");
To determine whether proximity is used in searches involving multiple documents or index definition files, set the search object wordMatching property to MatchAllWords and set its proximity property to true. In the example below, all instances of the words My and Search that are not separated by more than 900 words will be listed in the search:
search.wordMatching = "MatchAllWords"; search.proximity = true; search.query("My Search");
To use stemming in the search, set the search object stem property to true. For example, the following search lists words that begin with run, such as running or runs:
search.stem = true; search.query("run");
To specify that the search should only identify occurrences of complete words, set the search object matchWholeWord property to true. For example, the following code matches nail, but not thumbnail or nails:
search.matchWholeWord = true; search.query("nail");
To set the maximum number of documents to be returned as part of a query, set the search object maxDocs property to the desired number (the default is 100). For example, the following code limits the number of documents to be searched to 5:
search.maxDocs = 5;
To refine the results of the previous query, set the search object refine property to true, as shown in the following code:
search.refine = true;
For example, the phrase "Paris AND France" used in a search would return all documents containing both the words Paris and France. The phrase "Paris OR France" used in a search would return all documents containing one or both of the words Paris and France. The phrase "Paris ^ France" used in a search would return all documents containing exactly one (not both) of the words Paris and France. The phrase "Paris NOT France" used in a search would return all documents containing Paris that do not contain the word France.
In addition, parentheses may be used. For example, the phrase "Acrobat AND (Standard OR Professional OR Pro)". The result of this query would return all documents that contain the word Acrobat and either Standard, Professional or Pro in it.
search.wordMatching="BooleanQuery"; search.query("Acrobat AND (Standard OR Professional OR Pro)", "Folder", "/C/MyFolder");
To specify that a Boolean query will be used, be sure that the search object wordMatching property is set to BooleanQuery (which is the default).
Index properties
Property
available name path selected
Description Indicates whether an index is available The name of the index The device-independent path of the index Indicates whether the index will participate in the search
The catalog object may be used to manage indexing jobs and retrieve indexes. It contains a getIndex method for retrieving an index, a remove method for removing a pending indexing job, and properties containing information about indexing jobs.
To build an index, first invoke the catalog object getIndex method to retrieve the index object. This method accepts a parameter containing the path of the index object. Then invoke the index object build method, which returns a catalogJob object. The method accepts two parameters:
cExpr a JavaScript expression executed once the build operation is complete bRebuildAll indicates whether to perform a clean build in which the existing index is first deleted and then completely built
Finally, the returned catalogJob object contains three properties providing useful information about the indexing job:
path the device-independent path of the index type the type of indexing operation (Build, Rebuild, or Delete) status the status of the indexing operation (Pending, Processing, Completed, or CompletedWithErrors)
In the code shown below, the index myIndex is completely rebuilt, after which its status is reported:
// Retrieve the Index object var idx = catalog.getIndex("/C/myIndex.pdx"); // Build the index var job = idx.build("app.alert('Index build');", true); // Confirm the path of the rebuilt index: console.println("Path of rebuilt index: " + job.path); // Confirm that the index was rebuilt: console.println("Type of operation: " + job.type); // Report the job status console.println("Status: " + job.status);
Searching metadata
PDF documents contain document metadata in XML format, which includes information such as the document title, subject, authors name, keywords, copyright information, date modified, file size, and file name and location path. To use JavaScript to search a documents XMP metadata, set the search objects docXMP property to true, as shown in the following code:
search.docXMP = true;
12
Security
This chapter will introduce you to the various security options available through JavaScript for Acrobat. You will understand how to customize security in PDF documents by applying passwords and digital signatures, certifying documents, encrypting files, adding security to attachments, managing digital IDs and certificates, and customizing security policies. Topics Security essentials Digitally signing PDF documents Adding security to PDF documents Digital IDs and certification methods Description Overview for securing a document: encryption and certification. Methods of signing a signature field using JavaScript. Page page 163 page 166
A more detailed look at encryption using certificates and security page 170 policies. Discussed are how to customize and extend the management and usage of digital IDs using JavaScript, to share digital ID certificates, to build a list of trusted identities, and to analyze the information contained within certificates. page 175
Security essentials
JavaScript for Acrobat provides a number of objects that support security. These are managed by the security, securityPolicy, and securityHandler objects for managing certificates, security policies, and signatures. The certificate, directory, signatureInfo, and dirConnection objects are used to manage digital signatures and access the user certificates.
Certifying documents
The certification signature for a document makes modification detection and prevention (mdp) possible. When this type of signature is applied, it is possible to certify the document, and thereby specify information about its contents and the types of changes that are allowed in order for the document to remain certified.
163
Security
Methods for adding security to PDF documents 164
To apply an author signature to a document, create an certification signature field using the Doc object addField method. Then sign the field using the Field object signatureSign method, in which you will provide parameters containing the security handler, a signatureInfo object containing an mdp property value other than allowAll, and a legal attestation explaining why certain legal warnings are embedded in the document. The SignatureInfo object has properties common to all security handlers. These properties are described below in the following table.
SignatureInfo properties
Property
buildInfo date dateTrusted handlerName
Description Software build and version for the signature. Date and time of the signature. A Boolean value, which if true, specifies that the date is to be trusted. Security handler name specified in the Filter attribute in the signature dictionary. Security handler name specified by handlerName. Security handler name specified by handlerName. Physical location or hostname. Modification detection and prevention setting (allowNone, allowAll, default, defaultAndComments). Name of the user. Number of fields altered since the previous signature. Number of fields filled in since the previous signature. Number of pages altered since the previous signature. The number of revisions in the document. Reason for signing. Signature revision. Raw bytes of the signature, as a hex-encoded string. Validity status (4 represents a completely valid signature). String representation of signature status. Formats used for public key signatures. The URL of the server for time-stamping the signature. The date and time that the signature was verified. Security handler used to validate signature. Handler specified by verifyHandlerName.
name numFieldsAltered numFieldsFilledIn numPagesAltered numRevisions reason revision sigValue status statusText subFilter timeStamp verifyDate verifyHandlerName verifyHandlerUIName
Security
Methods for adding security to PDF documents 165
Description The first name of the user. The last name of the user. The full name of the user. Array of certificate objects for the user. An array of preferred certificate objects.
Description The raw bytes of the certificate. The distinguished name of the user. The value of the certificate key usage extension. The MD5 digest of the certificate. The SHA1 digest of the certificate. A unique identifier for the certificate. The common name of the signer. The distinguished name of the signer. The purposes for which the certification may be used: end-user signing or encryption. An application Rights object.
ubrights
Security
Digitally signing PDF documents 166
Security policies
Security policies are groups of reusable security settings that may include the type of encryption, the permission settings, and the password or public key to be used. You can create folder-level scripts containing objects that reflect these policies. Security policies may be customized through the use of securityPolicy objects, which can be accessed and managed by the security object getSecurityPolicies and chooseSecurityPolicy methods as well as the Doc object encryptUsingPolicy method.
Secure forms
You can lock form fields by creating a script containing a call to the Field object setLock method, and passing that script as the second parameter to the signature field setAction method. In addition, you can sign an embedded FDF data object by invoking its signatureSign method, and subsequently validate the signature by invoking its signatureValidate method.
The creation and usage of these parameters are explained below in the following sections: The security handler object, The SignatureInfo object, and Applying the signature.
Security
The security handler object 167
The following code illustrates how to set up signature validation whenever the document is opened, lists all available security handlers, and selects the Adobe.PPKLite engine associated with the Acrobat user interface:
// Validate signatures when the document is opened: security.validateSignaturesOnOpen = true; // List all the available signature handlers for (var i=0; i<security.handlers.length; i++) console.println(security.handlers[i]); // Select the Adobe.PPKLite engine with the Acrobat user interface: var ppklite = security.getHandler(security.PPKLiteHandler, true);
After obtaining the security handler, invoke the securityHandler object login method, which makes it possible to access and select your digital ID as shown in the following code:
var oParams = { cPassword: "myPassword", cDIPath: "/C/signatures/myName.pfx" // Digital signature profile }; ppklite.login(oParams);
Security
Getting signature information from another user 168
Removing signatures
To remove a signature field, invoke the Doc object removeField method. In the example below, Signature1 is removed:
var sigFieldName = "Signature1" this.resetForm([sigFieldName]); // clear the signature this.removeField(sigFieldName); // remove the field
Certifying a document
When applying a signature to certify a document, check the trustFlags property of the signatureInfo object. If its value is 2, the signer is trusted for certifying documents.
Security
Validating signatures 169
Validating signatures
To validate a signature, invoke the signature fields signatureValidate method. It returns one of the following integer validity status values:
-1 not a signature field 0 signature is blank 1 unknown status 2 signature is invalid 3 signature is valid, identity of signer could not be verified 4 signature and identity of signer are both valid
Security
Adding security to PDF documents 170
The Field method signatureSetSeedValue sets the properties that are used when signing signature fields. The properties are stored in the signature field and are not altered when the field is signed, the signature is cleared, or when resetForm is called. Refer to the Acrobat 8.0 Security User Guide to obtain a deeper understanding of the use of signature seed values.
Security
Encrypting PDF files for a list of recipients 171
In order to obtain certificates from a directory, you must first connect to it using the Directory object connect method, and return a DirConnection object. An example is given below:
// Obtain the security handler: var sh = security.getHandler("Adobe.PPKMS"); var dc = sh.directories[0].connect();
It is then possible to use the DirConnection object to search for certificates. You can specify the list of attributes to be used for the search by invoking the DirConnection object setOutputFields method, that accepts two parameters:
oFields an array of attributes to be used in the search bCustom whether the attributes are standard output attribute names
For example, the following code specifies standard output attributes (certificates and email):
dc.setOutputFields({oFields: ["certificates", "email"]});
Security
Encrypting PDF files for a list of recipients 172
To perform the search, invoke the DirConnection object search method. It takes the following parameters:
oParams an array of key-value pairs consisting of search attribute names and their corresponding
strings
cGroupName the name of the group to which to restrict the search bCustom whether oParams contains standard attribute names bUI whether a user interface is used to collect the search parameters
In the following example, the directory is searched for certificates for the user whose last name is "Smith", and displays the users email address:
var retval = dc.search({oParams: {lastName: "Smith"}}); if (retval.length > 0) console.println(retval[0].email);
When you invoke the Doc object encryptForRecipients method, the oGroups parameter is an array of Group objects, each of which contains a permissions property. The permissions property is an object containing the properties described in the following table.
Permissions object
Property
allowAll allowAccessibility allowContentExtraction allowChanges
Description Full, unrestricted access. Content access for the visually impaired. Content copying and extraction. Allowed changes (none, documentAssembly, fillAndSign, editNotesFillAndSign, all). Printing security level (none, lowQuality, highQuality).
allowPrinting
The following code allows full and unrestricted access to the entire document for one set of users (importantUsers), and allows high quality printing for another set of users (otherUsers):
// Obtain the security handler: var sh = security.getHandler("Adobe.PPKMS"); // Connect to the directory containing the user certificates: var dir = sh.directories[0]; var dc = dir.connect(); // Search the directory for certificates: dc.setOutputFields({oFields:["certificates"]}); var importantUsers = dc.search({oParams:{lastName:"Smith"}}); var otherUsers = dc.search({oParams:{lastName:"Jones"}}); // Allow important users full, unrestricted access: var importantGroup = { userEntities: importantUsers, permissions: {allowAll: true} };
Security
Encrypting PDF files using security policies 173
// Allow other users high quality printing: var otherGroup = { userEntities: otherUsers, permissions: {allowPrinting: "highQuality"} }; // Encrypt the document for the intended recipients: this.encryptForRecipients({ oGroups:[importantGroup, otherGroup], bMetaData: true });
See a related example in the section See Reviewing documents with additional usage rights on page 115.
To obtain a list of the security policies currently available, invoke the security object getSecurityPolicies method. The method accepts two parameters:
oOptions a SecurityPolicyOptions object containing parameters used to filter the list bUI determines whether the user interface will be displayed (affects bCheckOnline in the oOptions parameter)
The SecurityPolicyOptions object is a generic object used to filter the list of security policies that will be returned by the method, and contains the following properties:
bFavorites determines whether to return policies are favorites or not cFilter returns policies using the specified security filter (Adobe.APS, Adobe.PubSec, and Adobe.Standard) cTarget returns policies using the specified target (document or attachments)
Security
Encrypting PDF files using security policies 174
The following example illustrates how to request and display a list of favorite security policies:
// Set up the filtering options (SecurityOptionsPolicy object): var options = { bFavorites: true, cFilter: "Adobe.PubSec" }; // Obtain the filtered list of security policies: var policyArray = security.getSecurityPolicies(options); // Display the list of security policies by name: for (var i=0; i<policyArray.length; i++) console.println(policyArray[i].name);
To encrypt a PDF file using a security policy, you must first choose a security policy by invoking the security object chooseSecurityPolicy method and then encrypt the file by invoking the Doc objects encryptUsingPolicy method. The security object chooseSecurityPolicy method opens a dialog box that permits the user to choose from a list of security policies filtered according to a SecurityPolicyOptions object. The Doc object encryptUsingPolicy method accepts three parameters:
oPolicy the policy object to use when encrypting the document oGroups an array of Group objects that the handler should use when applying the policy oHandler the SecurityHandler object to be used for encryption bUI whether the UI is displayed
In the following example, a newly created document is encrypted for a list of recipients, using the encryptUsingPolicy method, by choosing and applying a security policy. A Policy Server must be configured for publishing before running this example.
// Create the new document var myDoc = app.newDoc(); // Choose the list of recipients var recipients = [{ userEntities: [ {email: "user1@adobe.com"}, {email: "user2@adobe.com"}, {email: "user3@adobe.com"} ] }]; // Encrypt the document using the security policy: var results = myDoc.encryptUsingPolicy({ oPolicy: "adobe_secure_for_recipients", oGroups: recipients }); if ( results.errorCode == 0) console.println("The policy applied was: " + results.policyApplied.name);
Security
Adding security to document attachments 175
Note: For Acrobat 7.0, the value of cCryptFilter must be the string DefEmbeddedFile, beginning with Acrobat 8, the value of cCryptFilter can be any string. Thus, an eEnvelope is a PDF file that contains encrypted attachments. The name of the crypt filter, which represents the recipient list, is defined and used when importing the attachment. An example is given below:
// Create instructions to be used in the recipient dialog box: var note = "Select the recipients. Each must have "; note += "an email address and a certificate."; // Specify the remaining options used in the recipient dialog box: var options = { bAllowPermGroups: false, cNote: note, bRequireEmail: true }; // Obtain the intended recipient Group objects: var groupArray = security.chooseRecipientsDialog(options); // Open the eEnvelope document: var env = app.openDoc("/C/eEnvelopes/myeEnvelope.pdf"); // Set up the crypt filter: env.addRecipientListCryptFilter("myFilter", groupArray); // Attach the current document to the eEnvelope: env.importDataObject("secureMail0", this.path, "myFilter"); // Save the eEnvelope: env.saveAs("/C/output/outmail.pdf");
Security
Digital IDs 176
Digital IDs
A digital ID is represented with a SignatureInfo object, which contains properties of the digital signature common to all handlers, in addition to other properties defined by public key security handlers. These additional properties are described in the following table.
Description User-configured appearance name. Chain of certificates from signer to certificate authority. User-specified contact information for determining trust. Bytes covered by this signature. Validity status of the document byte range digest. Validity of the identity of the signer. Numerical validity of the identity of the signer. Validity status of the object digest. What the signer is trusted for. Password used to access the private key for signing.
Security
Digital IDs 177
// Populate the filtered recipient list: for (var i=0; i<rcp.length; i++) { if (rcp[i].defaultEncryptCert && rcp[i].defaultEncryptCert.usage.endUserEncryption) fRcp[fRcp.length] = rcp[i]; if (rcp[i].certificates) { for (var j=0; j<rcp[i].certificates.length; j++) if (rcp[i].certificates[j].usage.endUserEncryption) fRcp[fRcp.length] = rcp[i]; } } // Now encrypt for the filtered recipient list: this.encryptForRecipients({ oGroups:[{userEntities: fRcp}] });
The relative distinguished name is a generic object containing the properties shown in the following table.
RDN object
Property
c cn o ou e
Description Country or region Common name Organization name Organization unit Email address
Security
Digital IDs 178
The securityHandler object has a DigitalIDs property that contains the certificates associated with the currently selected digital IDs for the security handler. The DigitalIDs property is a generic object containing the following properties:
oEndUserSignCert the certificate used when signing oEndUserCryptCert the certificate used when encrypting certs an array of certificates corresponding to all the digital IDs stores an array of strings (one for every certificate object) indicating where the digital IDs are
stored You can use the security object exportToFile method to save a certificate file to disk. In the following example, the signing certificate is written to disk:
// Obtain the security handler: var sh = security.getHandler("Adobe.PPKMS"); // Obtain the certificates: var ids = sh.DigitalIDs; // Write the signing certificate to disk: security.exportToFile(ids.oEndUserSignCert, "/C/mySignCert.cer");
Security
Digital IDs 179
Description The server hosting the data The port number (standard LDAP port is 389) Used to narrow the search to a section of the directory Maximum number of entries retrieved from search Maximum time allowed for search
Security
Managing digital ID certificates 180
For example, the following code displays information for an existing directory:
// Obtain the security handler: var ppkms = security.getHandler("Adobe.PPKMS"); // Obtain the directory information object: var info = ppkms.directories[0].info; // Display some of the directory information: console.println("Directory: " + info.dirStdEntryName); console.println("Address: " + info.server + ":" + info.port);
Security
Managing digital ID certificates 181
Security
Task based topics 182
Hiding scripts
Go to File > Properties and select the Security tab. Set up either password or certificate security for the document by clicking Security Method and choosing either Password Security or Certificate Security. In the Permissions area of the dialog box that pops up, ensure that Enable Copying of Text, Images, and Other Content is unchecked. You can verify that changes to scripts have been disabled by returning to the Security tab. In the Document Restrictions Summary portion, Changing the Document should be set to Not Allowed.
13
183
Annotation: import and export Form: barcode plain text Annotation: online Form: online Note: JavaScript allows SOAP access in forms. For Adobe Reader 6.0, SOAP access is allowed in Acrobat forms. For Adobe Reader 6.02, OleDb database access is allowed in Windows for static XML forms. For Adobe Reader 7.0.5, SOAP access is allowed for static and dynamic XML forms. Embedded File: create, delete, modify, copy, and import. Note: The ability to manipulate embedded data objects is available in Adobe Reader 6.0 and later.
Features
Methods
In Acrobat Standard and Acrobat Professional, the following controls are disabled for rights-enabled documents:
Menu items that allow the addition or modification of scripts (except for the Debugger). Menu items that allow the creation, modification, or deletion of form fields (except the Import and Export menu items). Certain operations within the Security Panel marked as Not Allowed.
In addition, since the following menu operations will be affected in Acrobat Standard and Acrobat Professional, so will their corresponding JavaScript methods, indicated in the following table.
If a document is rights-enabled but commenting is not allowed, then the JavaScript methods shown in the following table will be disabled.
If a document is rights-enabled but file attachments are not allowed, then the following JavaScript methods will be disabled:
If a document is rights-enabled but digital signatures are not allowed, then the following JavaScript methods will be disabled:
Doc.getField (for signature fields) Doc.addField (when cFieldType = "signature") Field.removeField (when cFieldType = "signature") Field.signatureSign
For more information on developing JavaScript solutions for Adobe Reader see Developing for Adobe Reader.
Enabling collaboration
By using RSS, collaboration servers can provide customized XML-based user interfaces directly inside of Acrobat itself, thus providing a more dynamic and personalized tool, and providing JavaScript developers a means to extend collaboration, including full user interfaces. In addition, it is now straightforward to migrate comments from one document to another, carry comments across multiple versions of a document, and anchor comments to content so that the annotations remain in the right place even if the content changes. The advantages of this are that it is possible to automate discovery of collaboration servers, initiation workflows, and RSS feeds which may be used to populate content inside Adobe Reader. It is significant to note that users of Acrobat Professional can enable both file-based and online collaboration, thus enabling them to invite users of Adobe Reader to participate in the review process. The following JavaScript methods will be enabled in Adobe Reader when collaboration is enabled:
When collaboration is not enabled, it is still possible for annotations to appear in a browser by embedding the following statement in the FDF file:
Collab.showAnnotToolsWhenNoCollab = true;
A complete example of an FDF file that makes it possible for annotations to appear in a browser is shown below:
%FDF-1.2 % 1 0 obj << /FDF << /F (file:///C:/ReaderAnnots/seafood_wallet_re.pdf) /JavaScript << /AfterPermsReady 2 0 R >> >> >> endobj 2 0 obj << >> stream app.alert("DocumentOpen Script Start"); Collab.showAnnotToolsWhenNoCollab = true; endstream endobj trailer << /Root 1 0 R >>%%EOF
14
About ADBC
The Acrobat extensions to JavaScript provides an ODBC-compliant object model called Acrobat Database Connectivity (ADBC), which can be used in document-level scripts to connect to a database for the purposes of inserting new information, updating existing information, and deleting database entries. ADBC provides a simplified interface to ODBC, which it uses to establish a connection to a database and access its data, and supports the usage of SQL statements for data access, update, deletion, and retrieval. Thus, a necessary requirement to the usage of ADBC is that ODBC must be installed on a client machine running a Microsoft Windows operating system. In addition, ADBC does not provide security measures with respect to database access; it is assumed that the database administrator will establish and maintain the security of all data. The ADBC object provides methods through which you can obtain a list of accessible databases and form a connection with one of them. These methods are called getDataSourceList and newConnection. In addition, the ADBC object provides a number of properties corresponding to all supported SQL and JavaScript data types, which include representations of numeric, character, time, and date formats. Note: To activate ADBC, create a registry key of type DWORD with the name bJSEnable and a value of true (1) in the following location:
HKEY_CURRENT_USER\SOFTWARE\Adobe\Adobe Acrobat\8.0\ADBC
This activates ADBC in Acrobat 8.0. In previous releases of Acrobat, ADBC was active by default. In Acrobat 8.0, this setting has been changed to require user intervention to activate ADBC because most users do not want to have ADBC accessible from PDF.
188
In the following example, a list of all available databases is retrieved, and the DSN of the DataSourceInfo object representing Q32000Data is identified and stored in the variable DB:
// Obtain a list of accessible databases: var databaseList = ADBC.getDataSourceList(); // Search the DataSourceInfo objects for the Q32000Data database: if (databaseList != null) { var DB = ""; for (var i=0; i<databaseList.length; i++) if (databaseList[i].name == "Q32000Data") { DB = databaseList[i].name; break; } }
To establish the database connection, invoke the ADBC objects newConnection method, which accepts the following parameters:
cDSN the Data Source Name (DSN) of the database cUID the user ID cPWD the password
The newConnection method returns a connection object, which encapsulates the connection by providing methods which allow you to create a statement object, obtain information about the list of tables in the database or columns within a table, and close the connection. In the following example, a connection is established with the Q32000Data database:
if (DB != "") { // Connect to the database and obtain a Connection object: var myConnection = ADBC.newConnection(DB.name); }
Normally, the DSN is known on the system, so searching for it is not necessary. You can connect in a more direct way:
var myConnection = ADBC.newConnection("Q32000Data");
The connection object provides the methods shown in the following table.
Connection object
Method
close newStatement getTableList getColumnList
Description Closes the database connection. Creates a statement object used to execute SQL statements. Retrieves information about the tables within the database. Retrieves information about the various columns within a table.
The connection objects getTableList method returns an array of TableInfo generic objects, each of which corresponds to a table within the database and contains the following properties:
name the table name description a description of database-dependent information about the table
In the following example, the name and description of every table in the database is printed to the console:
// Obtain the array of TableInfo objects representing the database tables: var tableArray = myConnection.getTableList(); // Print the name and description of each table to the console: for (var i=0; i<tableArray.length; i++) { console.println("Table Name: " + tableArray[i].name); console.println("Table Description: " + tableArray[i].description); }
The connection objects getColumnList method accepts a parameter containing the name of one of the database tables, and returns an array of ColumnInfo generic objects, each of which corresponds to a column within the table and contains the following properties:
name the name of the column description a description of database-dependent information about the column type a numeric identifier representing an ADBC SQL type typeName a database-dependent string representing the data type
In the following example, a complete description of every column in the Q32000Data database table called Sales is printed to the console:
// Obtain the array of ColumnInfo objects representing the Sales table: var columnArray = myConnection.getColumnList("Sales"); // Print a complete description of each column to the console: for (var i=0; i<columnArray.length; i++) { console.println("Column Name: " + columnArray[i].name); console.println("Column Description: " + columnArray[i].description); console.println("Column SQL Type: " + columnArray[i].type); console.println("Column Type Name: " + columnArray[i].typeName); }
The statement object provides the methods shown the following table.
Statement object
Method
execute getColumn getColumnArray getRow nextRow
Description Executes an SQL statement. Obtains a column within the table. Obtains an array of columns within the table. Obtains the current row in the table. Iterates to the next row in the table.
In addition to the methods shown above, the statement object provides two useful properties:
columnCount the number of columns in each row of results returned by a query rowCount the number of rows affected by an update
To execute an SQL statement, invoke the statement object execute method, which accepts a string parameter containing the SQL statement. Note that any names containing spaces must be surrounded by escaped quotation marks, as shown in the following example:
// Create the SQL statement: var SQLStatement = 'Select * from \"Client Data\"'; // Execute the SQL statement: myStatement.execute(SQLStatement);
There are two steps required to obtain a row of data. First, invoke the statement object nextRow method; this makes it possible to retrieve the rows information. Then, invoke the statement object getRow method, which returns a Row generic object representing the current row. In the example shown below, the first row of information will be displayed in the console. Note that the syntax is simplified in this case because there are no spaces in the column names:
// Create the SQL statement: var st = 'Select firstName, lastName, ssn from \"Employee Info\"'; // Execute the SQL statement: myStatement.execute(st);
// Make the next row (the first row in this case) available: myStatement.nextRow(); // Obtain the information contained in the first row (a Row object): var firstRow = myStatement.getRow(); // Display the information retrieved: console.println("First name: " + firstRow.firstName.value); console.println("Last name: " + firstRow.lastName.value); console.println("Social Security Number: " + firstRow.ssn.value);
If the column names contain spaces, the syntax can be modified as shown below:
// Create the SQL statement: var st = 'Select \"First Name\", \"Last Name\" from \"Employee Info\"'; // Execute the SQL statement: myStatement.execute(st); // Make the next row (the first row in this case) available: myStatement.nextRow(); // Obtain the information contained in the first row (a Row object): var firstRow = myStatement.getRow(); // Display the information retrieved: console.println("First name: " + firstRow["First Name"].value); console.println("Last name: " + firstRow["Last Name"].value);
15
Describes the major methods and properties of the SOAP object; page 193 also discusses such topics as synchronous and asynchronous information exchange, exchanging file attachments and binary data, accessing SOAP header information and authentication. How to the queryServices and resolveService methods to locate the service on the network and bind to it for communications. How to use XPath to extract XML data. page 203
page 205
Discusses how a SOAP-based collaboration server can be used to page 206 share comments remotely via a web-based comment repository.
Note: Beginning with version 8, the SOAP object is deprecated, though support will continue. Use the Net.SOAP when developing any new web services. See the documentation of the Net object in the JavaScript for Acrobat API Reference for details.
SOAP object
Method
connect queryServices
Description Obtains a WSDL proxy object used to invoke a web service. Locates network services using DNS Service Discovery.
193
Method
resolveService request response streamDecode streamEncode streamFromString stringFromStream
Description Binds a service name to a network address and port. The principal method used to invoke a web service. A callback method used in asynchronous web method calls. Decodes a Base64 or Hex stream object. Applies Base64 or Hex encoding to a stream object. Converts a string to a stream object. Converts a stream object to a string.
SOAP and web services topics Using a WSDL proxy to invoke a web service Synchronous and asynchronous information exchange Using document/literal encoding Exchanging file attachments and binary data Converting between string and readstream information Accessing SOAP version information Accessing SOAP header information Authentication Error handling
Page page 194 page 195 page 199 page 200 page 201 page 201 page 201 page 202 page 202
In the example shown below, a connection to a web service will be established, and its RPC-encoded web methods will be invoked. Assume that myURL contains the address of the WSDL document:
// Obtain the WSDL proxy object: var myProxy = SOAP.connect(myURL); // Invoke the echoString web service, which requires a string parameter: var testString = "This is a test string."; var result = myProxy.echoString(testString); // Display the response in the console: console.println("Result is " + result); // Invoke the echoInteger web service, which requires an integer parameter: // Since JavaScript does not support XSD-compliant integer values, // we will create an integer object compliant with the XSD standard: var myIntegerObject = { soapType: "xsd:int", soapValue: "10" }; var result = myProxy.echoInteger(myIntegerObject); // Display the response in the console: console.println("Result is " + result);
Note that each call to a web method generates a SOAP envelope that is delivered to the web service, and that the return value is extracted from the corresponding envelope returned by the web service. Also, since XML relies on text, there is no problem sending a string to the web service. In the case of integers, however, it is necessary to create an XSD-compliant object to represent the integer value. JavaScript for Acrobat does support some of the standard data types specified in the XSD. These are shown in the following table.
The request method accepts the parameters shown in the following table.
Request method
Parameter
cURL oRequest oAsync cAction bEncoded cNamespace oReqHeader oRespHeader cVersion oAuthenticate cResponseStyle cRequestStyle cContentType
Description URL for SOAP HTTP endpoint. Object containing RPC information. Object used for asynchronous method invocation. SOAPAction header used by firewalls and servers to filter requests. Indicates whether SOAP encoding is used. Message schema namespace when SOAP encoding is not used. SOAP header to be included with request. SOAP header to be included with response. SOAP protocol version to be used (1.1 or 1.2). Authentication scheme. The type and structure of the response information (JS, XML, Message). Indicates how oRequest is interpreted. Specifies the HTTP content-type header.
Assume that the namespace is http://www.example.com/methods, the method name is echoString, and it accepts a string parameter called inputString. The following code represents the oRequest parameter:
var echoStringRequest = { "http://www.example.com/methods:echoString { inputString: "This is a test." } };
The cAction parameter contains header information described by the WSDL document that is used by firewalls to filter SOAP requests. In our example, we will supply the location of the WSDL document:
var mySOAPAction = "http://www.example.com/methods";
In the case of synchronous requests such as this one, the value returned by the request method (response in this example) is an object containing the result of the web method, which will be one of the JavaScript types corresponding to XSD types. The default format for the response value is an object describing the SOAP body (or header) of the returned message. Note: In the case of base64 or hex encoding of binary information, the type returned will be a readStream object. We may now obtain the returned value by using syntax that corresponds to the SOAP body sent back by the web method:
var responseString = "http://www.example.com/methods:echoStringResponse"; var result = response[responseString]["return"]; // Display the response in the console: console.println("Result is " + result);
Similarly, we can invoke the echoInteger method. To do this, we will use the same value for the cURL and cAction parameters, and develop an oRequest parameter like the one we used for the echoString method. In this case, however, we must supply an XSD-compliant object to represent the integer value:
var myIntegerObject = { soapType: "xsd:int", soapValue: "10" }; var echoIntegerRequest = { "http://www.example.com/methods:echoInteger { inputInteger: myIntegerObject } };
Now we may invoke the echoInteger web method and display its results:
var response = SOAP.request ({ cURL: myURL, oRequest: echoIntegerRequest, cAction: mySOAPAction }); var responseString = "http://www.example.com/methods:echoIntegerResponse"; var result = response[responseString]["return"]; // Display the response in the console: console.println("Result is " + result);
while (!this.isDone) doSomethingElse(); } }; // Invoke the web service: SOAP.request({ cURL: myURL, oRequest: echoIntegerRequest, oAsync: mySync, cAction: mySOAPAction });
// The response callback function could contain the following code: // Handle the asynchronous response: var result = mySync.result("echoInteger"); // Display the response in the console: console.println("Result is " + result);
Once this is done, fill the oRequest parameter with an object literal containing the data. An example is given below:
// Set up two integer values to be added in a web method call: var aInt = {soapType: "xsd:int", soapValue: "10"}; var bInt = {soapType: "xsd:int", soapValue: "4"}; // Set up the document literal: var req = {}; req["Add"] = {a: aInt, b: bInt}; // Invoke the web service: var response = SOAP.request({ cURL: myURL, oRequest: req, cAction: mySOAPAction, bEncoded: false, cNamespace: myNamespace, cResponseStyle: SOAPMessageStyle.Message }); // Display the response to the console: var value = response[0].soapValue[0].soapValue; console.println("ADD(10 + 4) = " + value);
MTOM is used by additionally setting the request methods bEncoded parameter to false and the cNamespace parameter to an appropriate value. This is illustrated in the following code, which creates an oRequest object:
// Use the MTOM standard: var MTOMRequest = { "echoAttachmentDL": { dh: { inclusion: { soapAttachment: true, soapValue: myStream } } } }; var response = SOAP.request({ cURL: myURL, oRequest: MTOMRequest, bEncoded: false, cNamespace: myNamespace });
// Exchange header information with the web service: var response = SOAP.request({ cURL: myURL, oRequest: {}, cAction: "http://www.example.com/methods", oReqHeader: sendHeader, oRespHeader: responseHeader });
Authentication
You can use the request methods oAuthenticate parameter to specify how to handle HTTP authentication or provide credentials used in Web Service Security (WS-Security). Normally, if authentication is required, an interface will handle HTTP authentication challenges for BASIC and DIGEST authentication using the SOAP header, thus making it possible to engage in encrypted or authenticated communication with the web service. This parameter helps to automate the authentication process. The oAuthenticate parameter contains two properties:
Username A string containing the username Password A string containing the authentication credential
Error handling
The SOAP object provides extensive error handling capabilities within its methods. In addition to the standard JavaScript for Acrobat exceptions, the SOAP object also provides SOAPError and NetworkError exceptions. A SOAPError exception is thrown when the SOAP endpoint returns a SOAPFault. The SOAPError exception object will include information about the SOAP Fault code, the SOAP Actor, and the details associated with the fault. The SOAP objects connect and request methods support this exception type. A NetworkError exception is thrown when there is a problem with the underlying HTTP transport layer or in obtaining a network connection. The NetworkError exception object will contain a status code indicating the nature of the problem. The SOAP objects connect, request, and response methods support this exception type.
// Perform the service discovery: SOAP.queryServices({ cType: "http", oAsync: myNotifications, aDomains: [ServiceDiscovery.local, ServiceDiscovery.DNS] });
Once a service has been discovered, it can be bound through the SOAP object resolveService method to a network address and port so that a connection can be established. The resolveService method accepts the following parameters:
cType the DNS SRV service name (such as http or ftp). cDomain the domain in which the service is located. cService the service name to be resolved. oResult a notification object used when the service is resolved. It implements a resolve method that accepts parameters nStatus (0 if successful) and oInfo (used if successful, contains a serviceInfo object). The serviceInfo object contains the following properties: target the IP address or DNS name of the machine providing the service. port the port on the machine. info an object with name/value pairs supplied by the service.
You can convert a string containing XML information into a document tree using the XMLData object parse method, and then manipulate and query the tree using its applyXPath method. The XMLData objects parse method accepts two parameters:
param1 A string containing the text in the XML document. param2 A Boolean value that determines whether the root node should be ignored.
In the following example, assume that myXML is the document tree obtained in the previous example:
// Obtain moms information: var momInfo = XMLData.applyXPath(myXML, "//family/mom"); // Save the information to a string: momInfo.saveXML('pretty'); // Give mom a raise: momInfo.personal.income.value = "80000";
Workflow applications
Support for SOAP in JavaScript for Acrobat has a major impact on collaboration workflows. A SOAP-based collaboration server can be used to share comments remotely via a web-based comment repository. Through the DNS Service Discovery support, it is possible to enable dynamic discovery of collaboration servers, initiation workflows, and RSS feeds that can provide customized user interfaces, via XML, directly inside of Acrobat 7.0 or later. In addition, it is possible to deploy web-based scripts that always maintain the most updated information and processes, and to connect to those scripts via form field actions that invoke web services. In the following example, a form is submitted to a server using a SOAP-based invocation:
// Populate the content object with form and SOAP information: var location = "http://adobe.com/Acrobat/Form/submit/" var formtype = location + "encodedTypes:FormData"; var content = new Array(); for(var i = 0; i < document.numFields; i++) { var name = document.getNthFieldName(i); var field = document.getField(name); content[i] = new Object(); content[i].soapType = formtype; content[i].name = field.name; content[i].val = field.value; } // Send the form to the server: SOAP.request({ cURL: cURL, oRequest: { location + ":submitForm": { content: content } }, cAction: location + "submitForm" }
16
Overview of the 3D JavaScript engine and how to access it using page 207 the JavaScript engine for Acrobat. page 208
Getting the Annot3D object Discusses how to get a Annot3D object and how it is used to access the JavaScript 3D engine. of the 3D annotation
Using the default script of a The default script of a 3D annotation is executed by the page 210 JavaScript 3D engine, here, techniques for calling functions 3D annotation defined as default script form the JavaScript engine for Acrobat. Initializing upon activation Techniques for initializing variables defined in the default script page 211 of a 3D annotation, when that annotation is activated.
Basic concepts
To create 3D annotations and attach scripts to them using the JavaScript for 3D API you need Acrobat Professional or Acrobat 3D. Those scripts can run on Acrobat 3D, Acrobat Professional, Acrobat Standard, and Adobe Reader for Windows and Mac OS platforms. Unless otherwise noted, all JavaScript objects, properties, and methods have support starting in version 7.0. When you create a 3D annotation, it has certain default behaviors that allow the user to interact with the 3D model. These behaviors, which are accessed through the 3D Annotations toolbar, are Rotate, Spin, Pan, Zoom, Measurement, Play/Pause Animation, Use Perspective/Orthographic Projection, Model Render Mode, Lighting Scheme, Background Color and Toggle Cross Section. If you wish to enhance the users 3D experience beyond the default behaviors, you must use the JavaScript API for 3D annotations. With the 3D JavaScript engine, you can specify the render modes and 3D matrix transformations of any of the individual meshes; set camera position, target, and field of view; detect mouse and keyboard events; control animations, and many more behaviors. The document JavaScript for Acrobat 3D Annotations API Reference is the complete reference for the JavaScript API for 3D annotations. The 3D JavaScript engine, which is distinct from the JavaScript engine for Acrobat, can be accessed in one of two ways:
The primary way is by attaching a default script to the 3D annotation. This can be accomplished while placing a 3D annotation using the 3D Tool or on an existing 3D annotation by accessing its properties dialog box using the Select Object tool. This script will be run directly by the 3D JavaScript engine. Acrobat provides a mechanism to directly access the entire 3D JavaScript engine API from within Acrobats own scripting engine by means of the JavaScript Annot3D.context3D property. This allows the author to wire up elements on the PDF page, such as buttons and links, to manipulate the 3D content.
The second method is the primary focus of this chapter, but we must necessarily address the default script of the 3D annotation.
207
A 3D annotation is not required to have a name, and there is no UI for entering the name of the annotation, so this method may not be useful unless youve already programmatically assigned a name to the 3D annotation, see Example 16.1. For a 3D annotation on page 1 of the document with a name of my3DAnnot, we can acquire the Annot3D object as follows:
var oMy3DAnnot = this.getAnnot3D(0, "my3DAnnot");
Note that the first argument has a value of 0 because the index of the page is one less than the page number. The Doc method getAnnots3D returns the array of all Annot3D objects on a specified page. This method takes only a parameter of nPage, the 0-based page number,
var aMy3DAnnots = this.getAnnots3D(0);
Annot3D properties
The Annot3D has a number of properties, as summarized in the table below. Property
activated context3D innerRect
Description A Boolean value, which if true, indicates that the 3D model is activated. If activated is true, this property returns the context of the 3D annotation, a global object containing the 3D scene. An array of four numbers specifying the lower-left x, lower-left y, upper-right x and upper-right y coordinates, in the coordinate system of the annotation (lower-left is [0, 0], top right is [width, height]), of the 3D annotations 3D bounding box, where the 3D artwork is rendered. The name of the annotation. The 0-based page number of the page containing the annotation. Returns an array of four numbers specifying the lower-left x, lower-left y, upper-right x and upper-right y coordinates, in default user space, of the rectangle defining the location of the annotation on the page.
Of particular importance is the context3D property. The object returned is, in fact, the handle to the JavaScript 3D engine.
The context3D will be undefined until the corresponding annotation is activated. You may need to check in your script for this condition before attempting to execute script commands on the 3D annotation.
var c3d = this.getAnnots3D(0)[0].context3D; if ( typeof c3d != "undefined" ) { // 3D annotation activated .... } else { // 3D annotation not activated ... }
The example below demonstrates how to acquire the JavaScript 3D engine, and to use it to rotate a component of the 3D content.
1. If not already showing, display the Advanced Editing toolbar, by selecting Tools > Advanced Editing > Show Advanced Editing Toolbar. 2. On the page containing your 3D annotation, select the Select Object tool from the Advanced Editing toolbar. 3. Double-click the 3D annotation to view the 3D Properties dialog box. 4. Click the Edit Content button. 5. In the Add 3D Content dialog box, click the Browse button corresponding to the Default Script, and browse for your .js file. 6. Once located, click Open to import the file as the default script of the 3D annotation. 7. Click OK to exit the Add 3D Content dialog box, then click OK to exit the 3D Properties dialog box. 8. Click the Hand tool to exit Select Object mode. Note: The default script for a 3D annotation is executed directly by the JavaScript 3D engine.
Now to call the function setRenderMode from a button or link using the JavaScript engine for Acrobat, you would have script as follows:
// Get the Annot3D script context of the targeted annot. var c3D = getAnnots3D(0)[0].context3D; // Call the JavaScript function setRenderMode() defined in the default // script of the referenced 3D annotation. c3D.setRenderMode("transparent");
if ( a3d.activated ) { waitingFor3DActivated = false; console.println( "...3D Annotation is activated." ); app.clearInterval( timeout ); c3D = a3d.context3D; // The function setBackgroundColor is defined as part of the // default script, so it must be executed using the 3D JS engine // Here, we set the background color of the canvas to dark green. c3D.setBackgroundColor( 0, 0.6, 0 ); } if ( timeout.count >= 10 ) // set to 10 seconds { console.println( "The 3D Annotation is still not activated" ); console.println( "Time limit exceeded, terminating initialization"); app.clearInterval( timeout ); } } timeout.count++; } // Check for activation every second timeout = app.setInterval( "initialize()", 1000 ); timeout.count = 0; var waitingFor3DActivated = true;
Index
A
accessibility document metadata 109 reading order 109 tab order 109 tagging annotations 108 text-to-speech 107 tooltip 109 accessing 3D annotations 208 form field 71 accessing data execute a SQL statement 191 get a row of data 191 getting the next row of data 191 statement object, see statement object methods Acrobat Address Book 181 Acrobat Database Connectivity about 19, 188 accessing data, see accessing data connection, see connection establishing connections 189 supports SQL statements 188 Acrobat Family Developer Center 44, 45, 59, 105, 122 Acrobat forms about 67 accessible 107 email 93 field types 69 guidelines for creating 68 importing and exporting data 92 properties 71 securing 166 web-ready 91 Acrobat Web Capture 99 Active Directory 179 ADBC, see Acrobat Database Connectivity addAnnotStore method 117 adding security to attachments 175 adding words to dictionary 119 additional usage rights 115, 184 addStateModel method 117 ADO support for Windows (XML forms) 105 Adobe LiveCycle Designer Reader Extensions 183, 184 Reader Extensions, features disabled 184 Adobe LiveCycle Policy Server 173 Adobe Reader additional usage rights 183 Adobe Reader Extension Root Certificate Authority 183 ADSI, see Active Directory Annot3D object context3D 207 properties 208 annotation object hidden 121 setProps 114, 119, 120 transitionToState 120 annotation, see comments app object about 16 addMenuItemu 135 addSubMenu 135 addToolButton 136 beginPriv 46 endPriv 46 execDialog 18 fs 146 fullscreen 146 getPath 136 hideMenuItem 148 hideToolbarButton 148 newDoc 47, 49, 56 openDoc 56, 121, 136, 144 openInPlace 141 printColorProfiles 62, 65 printerNames 62 removeToolButton 136 response 99 setInterval 39 setTimeOut 39 trustedFunction 45, 46 app.media createPlayer 131 getAnnot 131 getPlayers 125 getRendition 131 openPlayer 130 application initialization 42 application/pdf MIME type 92 application/vnd.adobe.xfdf MIME type 92 application/vnd.fdf MIME type 92 application/xml MIME type 92 application/x-www-form-urlencoded MIME type 92 array, sort and compare elements 76 asynchronous communication 198
B
batch sequences about 15 Batch Sequences documentation 44 batch-level script 44 collecting comments 122 binder 52
213
Index
214
C
calculation order array 91 call stack 35 catalog object getIndex 162 catalogJob object 161 certificates authority 176 certificates object properties 165 default security 177, 179 getting information 181 public key 179 certification signature 166 certifying a document 168 CGI application 91 check boxes 74 Collab 117 Collab object about 116 addAnnotStore 117 addStateModel 117 getStateInModel 116 removeStateModel 116 setStoreSettings 117 transitionToState 116 collaborative review 112 color spaces 99 colors, creating custom 99 combining PDF documents 51
D
Data Source Name (DSN) 189 date arithmetic 95 date conversion date to string 93 string to date 94 date horizon 95 Date object getFullYear 93 use 93
Index
215
Index
216
F
FDF Toolkit 92 FDF, see Forms Data Format fetching an URL from JavaScript 99 Field object addField 88 borderStyle 72 buttonPosition 73 buttonSetCaption 73 currentValueIndices 80 deleteItemAt 80 display 73 exportValues 70, 75 fillColor 72 getField 88 getItemAt 80 insertItemAt 80 lineWidth 72 name 71 numItems 80 radiosInUnison 81 readonly 87 rotation 74 setAction 74, 81, 84, 145 setItems 80 signatureInfo 179 signatureSetSeedValue 170 signatureSign 164, 166 signatureValidate 169 strokeColor 72, 81 userName 73, 109 value 81, 88 fields See also Acrobat forms accessing 71 border style 72 buttons 72 creating 69, 88 getting the number of 80 making read only 87 naming conventions 87 properties 71 setting calculation order 91 setting tab order 91 value 88 widgets 87 Fields navigation tab 88 file attachments accessing XML attachments 54 adding security 175 encrypting 165 methods 53 opening 144 files, creating 49 folder level scripts App and User 42 locating 42 provided files 42 font options 65 form, see Acrobat form
E
E4X 54, 103 ECMA-357 Standard, see E4X ECMAScript 14 eEnvelope 175 Enable Global Object Security Policy 96, 97, 136 enabling JavaScript 22 encrypting documents 165, 170 for a list of recipients 163, 171 event object about 19 change 77 changeEx 77 value 77 events 40, 41 exceptions 45 execute JavaScript after document is printed 43 when document is printed 43 executing JavaScript with printing and saving 43 executing privileged methods 46, 48 export value of a field 70 external editor 26
Index
217
G
getStateInModel method 116 getting the Field object 71 glob.js 42 global object security policy 96, 98 global variables 17, 96, 97 global.setPersistent 97 global.subscribe 97
M
mDNS, see Multicast DNS mdp 163, 170 media players controlling 124 listing of open players 125 opening and playing 130 specifying settings 125 media playing modes 128 menu items adding 47, 135 hiding 148 Message Transmission Optimization Mechanism 200 metadata EXIF 18 UI location 109 MIME types for data formats 92 modification detection and prevention, see mdp monitor 127, 128 MTOM, see Message Transmission Optimization Mechanism multimedia preferences 134 multimedia presentation floating window 128 full screen 128, 131 screen annotation 128, 132 multimedia screen annotation, see screen annotation multiple selection list box 80
H
Hanko stamps 122 highlighting required fields 86 HTML, JavaScript in 14 HTTP authentication 18, 202 HTTPS 194
I
importing icons 74 indexes catalog 157 file 160 search 157 Inkan stamp 122 Intercepting keystrokes in an Acrobat form 98
J
JavaScript core 14 debugger options 29 enabling 22 formatting 22 objects, summary 16 scope of actions 25 tools 21
N
named destination 144 navigation adding to PDF documents 137 with layers 151 non-privileged methods 45
L
language order 118 layers, see Optional Content Groups link object methods 141 properties 142 setAction 141 links adding and removing 142 appearance 143 jump to a named destination 144 opening a URL 144 properties 142 removing a web link 142
O
Object Identifier, see OID OCG, see Optional Content Groups ODBC 19, 188 OID 183 online collaborative review 112 team review 15 Optional Content Groups about 150 getting layers (OCG objects) 150 layer properties 151 locking layers 152 navigating 151
Index
218
P
pages action 138 add a field 71 cropping 55 deleting 56 execute JavaScript 43 extracting 52, 56 getting and setting page box 55 getting number of 148 inserting 56 inserting pages 51 labeling 149 layout 148 magnifying 148 numbering 149 replacing 56 rotating 55, 56 setting page action 145 transitions 147, 149 parsing XML data 205 passwords 170 PDF documents, See documents PDF forms, see Acrobat forms PDF layers, see Optional Content Groups permissions object 172 placement of scripts batch level 42 document level 41 field level 42 folder level 41, 42 page level 41 playback settings 125 playing media full screen 131 screen annotation 132 plug-ins 15 PostScript options 65 printing advanced output settings 65 booklet 64 documents 62 font options 65 forms only 64 getting list of printers 62 setting PostScript level 65 setting print parameters 60 tile marks 65 to PostScript file 63 using print method 62
Q
quick bar 15
R
radio buttons accessing individual widgets 81 behavior 81 creating 70 exporting values 81 setting an action 81 regular expressions 79 relative distinguished name 177 removeStateModel method 116 rendition about 133 getting player settings 134 selecting 134 rendition action 130 Report object 50 required form fields 86 review, markup, and approval 112 rollover effect 99 rotated user space 69, 88 rotating fields 74 pages 55 rotating pages 56 RSS 186
S
safe paths 15 screen annotation, getting 131 scripts batch-level 44 Document Did Print 43 Document Did Save 43 Document Will Close 43
Index
219
T
tab order 91 template object 153 templates 153 terminal field 87 text field calculating 85 processing keystrokes 83 properties 83 setting an action 84 text-to-speech 107 3D annotations default script 207, 210 render mode 210 accessing 208 activation 211 3D JavaScript engine about 207 accessing 207, 208 throwing an exception 45 thumbnails 138 thumbnails, adding and removing 138 tile marks 65 tool buttons adding 136 hiding 148 transitions 147 transitionToState method 116 triggering a form field action 41 trust level 181 trusted certificates 48 trusted function 45 trusted user identities 168
Index
220 workflows (Continued) managing usage rights 20 review, markup, and approval 19 WSDL document 18, 194, 196 proxy 194 WS-Security, see Web Service Security
U
usage rights 20, 170 user certificates 163 UserEntity properties 165 util object about 18 printd 94 scand 94
X V
validation script 84 View windows in the debugger 31 viewing modes 146 full screen 146 putting into full screen 146 regular 146 X.509 public key certificate 110 XFA, see XML forms XFDF, see XML-based FDF XML forms dynamic forms 68 global submit 106 save 106 static forms 68 XFA-specific JavaScript methods 101 XML streams 18 XML-based FDF 91, 92 XMLData object applyXPath 103, 205 parse 103, 205 XObject objects 154 XPath expressions 18 parsing XML data 103 XSL transformation (XSLT) 103, 205
W
watches list 36 watermarks 58 web links, adding and removing 142 Web Service Security 202 web services 59, 193 widgets 81, 87, 88 Windows certificate security 179 workflows approvals 119 creating Acrobat forms 19 creating PDF documents 19 interacting with databases 20 interacting with web services 20
Z
zoom type 148