This is a guest post from my colleague Anatole Matveief who works on XFA-related features in Acrobat. In this post, Anatole introduces a really cool feature available since Acrobat 8.0 and Designer 8.0 called “formstate” which allows you to persist non-data related changes to your forms and restore them when the form is subsequently re-opened.
Minimum requirements (to use the forms in this tutorial): Acrobat Standard 8.0, Designer 8.0
FormState
In Acrobat and Designer 8, Adobe introduced the concept of saving a form’s state in XFA Forms. First a quick review: An XFA Form file usually contains a template and data. When the form is opened, the template instructs the runtime engine (like Acrobat, Reader or the server) how to create the Form DOM given a set of data. The user can then interact with the form. After the user fills the form, Reader or Acrobat will save the data. When the form is then reopened, Acrobat or Reader will take the saved data and once again do the merge to create the form.
However, many customers encountered a problem: They wanted to save or persist an element of the form that was not bound to the data. For example maybe in the process of filling the form, some captions changed, or the color of fields changed. Or maybe the number of instances in an unbound subform changed. Since these changes were not bound to data they would not be restored the next time the form was opened, since only the data was saved.
In Acrobat 8 this changed. Now by default, the state of the form, or its formstate is saved. This means that all those changes in the form that happened at runtime that weren’t bound to data will be restored next time the form is opened.
Automatic State Restoration
As an example, open formstate-auto.pdf in Acrobat. Click on the “Change Country” button once or twice, which runs a script to change numerous properties on the form to make it into a US form or Canadian form. These include colors, captions, and the number of instances in a subform, values, and the items in a list. Now save the file. When you open the form again, the captions, colors number of instances, unbound field values, and list items will be as they were when you saved. This would not be the case prior to Acrobat 8.
Here is the setting in Designer 8.0 that controls this automatic form state saving:
In the XFA Language it’s the property in the root subform called “restoreState”. The default value is:
restoreState="auto"
Now, as with most good things in life, it’s not quite so simple. Now that form state is restored, we open up a potential security issue. What if someone gets your form, changes a caption from “Address” to “Password”, then changes another caption to read “SSN”? When they save the file, the next time your intended customer opens the file they’ll see the spoofed captions, not the captions the original author intended! That is, the author’s intent has been compromised. So how do we get around this issue?
Manual State Restoration
There is now also the option to restore formstate manually, specified in the XFA Language on the root subform as:
restoreState="manual"
Or in Designer by selecting the second radio as shown here:
What does this mean? This means that the form author decides, through script, what parts of the form will be restored when the file is reopened. In fact, for certified forms, this is the only way to restore form state. Certifying an XFA Form is disallowed if the formstate’s restoreState is set to “auto”. (If for some reason the form does get certified, by a previous version of a product that doesn’t enforce this rule for example, Reader or Acrobat will not restore the formstate on open.) First let’s see an example using a form with restoreState=”manual”.
Open the file formstate-manual-noscript.pdf. Click the “Change Country” button once or twice, save, close and reopen the file. Notice that only values are restored. The properties changed by script are not. The exception to this rule are the unbound field values and the number of subform instances, as shown on the form. This means that even for restoreState=”manual”, unbound field values (where bind=”none”) and subform instances are restored.
So what do you do if you want to manually restore the form state? Thankfully, there is a simplified method to doing this by using script.
Open the file formstate-manual-script.pdf. Follow the same steps as before. When you reopen the file you’ll see that the entire state is restored. This is accomplished by placing this script on the Form:Ready event of the root subform:
// this script restores all the deltas manually.
var oList = this.getDeltas();
for (i=0; i < oList.length; i++)
{
var oDelta = oList.item(i);
oDelta.restore();
}
You can also be more selective about which fields, and even which properties within those fields you restore.
Open the file formstate-manual-script-partial.pdf. Follow the same steps as before. When you reopen the file you’ll see that only parts of the state are restored. This is accomplished by placing different scripts on different fields, and by not placing some scripts at all. For instance the form places the following script on the listbox to restore only the list items (it does not restore the color):
// this script restores the delta for the "items" (in XFA,
// it's the <items> element) property of this listbox only.
// Ie the color is not restored but the items in the list are.
var oListDelta = this.getDelta("items");
oListDelta.restore();
You can use a similar script to restore only certain attributes of the field.
Technical Note: One important point here is that the script runs on the opening of the form when the formstate is being restored. The entire state of the form is always saved when the file is saved. But Acrobat/Reader will always check the script to restore only the parts of the form state that are specified. Why isn’t there a script to choose what part of the formstate to save? That wouldn’t be secure: A malicious person could intercept the form in transit, and inject additional information in the formstate before it reached its target. However if the script runs when the form is opened and state restored, then the script will ignore any section the author did not intend to be restored. Of course the security assurance works only if the form is certified, since certification ensures the integrity of the template, where the formstate restore script (which you implement) lives. Ie, the script which does the state restoration is covered by the certification, so we can be sure the script wasn’t tampered with.
Summary
The new formstate feature:
- allows saving state in the form where that state is not bound to data — which is a good thing since you don’t necessarily want to “mess up” your data, which may need to comply to an XML schema, with formstate-related information.
- has an automatic mode which just restores the entire state from the last time the file was saved.
- has a manual restore mode, for added security. This manual mode:
- is required if you plan on certifying your form
- is made easier by the use of deltas
- allows you to pick and choose exactly what parts of the formstate to restore.
Posted by Stefan Cameron on September 29th, 2008
Filed under
Acrobat,
Designer,
Scripting,
Tutorials,
XFA