Archive for February, 2011

Multiple Top Level Subforms

I’m willing to bet that all the XFA form definitions you’ve looked at all have one top level subform.  Not surprising, because that’s what Designer
allows you to author.  But according to the XFA specification, there can be any number of top-level subforms below the <template> root.

Today I’ll briefly describe the processing rules for top-level subforms, provide a simple example where you might find them useful, and give you a couple of macros to make these easier to work with in Designer.

The Processing Rules

The rules are simple:

  • When there are multiple top-level subforms, only one is rendered.
  • We choose which subform to render based on which one best matches the data.  i.e. the template behaves like a choice subformSet: <subformSet relation="choice">. 
  • If no data is supplied, we render the first subform below the <template> element

A Sample

Suppose I want different variations of my form for printing and for interactive.  I construct my template so that it has top level subforms for both print and interactive.  Since the binding is all "by name", the form will render according to the name of the top level node in the data.  Try previewing the sample with these data files: interactive.xml, print.xml — or import these data files in Acrobat, and you’ll see the form change according to the data provided.  However, controlling print behavior with different data files is more applicable on the server than on the client. 

In order to force the form to use the print subform when printing from Acrobat/Reader, I added a pre-print event to the interactive root subform.  The script renames the top level node in the data, and forces a remerge.  This will cause the print operation to use the print subform.

interactive::prePrint – (JavaScript, client)
xfa.record.name = "print";
xfa.form.remerge();

Then to restore to the interactive view, I added a postPrint event to the print subform:

print::postPrint – (JavaScript, client)
xfa.record.name = "interactive";
xfa.form.remerge();

Design Experience

I’ve already hinted that Designer doesn’t really support multiple top-level subforms. But with a couple of handy macros, we can get by.

First problem is that there’s no easy way to create a new top level subform.  Here’s a macro to proide that functionality.  You’ll notice when you run the macro that there’s a problem.  The changes made by the macro don’t show up in the hierarchy.  This is a bug that will be fixed next release.  Meanwhile, closing and re-opening the form will workaround the issue.  Note that the macro to add the new top level subform also inserts a default master page (<pageSet>). Designer and the XFA runtime are generally very unhappy if they don’t have a set of master pages to work with.

Next problem is to figure out how to edit the new top level subform in Designer.  Here’s a macro to solve that problem. Since Designer always renders the first subform, this macro re-orders the top-level subforms so that you get a different top-level subform. Specifically, the macro re-orders the first subform to be last.  Just make sure that when you save the form that your preferred default subform is first in order.

Now, for the specific example of print and interactive variations, I could have implemented the solution in a number of different ways.  e.g. with a choice subformSet or with optional subforms at the second level in the hierarchy.  But the point was to bring to light some functionality that you might not otherwise been aware of.

Disable your form in older versions of Reader

When designing forms that require newer versions of Reader, you may want to be intentional about the experience users get when they open the form in older versions of Reader.  Today if you target a form for
Reader X and open it in Reader 9, you get this dialog:

After you’ve dismissed the message, Reader goes on to display the form as best it can.

The problem is that "as best it can" could lead to a very poor experience.  If you have functionality in your form that relies on a more recent Reader, then in all likelihood, your form is broken.  This could manifest itself in any number of ways.  e.g. Validations not firing correctly or the form not displaying correctly. 

As a form author, you’d prefer to prevent the user with an old version of Reader from having any interaction with the form.  No experience is better than a bad experience.  The topic for today is a design pattern to author a tailored experience for the user with an older Reader.

Design Pattern

There are probably several ways this can be done. I’ve chosen to add a version-checking subform below the root.  This version-checking subform has the following properties:

  • Contains content that warns the user that their version of Reader is not new enough
  • Points the user to the reader update page
  • Has a form field with the required Reader version number
  • Has an initialization script that compares the Reader version to the required version
  • If the Reader version is not new enough, the initialization script will remove instances of other subforms below the root and make sure the version checking subform is visible.
  • If the Reader version is new enough, the initialization script will add instances of other subforms below the root and hide the version checking subform

For this script to be effective, the other subforms below the root must be defined with occurence settings where the minimum is zero and the initial number is also zero:

I have attached a sample form that uses this technique. The form is targeted for Reader 10.  If you open it in version 9, you will get the version check warning experience.

Merging text to a caption

In your form design you have two choices when it comes to labelling your fields.  You can either place the descriptive label text in a field caption or you can create a separate text object with the label text. 

There are pros and cons to each, but today I am going to try and convince you to use captions — and give you a tool to make it easier to create captions.

Whether your descriptive text is stored as a separate object or whether it is specified as a caption, in most cases we can achieve the same visual effect with either. Admittedly there are some layout conditions where a caption cannot be used.  e.g. where the label extends both above and to the left of the field.  But this is the exception.

The advantages of using separate objects:

  1. Absolute control over label positioning
  2. Can be less effort to author in this mode

The advantages of using captions:

  1. Far better accessibility experience
  2. Results in smaller form templates with better performance
  3. Lower form maintenance

Accessibility

Field captions can be used to generate a good accessible experience.  The caption text can be used as the text that the screen reader uses to describe the field. Obviously when it is stored as a separate object we do not have this correlation. When the label is a separate object, we have extra “noise” as the screen reader traverses the read order of the document. The read order will encounter the label and the field as objects that will be read separately.  If they’re not consecutive in the read order, there is potential for even more confusion.

Form Size

As I’ve mentioned before, form size matters. If your form is delivered with rights enabled and/or with certification, the time to open the form is directly impacted by the size of the form template.  This is because both RE and certification use encryption and we need to validate that the form has not been tampered with at open time.  To make a long story short, the validation involves loading the form template more than once.  If there are fewer objects and less syntax, the form will load faster and open time will be reduced.

Lower form maintenance

When a caption is combined with a field, then all operations treat the field and caption atomically: 

  • A script to make a field invisible will also hide the caption. 
  • A page break will never separate a field from its caption, but could separate a field from label text. 
  • Moving or deleting a field in Designer automatically does the same for the caption. 

The Form Conversion Problem

My suspicion is that very few form authors consciously choose to separate the label from the field.  In most cases this is a byproduct of a conversion process from some other format to XDP.  The form author’s starting point is a form design where all fields are separated from their caption.  The question becomes: is it worth the time and effort for an author to combine these objects?  Is the net gain worth the investment?  The answer is dependent on your own scenario — and dependent on the amount of effort to fix the form.

Designer has a built-in function that will combine text and field into a combined field with caption.  You select the text and the field and choose “Layout/Merge as Caption”.  The problem you’ll find is that while designer does combine the objects, it does not preserve the layout, positioning, font and paragraph properties of the label when converted to a caption.  I think you will see this function improve in future versions of Designer.  But in the mean time, this is also a function that can be customized using a designer macro.  Here is a designer macro you can install that will combine labels with fields when the label is positioned above the field. 

You should find that the macro works fairly hard to give you a finished result with the same visual appearance as the original.  Here is a sample PDF with the separated label/text on the left and the combined result on the right. 

As I was writing the macro, I realized there are cases where the end-user might want a different behaviour than I’ve provided.  For example, when the caption is wider than the field, should we expand the field to match the width of the caption? That was the choice I made. If you prefer a different result, you can tailor the macro to your own needs.

Enjoy.  Hopefully there’s enough of a starting point here that someone could expand the macro to also handle captions placement to the left/right/bottom of fields.