Stefan Cameron on Forms
Building intelligent forms using Adobe LiveCycle Designer

'Events' Category Archive

XFA 3.0 Specification Available

The recent update to Acrobat/Reader 9.1 supports XFA 3.0. Unfortunately, the currently-shipping version of LiveCycle Designer (even with its update) won’t author/support more than XFA 2.8 until the next release. The comments for the XFA 3.0 spec indicate that “there will be releases [of LiveCycle Form Server and LiveCycle Designer] for XFA 3.1 and they will also handle 3.0.”

There are still some great things worth mentioning about XFA 3.0. In particular,

  • new “inactive” value for the presence attribute which, when set on a container (e.g. subform), “prevents the container and its contents from processing calculations, validations, and events”;
  • enhancements to events framework now permits event propagation upward to parent objects — this is great because you can now implement validation code on a subform for all of its children instead of having validation code in each child, for example;
  • new validation events and global validation handling control — this should address a lot of the current issues with form validation.

It looks like John Brinkman will be detailing these new features, and perhaps others, soon.

August 18, 2009 — Added links to new XFA 3.0 topics on FormFeed.


Posted by Stefan Cameron on March 24th, 2009
Filed under Acrobat,Events,XFA

Pre-Process Web Service Responses

Connecting to a web service usually means using import bindings to capture the response but what if you wanted to do something special with the response? What if the response wasn’t exactly correct for merging into your form (e.g. you just wanted to extract a part of the response and push it into your form somewhere)?

You could still use import bindings (set using the “Object palette > Bindings tab > Import/Export Bindings property”) but then you might have to hide most — or all — of those fields if you didn’t want to expose them. You would wait for the web service data connection to execute, then find the field that contains the piece of data you want and set it where it needs to go. This isn’t ideal, however, because Designer doesn’t expose any events, in the Script Editor, that would let you know that you now have data from the web service response in your form. Furthermore, having those extra fields around could add a lot of unnecessary weight (read: file size).

Continue reading…


Posted by Stefan Cameron on March 23rd, 2009
Filed under Data Binding,Designer,Events,Scripting,Tutorials,XFA

Submit or Execute on Other Events

I discovered something interesting the other day: Just because Designer wants you to type script for a field’s Full event doesn’t mean you have to execute script when the Full event is triggered.

The XFA 2.8 specification specifies the <event> node’s content as being one of the following nodes: <script>, <execute> (executes a web service data connection), <submit> (causes the form to be submitted via email or HTTP) or <signData> (causes the form to be signed). Only one may be specified and whatever content is there will be executed when the event is triggered.

This means that you could, for example, cause a web service to be executed whenever a repeatable subform’s index changes (i.e. whenever you add/remove instances).

Is this useful? Well, perhaps not, but I thought it was interesting! Who knows what you might think of doing with this…

The only catch to all this is that Designer only lets you enter script (JavaScript or FormCalc) into an event, thereby specifying an event’s content as <script> as opposed to <submit> or <execute>. If you want to, say, cause a form submit when a field’s Full event is triggered, you’ll have to go to the XML Source and set the event’s content to a <submit> node yourself. An easy way to do this is first to add an Email/HTTP Submit Button to the form, set the field’s Full event to a placeholder script, go to the XML Source view, find the button using the Hierarchy palette, copy its Click event <submit> node and paste it into the field’s Full event so it looks like what’s below and delete the button:

<event activity="full" name="event__full">
    <submit format="xml" textEncoding="UTF-8" target="mailto:"/>
</event>

Sample Form

Check-out my little sample form that causes the form to be submitted via email when you fill the text field at the top and where a web service data connection is executed whenever you add an instance of Subform2 using the button at the bottom (below the web service import/export fields).

Download Sample [pdf]

Sample Minimum Requirements: Designer and Acrobat Standard/Pro 8.0 (XFA 2.5)


Posted by Stefan Cameron on January 30th, 2009
Filed under Events,Scripting,Tutorials,XFA

XFA and AcroForm Event Object Access

XFA forms are event-driven. Pretty much every action triggers an event and in that event (e.g. Initialize, Change, Click, etc.), you always have access to an xfa.event object (see the “eventPseudoModel” topic on page 63 of the Designer 8.2 Scripting Reference) and, depending on whether your form is running in Acrobat/Reader, you will also have access to an AcroForm event object.

I have discovered that in that event isn’t quite accurate. It should rather be stated as within the context of that event. That’s because any function calls that you make from the event handler (for instance, into a script object that contains other functions — maybe your event handler simply passes execution to a re-usable event handler function that you have defined in this script object) will have access to these very useful objects.

In essence, xfa.event and event (if defined) are, for lack of a better term, contextual objects that exist — and are valid — as long as you are within the context (where context is different from usual definition of scope) of an event handler.

I had a case, just recently, where I needed to access the event.target property (that is, the AcroForm Doc object provided by Acrobat when it’s the host) in a function located inside a script object which I was calling from a subform’s Initialize event. At first, I thought I needed to pass it in as a parameter:

// Subform Initialize Event handler code
utils.InitSubform(this, xfa.host.name == "Acrobat" ? event : null);

-----
utils Script Object
-----

function InitSubform(sf, hostEvent)
{
    ...
    if (hostEvent != null)
    {
        // access AcroForm Doc object from parameter
        var pdfDoc = hostEvent.target;
        ...
    }
    ...
}

Unfortunately, this would’ve required updates to many forms since the script object was being used as a script object fragment and many forms were already using that function with only the first parameter.

Since the event object is actually available at that point in time, given that the handler is executing in the context of the subform’s Initialize event, I didn’t have to pass it in as a parameter and so I didn’t have to update a bunch of forms:

// Subform Initialize Event handler code
utils.InitSubform(this);

