Exclusion Groups v2.0

This is the second blog entry describing a DIY exclusion group. If you have not read part one, you should probably start there before trying to digest part two.

I wanted to build on the functionality of the exclusion group from the previous blog entry:

  1. Allow the form author to include nested subforms and radio button lists within the exclusion group
  2. Improve the handling of different field types
  3. Move the script logic outside the exclusion subform

The sample

The example is a form to choose a payment type. The payment type is an exclusion group with three kinds of content: a checkbox, radio button group and subform. The user chooses one of: cash (checkbox), cheque (radio button list specifying kind of cheque) or credit card (subform with all the credit card fields). When they choose a payment type, then the other payment types are cleared. Here is the sample.

Nested Subforms

Notice that the credit card fields are wrapped in a subform. The subform behaves as a single unit in the exclusion group. When any field inside the subform is selected, the subform is considered to be selected.

Field Types

The form in my previous post handled only check boxes and text/numeric fields. This sample includes handling for choice lists and radio button groups. The logic to check if a field is selected or not varies by field type.  This version of the exclusion group is more rigorous in its checking. Similarly, the logic to clear an entry varies according to the kind of object.

Separate the script

You will notice in the form that I moved the script into a script object called “utility”.  This is so that the script is not included (and duplicated) each time the form author includes another exclusion subform on their form.  It does have the downside that the form author needs to remember to add the utility script to the form.

To make this more foolproof, I have added a simple check at the beginning of the exclusion group calculate:

if (typeof(utility.makeExclusive) == “undefined”)
xfa.host.messageBox(
“You need to include the utility script object!”);

If utility.makeExclusive is found, the JavaScript typeof() function will return: “function” otherwise it returns “undefined”.
If your form author has forgotten the script (or put it in the wrong place) this simple check will notify them the first time they preview the form.

The Algorithm

Just as in the previous post, you do not really need to read past this point if you do not want gory details. Just take the sample, remove the contents from the exclusion subform and add the subform to your object library.  Do the same for the utility script. The whole point is that the logic is self contained, reusable and you can add content without writing any new script.

Hopefully reading the script code is self-explanatory, so I’ll just highlight a couple points here:

Get field type

In order to check the field type, the script needs to examine the content under the <field><ui> element. In the XFA grammar, this element is expressed as a “one of” relationship. The widget-type-child of <ui> must be one of: <barcode>, <button>, <checkButton>, <choiceList>, <dateTimeEdit>, <defaultUi>, <exObject>, <imageEdit>, <numericEdit>, <passwordEdit>, <signature> or <textEdit>. The convenient way to select this element is with the oneOfChild script property. So then the code to check if a field is a check button looks like:

if (vContainer.ui.oneOfChild.className == “checkButton”)

Code Additions

There are new functions: isSelected() and clearContainer(). Previously we assumed all members of the exclusion group were simple fields. Checking if a field was selected or clearing a field were one-liners. Now that we support subforms and more field types, these operations are more complex and we modularize them into functions.

That’s all for now.  Next up: min and max selections.