In this post I have consolidated a bunch of tools and tips for developing and debugging XFA/PDF forms.
Use the console Object Effectively
Always show the console on errors
The console methods
console.println() is an indispensable tool for tracing what is happening in your form script logic. It is much more effective than xfa.host.messageBox() or app.alert(), since it doesn’t require dismissing a dialog with every message.
Did you know there are other methods on the console object? clear(), hide(), show(). You might want to place a call to console.clear() when your form initializes. When it’s time to deploy your form, make sure you haven’t left any extraneous messages in the console.
The Server Alternative
Since the console object is an acrobat-specific tool, you need to use something different to emit trace message for server-based XFA forms. For the server, use xfa.log.message() to write your message to the server log file.
Trace Function Calls
Have a look at the data DOM
It’s often useful to see what the data currently looks like. One way to get there is to add a big text field that displays the data dom. Give it this one line calculation: xfa.datasets.saveXML("pretty"); Set the field as bind="none". Now you will have an up-to-date snapshot of the state of the data dom.
Re-factor your form
Design for re-usability. Develop common patterns that are shared between forms. Create script frameworks inside script objects. Put the framework script objects in your fragment library.
Use the Merge/Layout Debugger
If your problems are in merge or layout, then try this. (Try it even if you’re not having problems with merge/layout — it’s cool.)
When an exception is thrown and displayed in the console (or in the server log file) the resulting message can be frustratingly cryptic. To get higher quality information (including a stack trace), catch errors and parse them into human-readable text. There is sample code here to get you started.
Be Version Aware
If you make extensive use of script objects or if you’ve dabbled in using dynamic properties on XFA objects then get educated about the effects of strict scoping and how it behaves in different versions of XFA and Reader. Read lots more here and here.
Summarize your form
This post shows how to get a "big picture" summary of the form meta data and the content in the form.
Document your Script
Reduce and Isolate your problem
If you are struggling with a particular problem, try to reproduce the problem in a new, simplified form. The act of isolating will often lead to discovering any outside influences are affecting your form behaviour. If you’re still having the problem in your new simple form, then you have a simplified version of the problem that makes it easier to share with others when you ask for help.
Designer Script Editor
Turn on Line Numbers
In your designer script window, turn on line numbers by right clicking on the script window and selecting "Show line numbers" from the context menu.
Don’t Leave Blank Lines at the Top of your Script
<control>+f — bring up the find dialog. Any highlighted text is automatically used as the find string. <control>+h — brings up the find/replace dialog. F3 — find next. <shift>+F3 — find previous.
Convince your boss you need two monitors. Keep Designer in one monitor and place your script editor and Acrobat console in the second monitor.
"foo.bar is not a function"
Your script makes a call to foo.bar() and you get the mysterious message: "foo.bar is not a function". But you look in your script object and it sure looks like it is defined. The problem is that you have a syntax error somewhere in your foo script object. This prevents the runtime from discovering the foo.bar() function. When you see this message, run Designer’s script syntax checker.
Declare your Variables
Don’t code: for (i=0, i<myList.length; i++)
Instead, code: for (var i=0, i<myList.length; i++)
While you’re at it, use variable names that are unlikely to collide with names of objects on your forms. Such as prefixing variables with a "v" or "n" or "s". (vObject, nOffset, sStringValue).
Beware of Ambiguous Expressions
If you’re writing code that is intended to be re-usable in multiple forms, beware of potential conflicts between property names and form objects. For example, the expression subform.border.fill.color becomes ambiguous if this script in a context where the subform has a field child named "
;border". To avoid ambiguity, use the expression: subform["#border"].fill.color. The hash symbol specifies that what follows is a className instead of a container name.
Find the Root Subform
If you have re-usable script that needs to locate the root subform, you can use this expression:
Or the slightly more terse:
Don’t Modify Your Form in XML Source Mode
If you need to change a property that Designer doesn’t expose in one of it’s property editors, then change the property via script. For example: Designer doesn’t support making a positioned subform repeatable. Rather than adding an <occur> element in XML source, set this property in script:
Subform1.occur.max = "2";
var vNewSubform = _Subform1.addInstance();
Batch Changes to your Form
June 16, 2009 update