-----
utils Script Object
-----

function InitSubform(sf)
{
    ...
    if (xfa.host.name == "Acrobat")
    {
        // access AcroForm Doc object from in-context event object
        var pdfDoc = event.target
        ...
    }
    ...
}

Just remember that the xfa.event and event objects are only valid for the duration of the event which was triggered (so you shouldn’t hold on to them for future use) and that the event object is only available to you if the host is Acrobat/Reader (testing for xfa.host.name == “Acrobat” works for both Acrobat and Reader).

Tested with Adobe Acrobat and Reader 9.0.


Posted by Stefan Cameron on January 14th, 2009
Filed under AcroForm Objects,Events,Scripting

Handling List Selection Changes

This is something I get asked a lot so I thought I’d write a little tutorial on how to handle a selection change in a list object (drop down list or list box).

Single Selection Lists

All XFA events have an object that represents properties about the event currently in execution:

xfa.event

This object holds many interesting properties but the one that’s important here is the newText property which, for a list, contains the new selection.

It’s important to note that there are two types of list items: Ones that have text data only and ones that have both text and value data. By default, the Object palette creates lists with items that have text data only. On the Field tab, you can add/remove items and specify their text data while on the Binding tab, you can optionally set each item’s value data by checking the “Specify Item Values” box.

The xfa.event.newText property always returns the text data. You can access the value data associated with the new text data by using the list’s boundItem() method:

// get the value data associated with the new selected text data
var newValue = MyList.boundItem(xfa.event.newText);

For single selection lists, you can therefore use the text data or get the associated value data for the new selection and do something from there. The following code sample gets the new selected value data in a list object’s Change event and changes the list’s background color accordingly:

var newValue = this.boundItem(xfa.event.newText);

switch (newValue)
{
    case 1:
        this.fillColor = "255,0,0"; // red
        break;

    case 2:
        this.fillColor = "0,255,0"; // green
        break;

    case 3:
        this.fillColor = "0,0,255"; // blue
        break;
}

Multiple Selection Lists

List objects may also support a multiple selection of items. You can specify that the list supports multiple selection by setting the “Object palette > Field tab > Allow Multiple Selection” property but you cannot specify a default selection of multiple items using the Object palette (only a single default selection is supported though it still works for lists that allow multiple selections). You would have to use the list’s Initialize script to do that.

At runtime (e.g. in Acrobat/Reader), you may select multiple items in the list by using the Shift and Ctrl keyboard keys: Shift + Click will select all items from the last selected item to the item you click on and Ctrl + Click will add/remove individual (non-sequential) items to/from the selection.

Determining the selection in a multiple selection list is different from doing so in a single selection list because you have to deal with the fact that more than one item may be selected. There is also a difference in the event you must use in order to handle the change in selection: When you set the “Allow Multiple Selection” property, the “Object palette > Field tab > Commit On” property changed to allow only a setting of “Exit” (as of Designer 8.1; Designer 8.0 may have still allowed “Select” to be chosen however I recommend setting this property to “Exit” if you have the choice) which means that the change in selection — as far as the list is concerned — will only take place once the user exits the list (once they hit the Enter key, tab away or click away from the list) rather than immediately when they visually change the selection. The result is that you must handle the change in selection in the Exit Event rather than in the Change event as in single selection lists.

You can handle a change in single selection lists using the Exit event as well however for single selection lists, it’s usually preferable to handle the change immediately rather than once the user leaves the list. For multiple selection lists, the idea is that the user may click more than once to set the selection they want so you typically want to react to the change only once they’re done which is why the selection is only committed once the user exits the list.

Determining the set of selected items was really difficult leading up to Designer and Acrobat/Reader 8.0 when the new list object properties and methods were finally introduced. These new APIs make it much easier to deal with lists that contain multiple selections: Use the length property to iterate through the items, the getDisplayItem method to get the text data associated with an item, the getSaveItem method to get the value data associated with an item and the getItemState method to determine whether the item is selected or not.

Here’s our sample script from earlier that sets the background color of the list object after a change in the selection (in the list’s Change event) however this time the script is meant for the Exit event and the list supports multiple selection. The color values are combined if more than one is selected, producing more color combinations up to white (an RGB color value of “255,255,255″) then all 3 items are selected:

// array with 3 elements, all at zero initially
var rgb = new Array(0, 0, 0);

for (var i = 0; i < this.length; i++)
{
    if (this.getItemState(i))
    {
        // item is selected
        // item values are 1, 2 or 3 (1-based)
        // array elements are 0, 1 or 2 (0-based)
        rgb[this.getSaveItem(i) - 1] = 255;
    }
}

// Array.toString() produces a comma-delimited string containing the
//  values of the array elements so this will produce "255,0,255" if
//  items 1 and 3 are selected.
this.fillColor = rgb.toString();

If you give this a try, remember to create a list with 3 items (1, 2, 3) and place the script in the Exit event, not the Change event. Then remember to click away from the list once you’ve set the selection at runtime.

Multiple Item Default Selection

Setting a default selection of more than one item is unfortunately not something that Designer supports. To achieve this, you’ll need to set the list’s Initialize script to do the work. For example, to initialize a multiple selection list of 5 items where items 1, 4 and 5 are selected, you would do this (remember that list item indexes are 0-based, not 1-based) in the list’s Initialize event:

this.setItemState(0, true); // item 1
this.setItemState(3, true); // item 4
this.setItemState(4, true); // item 5

Sample

To see this in action in what you might consider a more realistic example, my “What About the Other Field?” tutorial uses single selection lists that show an “other” field when their “other” item is selected.


Posted by Stefan Cameron on October 27th, 2008
Filed under Acrobat,Designer,Events,Scripting,Tutorials,XFA