AcroForm Objects

Today I thought I would tackle the subject of AcroForm Objects — objects available via scripting in the Acrobat Form Object Model — because they offer unique possibilities for your forms *when they’re running in Acrobat in the PDF format*.

Just to be clear, AcroForms are *specific to Acrobat* and therefore this functionality doesn’t apply when rendering your forms to a target other than PDF (e.g. when using “LiveCycle Forms”:http://www.adobe.com/products/server/formserver to render your XFA Forms as HTML).

First, let’s explain what XFA (XML Forms Architecture — a “W3C Submission”:http://www.w3.org/1999/05/XFA/xfa-template) does: It lets you describe a form, using a defined set of rules that govern an XML structure, which can target many different clients (e.g. PDF, HTML, etc.) — as long these clients support the XFA format. Today, the Adobe LiveCycle Designer targets PDF out-of-the-box and, along with “LiveCycle Forms”:http://www.adobe.com/products/server/formserver, targets HTML.

The fact that XFA is always translated into a format which can be understood by a client with which a user interacts in order to fill a form and possibly submit its data to a receiver means that the scripts you write in your XFA forms get executed in the target client application (such as Acrobat or a web browser). If the target client also contains a Scripting Object Model — like Acrobat does — there may be ways that you can take advantage of specific functionality exposed by the client which is hosting your XFA forms.

This brings us to the topic at hand: “Acrobat’s Form (AcroForm) Object Scripting Model”:http://partners.adobe.com/public/developer/acrobat/sdk/index_doc.html#js. If you’re designing your form only to target PDF (or you add code to your form to detect when your form is being hosted by Acrobat using xfa.host.name, for example), you can get access to the Acrobat _app_, _Document_ and _Field_ objects, amongst others, and do some really cool things like have a “field with invalid data start flashing red”:http://blogs.adobe.com/formbuilder/2006/06/invalid_flashing_fields.html when the user attempts to submit the form’s data.


h2. xfa.hostWhen writing scripts in an XFA form, you have access to the special _xfa.host_ object. This object gives you access to methods which are *specific to the application hosting your form* (such as Acrobat, a form server or a web browser). For example, thebc. xfa.host.nameproperty tells you the name of the application hosting your form at the time the script is interpreted. If your form is being viewed/hosted in Acrobat, this property will return “Acrobat” while it’ll return the name of the browser if it has been served to a web browser. Furthermore, it’ll return “Presentation Agent” if the script was flagged to run on the server and the server application serving the form to PDF or HTML is Adobe’s “LiveCycle Forms”:http://www.adobe.com/products/server/formserver product.xfa.host also gives you access to other properties and functions such asbc. xfa.host.messageBox // displays a dialog box on the screenxfa.host.validationsEnabled // turns the form’s validations on/off with a single callbut take note that not all functions and properties are available on all hosts (e.g. since a server host can’t display a dialog which requires user input, the xfa.host.messageBox function is only supported on _client_ hosts like Acrobat and web browsers).You can obtain more information on xfa.host on page 185 of the “Adobe XML Form Object Model Reference”:http://www.adobe.com/devnet/livecycle/designing_forms.html.h2. Acrobat app ObjectSince the scripts you write in functions and events within an XFA form are interpreted by and executed within the context of Acrobat’s Scripting Engine, you have access to a special object called _app_. This object gives you access to the collection of active documents and plugins, amongst other things, and lets you display alert messagesbc. app.alert(“Hello world!”);and even set Acrobat into full screen mode with a red background!bc. app.fs.backgroundColor = color.red;app.fs.isFullScreen = true;Note that while _color.red_ isn’t an object provided by the XFA Scripting Object Model, it still exists within the context of your scripts because the scripts are ultimately interpreted and executed within Acrobat. You can get more information on the _app_ object in the “Acrobat JavaScript Scripting Reference”:http://partners.adobe.com/public/developer/acrobat/sdk/index_doc.html#js.h2. xfa.eventThis is a special object which exists only via the XFA Plugin which executes XFA scripts on XFA object events inside Acrobat. Whenever an event occurs (such as the click of a button or a field gaining input focus), your script has access to the _xfa.event_ object which gives lots of important information about the event.For example, if you want to know the value that was selected in a list box or a drop down list in order to change the state of another object on your form, you would script against the list box’s or drop down list’s Change event. If you used the following code to get the value of the item that the user selected:bc. this.rawValueyou would get the previously-selected value because the object’s rawValue property isn’t updated until after the Change event has occurred. In order to get the information you need, you must use the following code:bc. xfa.event.newTextwhich will give you the value of the item the user just selected._xfa.event_ also gives you access to a very useful property called _target_: In Acrobat, this property specifies the Acrobat _Document_ object (which contains the Acrobat _Field_ object which wraps the XFA object whose event is being scripted). This means that you can get at the Acrobat _Document_ object for the “active document” just by using:bc. event.target(Note that you don’t need — and shouldn’t use — the “xfa” prefix when accessing the “event.target” property — I don’t know why yet but you’ll have trouble using it if you use the “xfa.event.target” syntax.)Using this information, you can:bc. event.target.zoom *= 2; // increase the zoom level two-foldevent.target.zoomType = zoomtype.fitW; // zoom to page-width levelevent.target.zoomType = zoomtype.fitH; // zoom to page-height levelor you can use the _getField_ method to get an Acrobat _Field_ object and do some more interesting things.You can get more information on the _Document_ and _Field_ objects in the “Acrobat JavaScript Scripting Reference”:http://partners.adobe.com/public/developer/acrobat/sdk/index_doc.html#js.h2. Putting it all Into PerspectiveTo tie this all together, I’ve drawn-up a *simplified* version of the Scripting Object Model the way I picture it in my head:==Scripting Object Model (simplified)==This image illustrates how things work from the perspective of a script running within an XFA Event or an XFA Script Object Function (note that you don’t have access to the xfa.event object there unless you pass it into the function by calling it from an XFA Event). You can see how, from the XFA object, you can get to the:* Acrobat app object (directly);* Acrobat Document object (via event.target or the app object);* Acrobat Field object (via the Document object);* xfa.host object (directly).Hopefully this post will have given you a general idea of the *Acrobat-specific* tools at your disposal when you’re writing XFA scripts using the JavaScript language. Please note, however, that changes may occur to the way XFA Form Objects are hosted within Acrobat in future releases and therefore using the AcroForm Object Model should be a *last resort* if an XFA equivalent simply isn’t available.====~*Updated:* August 30, 2006~

20 Responses to AcroForm Objects

  1. Hi Stefan,Another great article! Just one quick correction. XFA was a W3C submission but is *not* a W3C standard. A standard is a document that has gone through a rigorous review process by multiple independent parties. A W3C submission is done unilaterally by a party or parties interested in having the W3C take the submission into consideration during the standards process.Just because something appears on the W3C site, doesn’t make it a W3C standard, but it does mean that the parties involved are participating in the W3C process.I should know because my name is on the submission. :)Regards,Rob

  2. Rob,Thanks for correcting me on that one! I see now that the W3C document states that it’s a submission and not a standard. I’ve made the correction in my post.

  3. smvo says:

    Hi,Thank you for your article.I would like to make one question that I think is related to this article:When opening a pdf file using a xdp file, I realize that at least some events get fired twice. Can you explian that?Thank you

  4. smvo,Based on the Adobe ML Form Object Model Reference, opening a dynamic PDF form will result in the pre-render sequence of events to fire twice completely simply because of the way the form is loaded into Acrobat.Also, you’ll get multiple Initialize event triggers depending on whether you’re merging data into your form: If you don’t merge data, you should only get it once for every object; otherwise, you’ll get it once prior to data merge and another time after the data merge has completed.Does that clarify things for you?

  5. smvo says:

    Stefan,I would like to make another question about a subject in your tutorial.You said this: “…your XFA forms get executed in the target client application (such as Acrobat or a web browser)”.My question is, how can I have a brwoser as a host/target application? I ask this, because, even when acrobat open inside a web browser, the host is still Acrobat, right?So How can I open a XFA form in a browser?Thank you again.

  6. smvo,You can have your forms hosted by (executed within a) browser by deploying them to HTML via LiveCycle Forms — an Adobe LiveCycle solution which lets you securely capture data from and deploy your forms to a number of different devices from desktops to Pocket PCs without users having to install any extra software.

  7. smvo says:

    Hello again Stefan,I have two more questions that I hope to be related with your topic. Any help is appreciated.1) When opening a xdp file referencing a PDF file, for instance in a browser IFrame, I realize the xdp file by itself opens inside the IFrame, and then it browses to the PDF and this way the PDF will no longer be opened inside the IFrame (so Im´not able to hide it from the user).Is there any way to control this beahaviour/event? For instance, is there any way to instruct acrobat to open the referencing xdp file in a predefined window´s frame? (self, top, etc)2) Because I couldn´t figured out a way to accomplish the previous goal, I tried to open a new hidden browser window where the pdf would be rendered, and automate the initialize event of the XFA PDF calling a button click event to print the document:xfa.host.print(0, “0”, (xfa.host.numPages -1).toString(), 0, 0, 0, 0, 0);The goal was to create a new hidden window, where the pdf would be rendered.This way the initialize event would be automatically call, and also the click event of a print button inside de pdf. The PDf would print and the browser window close.However there is one problem in this scenario: the print method of the xfa.host will be called, but it will soon stop sending to the printer. I can see the pdf being send to the printer spool at start but if the pdf is a bit longer the send to the spool will stop and the spool became clean without printing. It seems the print method is asynconous or something like this.Thank you

  8. smvo,I’m afraid it’s “0 for 2” in this case:1. The only thing I know of that you can do when opening a PDF is to tell it either to open in the current window or a new one — you can’t specify which frame it should open in.2. For security reasons, you can’t (or at least you shouldn’t be able to) silently (without user interaction) execute a print command neither by using xfa.host.print nor by using event.target.print. Therefore, attempting to execute a print command in an Initialize event shouldn’t result in anything.

  9. Sérgio says:

    Hi Stefan,Here it goes 2 more questions about your article. Any help is really appreciate.I´m writing code in an application/folder level javascript file. From there, I would like to get the value of some fields palced in my XFA forms… Is this possible? At what level can we interact with xfa forms using application level javascript? For instace, can I pass an object as a function parameter to the application level javascript and then change some properties?Thank you!

  10. Sergio,I don’t see why you couldn’t pass an XFA Object reference to an Acrobat application-level script. Also, from your script, if you get an Acrobat Document object, you can get the XFA Form Object Model from there by using the “xfa.form” object within the current context (the specific Acrobat Document object). That should let you do things likexfa.form.form1.resolveNodes(“#subform[*]”); in order to get a list of page-level subforms (assuming the current form’s root subform is named form1).I’m not promising that this works but I would hope that it does. In the end, however, it’s best to use application-level scripts only if absolutely necessary. Access to certain Acrobat Object Model objects in an XFA-PDF form may change in future releases and this could cause your scripts to break.

  11. Sérgio says:

    Stefan,At first I tried to get the XFA object from an application/folder lever javascript function using “this.xfa”. The result was always “undefined”. Using a direct call to “xfa” was undefined too. However, using “event.target.xfa” works very well. All the properties/methods of the xfa object could be used this way.I think this is an important point to your great figure in this article: If I´m not wrong, using “this” in a folder level script return an Acrobat Document object, while event.target will return an xfa form object.So, maybe you could show that in your figure as it mainly shows the direction form xfa to acrobat and not the opposite with the exception of the get field function. I don´t know if I make my self clear about this… I´m only trying to figured out all these ways in my mind using your figure.In what relates to code breacking, I understand your point, however, I rather change the code in a javascript file than change it in about 400 documents… That is why I´m trying to put my code inside an external javascript file.Stefan, thank you for your help.Regards,Sérgio

  12. Sergio,Thanks for your input.I see your point about code breakage and not wanting to update 400 forms to fix one little typo in a script. Hopefully you’ll like what a future version of Designer has to offer in order to address this sort of problem.With respect to the xfa object, I’d like to clarify that the reason why “event.target.xfa…” works is because “event.target” represents the active Acrobat Document Object and within that object lives an xfa object (as long as you’re dealing with an XFA-PDF form). From there, you can access the XFA Form Object Model by doing things likeevent.target.xfa.form.form1.resolveNode(“#subform[0]”).myField.rawValue = ‘test’;in order to assign the value “test” to a field named “myField” on the first page of a form named “form1”.As far as the “this” keyword in Acrobat application level scripts goes, while I’m no Acrobat scripting expert, I’m quite certain that “this” usually refers to the app object (Acrobat Application) instead of an Acrobat Document Object. You would have to get the list of opened documents and then test each one for the existence of the xfa object. For example, you could do something like this (please note that I haven’t tested this Acrobat script):var aOpenDocs = app.activeDocs;if (aOpenDocs.length > 0){var oDoc = aOpenDocs[0];if (oDoc.xfa != null){// access the xfa object…}}

  13. Sérgio says:

    Stefan,What do you mean about this:”Hopefully you’ll like what the next version of Designer has to offer in order to address this sort of problem.”What version of Designer are we talking about? I believe it will be a new release right?Thank you!

  14. Sergio,Curious, are we? ;)I’m talking about a new release of Designer. Unfortunately, that’s about all I can say at this point.

  15. Sérgio says:

    Ok,Another question less curious, about the new table object of Designer 7.1.Is it possible to add new columns programmatically or at least, hide columns already in the table?Thank you!

  16. Sergio,In response to your question on table columns, check-out my post on Scripting Table Columns.I hope it answers your questions.

  17. smvo says:

    Hello Stefan,Here I am again, now that I´m trying to use LiveCycle Forms.Well, after all the code created in LiveCycle Designer, and because I used some acrobat objects and application level code, I am now stuck in some issues:1 – I need to use something like a xml string reader. So I used XMLData object in Livecycle Designer. In LC Forms I only get this: Object302394736Does this menas that there is not a way to work with xml strings using xfa (to be compatible with Livecycle Forms)? This is really bad, because I will need many hidden fields to accomplish the sabe functionality…2 – I use a lot of application script because I don´t want to get big PDF files. However, I guess this will not work in LC Forms, right? Is there any sort of code container to LC Forms similar to the acrobat install script Directory where we put javascript files? So that when the script is not on the form, LC Forms will search somewhere else?Thank you.

  18. smvo,I’m afraid it’s 0 for 2 on this one.Since the XMLData object is an AcroForm object, it isn’t available to the scripting model when the form is running on Form Server.As for your question about a central place to put global JavaScript scripts on the server, this isn’t possible either.I’m afraid you’re best bet here is to write a little XML parser in JavaScript (I know, that’s really not what you wanted to hear and it’s not what I wanted to be able to tell you either) and to place all scripts in the form itself.

  19. smvo says:

    Stefan,I decided to use arrays.Tell me, is there a way to get the full path to an object? For instance, in an object event: this.some_propertie_to_get_the_full_path_of_it?Thank you

  20. smvo says:

    ok, I had figured out: this.somExpressionThank you