Exclusion Groups v3.0

This is the third and final post describing a pattern for building your own exclusion group.  The first two posts are required reading for this entry:
Build a better exclusion group   Exclusion Groups v2.0

The included sample builds on version 2 and adds a couple of useful pieces of functionality:

  • Allow the exclusion group to have multiple entries selected
    (specify the minimum and maximum selected entries)
  • Make the exclusion group mandatory
  • Make the sample work in Reader 7

The Sample

Go ahead and open the attached sample. There is a new exclusion group, and for completeness I have also included the previous two examples.  When you open the sample, turn on field highlighting so that you can see when fields are mandatory (highlighted with a red border).  The sample shows a case where the user needs to select a minimum of one phone feature and a maximum of three.  Note these behaviors when you fill the form:

  • On opening the empty form, the fields are all highlighted red (mandatory) because none are selected — we are below the minimum selected.
  • When you select one entry, the mandatory setting is turned off. 
  • When you get to three selected entries, the remaining unselected entries are made read-only in order to prevent the user from selecting too many. 
  • If any entries are subsequently unselected, then the read-only setting is removed.

Code Changes

Initialization

There is now an initialization script on the exclusion subform to establish the minimum and maximum entries:

utility.setMinAndMax(this, 1 /* min */, 3 /* max */);

When users drags this object in from the object library, they need to tweak the initialization script to get the settings they want.  Note that if they set the maximum to one, then we use the toggling behavior when selecting entries (selecting one entry unselects another).  If they set a maximum greater than one we use the explicit select/unselect ui experience.

New functions

The script includes three new functions setMinAndMax(), setReadOnly() and setMandatory() plus new logic in makeExclusive() to set the mandatory and read-only states of exclusion group members.  From the behaviors described above and the code comments you can probably figure out how they’re used.

isSelected()

The logic inside isSelected() needed to be changed in order to support Reader 7.  Previously we relied on the selectedIndex property to determine if a checkbox was selected.  When selectedIndex is zero, the field is considered on/selected.  Grammar-wise, this is represented by this markup:

<field>
  <items>
    <text>yes</text>
    <text>no</text>
  </items>
</field>

selectedIndex refers to the position in the current chosen element in the <items> array. Since selectedIndex was not introduced until Reader 8, the alternate (Reader 7 compatible) strategy is to compare the value of the checkbox field to the first element under <items>.  If they are equal, the field is selected.

What Else?

I debated whether to expand on the logic behind isSelected().  For numeric fields, you might consider a value of zero to mean "not selected".  Also, there is probably more that could be done to support mandatory logic inside nested subforms.  For now I will leave these as an exercise for the user :-)

Summary

This is probably a good time to issue a caveat emptor.  These samples are intended to encourage some specific design patterns.  They are not supported objects for you to immediately use in your production forms.  You need to adapt them to your own needs and you need to test them in your own environments.

The main points I hope you take away from this exercise:

  • You can package your desired exclusion group experience into library objects without requiring users to add code to individual entries in the group
  • Tweak the provided sample to your own needs and include it in your object library
  • Centralize the script logic — do not have more than one copy in your form

3 Responses to Exclusion Groups v3.0

  1. Leah Kalasky says:

    I have a form where I want to specify the minimum and maximum selected entries. I copied your subform into my Library. When I attempt to place it into my doc, it is grayed out. Could it be because I am working with a file that was a pdf previously? Under Hierarchy, I don’t have any subforms and don’t see where to insert one. Thanks for any help.

  2. Leah:Yes, this is because your form started out as an imported PDF — and you kept is as “fixed pages”. In these cases we do not allow subforms in the PDF.If you must keep it as a fixed PDF, then the way around this would be to create a variation where the calculation to enforce exclusion resided in a hidden field. This field would have to keep a list of field objects and the global script objects would have to be updated accordingly.I will add this to my list of blog topics and see if I can eventually propose a re-usable pattern. But it will not be as easy to use as the subform-based version.John

  3. Two notes regarding this post:1) For Leah, in case you haven’t seen it already, I have added a blog entry with a sample that does what you asked for. See: http://blogs.adobe.com/formfeed/2008/12/exclusion_groups_v40.html2) I have updated the sample in this post to illustrate how to make execValidate() work for mandatory checkbox fields. See Tom’s comment and my reply at the exclusion group v4.0 post.John