TeamSite Form API Guide
TeamSite Form API Guide
Reference Guide
Version 7.1
Document Revision 1
December 2009
Copyright Notice
Notice
This document is a proprietary product of Autonomy and is protected by copyright laws and international treaty. Information in this manual is
subject to change without notice and does not represent a commitment on the part of Autonomy. While reasonable efforts have been made to
ensure the accuracy of the information contained herein, Autonomy assumes no liability for errors or omissions. No liability is assumed for direct,
incidental, or consequential damages resulting from the use of the information contained in this document.
The copyrighted software that accompanies this document is licensed to the End User for use only in strict accordance with the End User License
Agreement, which the Licensee should read carefully before commencing use of the software. No part of this publication may be reproduced,
transmitted, stored in a retrieval system, nor translated into any human or computer language, in any form or by any means, electronic,
mechanical, magnetic, optical, chemical, manual or otherwise, without the prior written permission of the copyright owner.
This document may use fictitious names for purposes of demonstration; references to actual persons, companies, or organizations is strictly
coincidental.
December 2009
Contents
Intended Audience. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
Notation Conventions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
Manual Organization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
Documentation Updates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
Chapter 1:
Overview
13
Chapter 2:
Using FormAPI
15
Chapter 3:
FormAPI Reference
15
17
18
18
19
20
21
23
25
25
26
27
29
32
34
38
40
41
41
41
42
45
Contents
81
67
73
77
78
80
81
81
83
85
85
85
86
87
88
88
88
91
92
92
93
97
98
Figures
Figures
Tables
Table 1
Table 2
Notation Conventions................................................................................................. 9
Events Available to User Scripts.............................................................................. 67
Tables
Intended Audience
This book is written for those who are developing FormsPublisher forms and wish to use API
calls to enhance those forms.
Notation Conventions
This manual uses the following notation conventions:
Table 1
Notation Conventions
Convention
Bold
Text that appears in a GUI element such as, a menu item, button, or
element of a dialog box, and command names are shown in bold.
For example:
Click Edit File in the Button Bar.
Italic
Monospace
Table 1
Notation Conventions
Convention
Monospaced
italic
This means that you must replace role and user with your values.
Monospaced bold
Monospaced bold
italic
The term Windows indicates any supported version of the Microsoft Windows operating
system, such as Windows 2000.
Directory paths use UNIX conventions. These conventions mandate using forward slashes (/
) in path names. (Windows systems use backward slashes.) The Windows convention is used
when referring to a Windows-specific directory. For example:
UNIX: docroot/news/front.html
Windows: docroot\news\front.html
Manual Organization
This manual is organized as follows:
10
Manual Organization
Appendix A, Sample User Scripts, describes the sample user scripts that ship with
FormsPublisher.
Documentation Updates
Additions and corrections to this document (when available) can be downloaded in PDF format
from the following Web site: https://customers.autonomy.com.
11
12
Chapter 1
Overview
FormsPublisher FormAPI allows you, as a template designer, to create forms that dynamically
respond to user actions and other external events. With FormAPI, browser templates are no
longer simple, static forms. They can become responsive, interactive, highly customized
interfaces that greatly enhance the experience of the user entering content.
Some of the things you can do with FormAPI include:
Automatically compute the value of one field based on the value of another (for example, a
Totals field is computed from a set of Price replicants).
Change the options in a selection element based on the value of another element (for
example, after the user has entered City and State, a database query automatically populates
the ZIP Code field with the valid ZIP codes for that city).
Make an entry field appear or disappear as needed (for example, the Shipping Address
fields only appear if the user unchecks Same as billing).
Intercept the Save button press to provide custom data validation (for example, warn if the
user has entered a value for Project Start Date that is after the value for Project End Date).
Automatically set the name of the data record (DCR), based on the value of other fields (for
example, use the value from the Model Number field of a product description record for the
file name, precluding the need to prompt the user for a name).
You enable this functionality by writing a user script that is included (either in-line or
referenced) in the data capture template (DCT). A user script is custom JavaScript code that uses
FormAPI to interact with the data capture form presented by FormsPublisher. Almost anything
that can be done manually by the user entering content into a form may be scripted (thus the
name user script) through FormAPI.
At the heart of FormAPI are the event registry and the form item object. The event registry
allows you to associate a user script function to a user event, such as changing the value of a
selection or clicking the Save As button. The FormAPI item object represents an individual form
element, like the Name entry field or the Gender radio button set. The item object provides
methods that let you dynamically query and change its value and other attributes. A user script
author identifies an item by its address, which is an XPath(1)-like notation that references an
item relative to its position in the DCR.
13
Chapter 1: Overview
FormAPI also provides numerous other methods for operating on the form as a whole and for
querying attributes of the DCR.
Some important things to note about FormAPI:
FormAPI supports DCRs from both the Interwoven DTD and from custom DTDs.
FormAPI is a JavaScript API. This documentation assumes the user is familiar with the
language syntax, features and limitations. An excellent reference is JavaScript: The
Definitive Reference, 4th ed, by David Flanagan, O'Reilly and Associates, 2004.
The user script does not interact with the browser document object model (DOM) interface
to the HTML form. Instead, FormAPI provides methods to query and set the values of items
in the form.
This lets FormAPI provide a consistent interface to form items that have no DOM analog
(like VisualFormat textareas or items that are not currently on the displayed page in
multipage forms) or to features that the DOM does not support (such as custom validation
expressions for an item).
JavaScript authors familiar with the DOM will find the FormAPI interface very similar,
however.
While user scripts may interact with the user in a number of ways (like JavaScript dialogs or
new browser windows), FormAPI itself presents no visible elements to the user.
User scripts must be valid JavaScript code that use FormsPublisher FormAPI only as defined in
this document. Failure to do so can result in unusable templates.
Some of the FormAPI features are applicable to a single file only and are not supported for the
multi-file tagging. These include:
14
Features pertinent to a single file (for example, the DCT attribute to hide a tab).
Asynchronous callbacks (for example, CallServer, IWDataSource, and other AJAX calls).
The next chapter (Chapter 2, Using FormAPI) provides details on how to include user scripts
in templates and discusses some of the methods in detail. Chapter 3, FormAPI Reference
provides a complete reference to all the methods in FormAPI.
15
Chapter 1: Overview
16
Chapter 2
Using FormAPI
This chapter provides information on how to set up FormAPI so it can be used in your data
capture templates. It also provides information and examples on other aspects of FormAPI that
will help improve your results.
As this snippet from the DTD indicates, the <ruleset> element in the DCT now takes any
number of <script> tags. The <script> tag has three attributes: language, location, and src,
and it may also have content.
15
The language attribute defaults to javascript. Currently, FormAPI has a JavaScript binding
only.
You may specify a user script in either of two ways:
You can include the user script in the DCT in the <script> tag, as a CDATA section. This
has the advantage that the code is always with the template definition and changes that
affect both parts can be maintained in a single file.
You can keep your code separate from your DCT and point FormsPublisher to your file
using the src and location attributes. This makes it easier to share the file across templates.
To place the code inline in a CDATA section, place the content within the XML CDATA
markers, <![CDATA[ and ]]>. For example, the following code opens an alert when the template
is first loaded:
<ruleset name="TeamSite Templating">
<itemref name="Address"/>
<script>
<![CDATA[
alert ("Hello, world!");
]]>
</script>
</ruleset>
Alternatively, you could save the script in a file called hello.js and specify its location using
the src attribute. The actual location the src attribute points to may be anywhere on a
webserver, in the same directory as the data capture template type definition, or somewhere else
on the same TeamSite server. The value of the location attribute controls how the src attribute is
interpreted:
webserver
The src attribute is the URL of the target, for example http://myserver/mypath/hello.js.
This is the default if the location attribute is not specified.
template-type
In this case, src specifies a location relative to the template type directory. So if hello.js lived
alongside the DCT in:
/iwmnt/default/main/WORKAREA/user/templatedata/category/type/hello.js
16
Initialization
Typically, a user script consists of a set of functions, usually with one initialization function.
The last line of the user script usually includes a call registering this initialization function to be
called when the onFormInit event occurs that indicates the form load is complete. This
call-back mechanism ensures that certain operations that might affect form elements are not
attempted until the form has been completely processed (see Initialization). In any case, the
JavaScript code is simply executed as it is loaded, as it would in any browser frame.
Because FormAPI and the user script code loaded by the <script> tag all reside in the same
frame, it is important to adhere to naming conventions to avoid collisions in the global
namespace. Identifiers that start with IW, iw, or _iw are reserved for use by FormsPublisher.
Initialization
Initialization describes the process by which FormsPublisher creates form objects that can be
manipulated with FormAPI calls. For performance reasons, user script code is loaded at
approximately the same time as the data capture form is initialized. Operations directly affecting
a visual aspect of an item, such as visibility, readonly, and collapse state, may be sensitive to the
timing of form initialization. To ensure that FormAPI operations (perhaps to make a container
invisible) occur after initialization is complete, FormAPI provides a form event OnFormInit to
defer execution of user script code. Typically this might look like:
function init() {
var containerToHide = IWDatacapture.getItem("/myform/hidden");
if (containerToHide){
containerToHide.setVisible(false);
}
}
IWEventRegistry.addFormHandler("onFormInit", init);
It would be possible to simply call the init function; however, doing so risks that the form has
not completed initialization, and some or all of the items the user script code will try to modify
may not have been completely created. In the example init() function above, this might result
in an apparent failure of the setVisible() operation (since the setVisible() operation will fail
silently). Using the onFormInit event ensures that the setVisible() operation is not called
until the form items are properly initialized.
17
Addressing
Addressing is a means of selecting an individual item in the data capture form. It is also used to
register event handlers for an item. The notation of FormAPI item addressing is similar to the
W3C XPath Recommendation (http://www.w3.org/TR/xpath).
NOTE
The similarity to XPath is limited to the simple notation for node names. Other features of
XPath such as wildcard characters, functions, and relative paths are not part of FormAPI item
addresses.
FormAPI addressing provides a single, consistent view of the DCT's item structure regardless of
its source. Hence the address of an item is directly derived from the DCT that defines it. Each
and every item that is directly in the hierarchy of an item in the DCT needs to be included in the
address regardless of whether the item has a pathid or location attribute. This applies to both
Interwoven-style templates as well as custom DTD templates.
This is necessary because a tab is structurally like a FormsPublisher container, and FormAPI
must be able to distinguish between items that have the same name but are located in different
tabs (containers). If you have existing FormAPI code that specifies a path to a non-tab item and
you modify that item in datacapture.cfg so that it now resides within a tab, you must update
your FormAPI code so that the absolute path for the item contains the tab name.
NOTE
Tab names are not required in data records because data records pertain only to saved data. The
location and pathid attributes in the <container> and <item> elements in datacapture.cfg
specify the data record location for the items data. The <tab> element, on the other hand, does
not have a location attribute. Therefore it is non-located and has no representation in the data
record.
18
Addressing
Addressing Syntax
The notation used for item addresses is similar to basic XPath syntax, which is similar to the
UNIX file system addressing. Consider a simple XML file:
<state>
<city>
<street>This is the street node</street>
</city>
</state>
For this XML snippet, the address for node street is /state/city/street, where street is a
child of city, which is a child of state. If the path starts with a forward slash /, then it
represents an absolute path to the required element from the root element. Absolute paths are the
only notations allowed in FormAPI. Relative paths are not supported.
If you consider an XML document to be a tree of nodes, then the address to a particular node is
/parent_node_address + /child_node_name. If a parent node has multiple children with same
name, then the address to the child node contains its position as a number in square brackets
next to its name. This address will look like: /parent_node_address/
child_node_name[position], where position is a positive integer.
There is an important difference between FormAPI address notation and XPath. The path
consists of name attributes, instead of using the tag names to represent an address.
So the corresponding DCT snippet might look like:
..<container name='state' ... >
<container name='city' ... >
<item name='street' ... />
</container>
...
19
Because node c is a replicant, the address of the first instance is /a/c[1], while that of second
instance is /a/c[2], and so on.
To intercept the onItemChange event on all instances of node c item, register a handler to the
address /a/c:
IWEventRegistry.addItemHandler("/a/c", "onItemChange", handle_c_changed);
To register an event for only a specific instance of a replicant, give the path to that replicant.
20
Addressing
Addressing Examples
Example 1: Container Addresses
For this DCT:
<container name="Story" combination="and" location="story">
<item name="Section" location="Section">
<text required="t" maxlength="100"/>
</item>
</container>
The address for the item Section would be /Story/Section. The address for the item Story
would be /Story.
21
NOTE
</ruleset>
</data-capture-requirements>
In this example, the MixedContent item has a mixture of both PCDATA and subelements (item j).
Addresses for items are:
instance of MixedContent
Note that PCDATA only appears in an address if it is part of a mixed content element.
22
The following userscript code returns the item object that corresponds to the element e:
item = IWDatacapture.getItem("/b/e");
To get the parent item that corresponds to the element b, use the '..' notation:
parent = IWDatacapture.getItem(item.getName() + "/..");
The items <text>, <textarea>, <hidden>, and <browser> have simple string values. (For
VisualFormat controls, the string is the HTML that is generated by the contents of the field.)
Single <select> and <radio> items have a single integer value that represents the
zero-based index of the currently selected option.
Multiple <select> and <checkbox> items have an array of integers that represent the
zero-based indices of their selected options.
The items that have options use the index of their selections and not the label or the value of
their options. FormAPI provides four methods to access the options of an item:
getOptions()
addOption()
removeOption()
setOptions()
The getOptions(), addOption(), and setOptions() methods all make use of the standard
JavaScript Option object. This object has text and value properties to access the label and value
of the option, respectively. The text of an option is the label the user sees in the form. The value
of an option is the value that is saved in the DCR.
23
One of the most powerful features of FormAPI is the ability to dynamically change the available
options of an item. For example, suppose the DCT specifies that the city selection has options
for New York, Chicago, and Los Angeles:
<item name="city">
<label>City</label>
<select>
<option value="ny" label="New York"/>
<option value="chi" label="Chicago"/>
<option value="la" label="Los Angeles"/>
</select>
</item>
Here, we used the JavaScript Option object constructor to create the new entry for Boston. By
specifying false to both the selected and defaultSelected arguments, the new option is added
without changing the current selection.
Alternatively, you could replace the entries in the city selection with a new list of cities:
newOptions = new Array();
newOptions[0] = new Option("London", "lon", false, false);
newOptions[1] = new Option("Paris", "par", false, false);
newOptions[2] = new Option("Madrid", "mad", false, false);
IWDatacapture.getItem("/city").setOptions(newOptions);
24
The most simplistic approach is to use labels that match values. This is easily implemented
if this constraint is acceptable.
The DCT can be configured to list the superset of all possible options, and the user script
dynamically sets the correct subset it needs on startup. This, too, is easily implemented but
is not acceptable if the options are dynamically generated or queried from a large external
source.
The best solution is to ensure that the user script restores the options of a selection if the
value does not have the right label. This requires querying the option and checking the label
of the selected option. If it is not correct, a new options array is created that adjusts the
problem. Because the user script usually has the ability to regenerate the option, this
approach is the most flexible.
Empty Options
If a single <select> item has no value (and no default value), FormsPublisher renders the select
list with an extra blank option at the top.
Even though this blank entry is physically present in the list to enable the user to make no
selection, it is not returned by the FormAPI option methods. If a single <select> or <radio>
item is unselected, getValue() returns null. Calling setValue(0) selects the first non-blank
25
option; calling removeOption(0) removes the first non-blank option. The options array returned
by getOptions does not include the blank option.
Because FormsPublisher uses the empty string to represent the case of no selection, options
should not have empty values. If they do, options with empty values are treated as if no selection
was made.
Multiple <select> items are unaffected by this behavior because they natively support the
empty selection when none of their options are selected. If a multiple <select> has no option
selected, getValue() returns an empty array.
Events
To respond to user actions dynamically, the user script needs to be notified that the user has done
something. It does so by listening for a FormAPI event, which is triggered (generated) as the
user interacts with the form. Specifically, FormAPI triggers events when the user:
Changes the value of an item, for example, by typing text into a text field or changing the
value of a selection (onItemChange). This event is generated for the specific item.
Tries to close the form (onClose). This event is generated for the entire form.
Clicks the callout button for an item (onCallout). This event is generated for the specific
item.
Adds, moves, deletes, collapses, or expands a replicant. This event is generated for the
specific item.
Previews or generates a form through a presentation template. The event is generated for the
entire form.
Tries to save the form, either by clicking Save or Save As, or by requesting a save when
prompted after clicking Preview or Generate (onSave). This event is generated for the
entire form.
Events are also generated at various stages of the save process (onSaveValid,
onSaveNameSpecified, and onSaveDone).
A user script registers a handler (also known as a callback) to a particular event (or, in the case
of the item-specific events, to an item and an event). A handler is a user script function that is
called when the event triggers. Depending on the event, the handler may be passed arguments
(for example, the onItemChange event handler is passed a copy of the item object that triggered
the event).
26
Events
FormAPI supports multiple event handlers, allowing the processing of multiple events from
multiple servers in the same form. For example, data from MediaBin and WorkSite servers can
now be used to populate the same data form.
Use the methods of the IWEventRegistry object (see Event Registry - IWEventRegistry) to
register (or remove) an event handler. For example, to call the nameChanged() function every
time the user changes the value of the /name item:
IWEventRegistry.addItemHandler("/name", "onItemChange", nameChanged);
The user script author does not use the browser's events or DOM in any way. The user script
only needs to interact with FormAPI events.
The following sections describe the onItemChange and SaveEvents event handlers in more
detail. See Event Registry - IWEventRegistry for the complete list of events.
onItemChange
The most commonly used event is onItemChange. It is triggered:
On a <text> or <textarea> when the user finishes typing and the focus leaves the item with
a different value than it had before.
On a single <select>, <checkbox>, or <radio> item whenever the user makes any selection.
On a multiple <select> list when the user leaves the item, and the set of selections is
different than it was before.
As in the browser event model, this event usually corresponds to the browser's onChange event.
The exception is multiple <select> items, which call onItemChange only when the focus leaves
the item (the browser's onBlur event) and the set of selections changes.
The handler for an onItemChange event is passed a copy of the item object that triggered the
event. This object also has a special property set, oldValue, that stores the value of the item (as
returned by getValue()) before the user made the change.
For example, if onItemChange for the /name is registered to the nameChanged() function as
above, then nameChanged() could restore the original value of the field if the user erased it:
function nameChanged(nameItem) {
if (nameItem.getValue() == "") {
nameItem.setValue(nameItem.oldValue);
}
}
27
NOTE
Because of the performance penalty involved in computing VisualFormat values, the oldValue
property is unavailable on these items.
28
Events
Save Events
The save process is more complicated because it involves several steps:
Figure 1
A save may be initiated in several ways. The user might click the Save or Save As button. The
Preview and Generate buttons also give the user the opportunity to save the DCR before
proceeding. All of these conditions trigger an onSave event.
29
The onSave event handler is passed an integer that indicates what button triggered the event. In
this way, the save handler can determine how the save was triggered and behave differently if
necessary:
function saveHandler(button) {
switch (button) {
case IWDatacapture.SAVE_BUTTON:
case IWDatacapture.SAVEAS_BUTTON:
case IWDatacapture.SAVECLOSE_BUTTON:
// User clicked 'Save', 'Save As' or 'Finish'
...
break;
case IWDatacapture.PREVIEW_BUTTON:
case IWDatacapture.GENERATE_BUTTON:
// User clicked 'Preview' or 'Generate'
...
break;
}
}
NOTE
If an onSave event handler is registered, it must return true for the save to proceed. If it returns
false or null, the save is terminated.
If the save proceeds, FormsPublisher validates the form, using the required states and validation
expression set for each item (see Validation and Highlight Mode). If validation fails, the user is
alerted and the save is terminated. The form automatically enters highlight mode, during which
all invalid fields are marked with red labels.
If the form is valid, the onSaveValid event is generated, and any registered user script function
is invoked. Here, you can include code that validates the form as a whole (for example, ensuring
that the start date is before the end date):
IWEventRegistry.addFormHandler("onSaveValid", validateForm);
...
function validateForm() {
// Determine if the form is valid.
...
if (formValid) {
return true;
} else {
alert("Form is invalid ...");
return false;
}
30
Events
Note that the onSaveValid event handler is not passed any arguments. As with the onSave event,
the save terminates if the handler returns false.
If the save proceeds, FormsPublisher next checks to see if it knows the name of the DCR, or if it
needs the user to specify one using the workarea browser. Specifically:
If the user enters the save process by clicking the Save As button, the workarea browser
always displays.
If the DCR currently has no name, either because it is a new DCR or because the user script
reset the current name by calling IWDCRInfo.setDCRName(null), the workarea browser
displays.
If the workarea browser displays and the user clicks Cancel, the save is terminated. If the user
selects a name, FormsPublisher then triggers the onSaveNameSpecified event, and calls any
registered handler. This provides you with a means to validate the users file name selection:
IWEventRegistry.addFormHandler("onSaveNameSpecified", nameChosen);
...
function nameChosen(path) {
// Determine if the path is valid.
...
if (nameOK) {
return true;
} else {
alert("The filename chosen is invalid ...");
return false;
}
}
The onSaveNameSpecified event handler is passed the vpath the user selected. The event
handler can examine this path and decide if it is acceptable, and return true to continue the
save. If the onSaveNameSpecified handler returns false, the save is terminated.
NOTE
The event handler can also change the name of the DCR by calling IWDCRInfo.setDCRName(),
but because this function is asynchronous, it cannot use the other methods in IWDCRInfo to
check the properties of the file (see DCR Information - IWDCRInfo).
At this point, the system has all the information necessary to save the form, and the data has
passed validation by FormsPublisher and by any custom user script function. When the save
completes, one final event, onSaveDone, is triggered:
IWEventRegistry.addFormHandler("onSaveDone", saveDone);
...
function saveDone(success) {
31
if (! success) {
alert("The save did not succeed ...");
}
}
The onSaveDone handler is passed a boolean argument indicating whether the save was
successful. The user script can alert the user as needed. Because it is the last step of the save
process, the onSaveDone handler does not have to return a value.
FormAPI also provides the IWDatacapture.save() method, which allows the you to save the
form without any user interaction. This method does not generate the onSave, onSaveValid, or
onSaveNameSpecified events. It also does not validate the form. It enters the save process near
the end, checking only if the DCR name has been specified. If not (because this is a new DCR or
because setDCRName(null) was called), IWDatacapture.save() does nothing. Otherwise, the
form is saved, and the onSaveDone event is triggered.
FormsPublisher provides a <readonly> item type that is distinct from the dynamic read-only
state introduced by FormAPI. The <readonly> type is no longer necessary and is not supported
by FormAPI (see <readonly> vs setReadonly()).
Use the setVisible() and the setReadOnly() methods of the IWItem object to change the state
of an item. Use the isVisible() and isReadOnly() methods to query the state of an item.
An invisible item (made so by calling setVisible(false)) is completely absent on the form.
The user will not see the field, its contents, or its label. In addition, the fields entry in the
navigation tree is removed.
32
A read-only item is rendered exactly like a normal item, but the user is unable to change its
value (text or selections):
Figure 2
Normal Items
Read-only Items
NOTE
FormsPublisher has no mechanism for recalling the visibility or read-only states of an item
when a DCR is reopened. That information exists only in the running user script and is not
written to the DCR. Unless the user script explicitly changes the state of an item on load, it is
visible and editable. For the same reason, view mode (which does not enable FormAPI or load
user scripts) always displays the contents of all the items in the form, regardless of the visibility
state that was set in edit mode.
33
More typically, you may want to make some fields invisible in response to other selections.
Consider an address entry form that is designed to accept both domestic and international
addresses. If the country field selection is set to USA, fields for state and ZIP code should appear.
For any other country, they should not be visible.
If the country field has the address /address/country, FormAPI can register an event handler,
countryChange(), on it for the onItemChange event. This function adjusts the visibility of the
state and ZIP code fields. FormAPI calls this function directly on start up, so the initial state of
the fields is set correctly.
function init() {
IWEventRegistry.addItemHandler("/address/country",
"onItemChange", countryChange);
countryChange(IWDatacapture.getItem("/address/country"));
}
The countryChange() function is passed the item object for the country field. It checks if the
value of the currently selected country is USA and sets the visibility of the state and ZIP code
fields accordingly. Finally, it forces a redraw to effect the changes:
function countryChange(item) {
var flag = item.getOptions()[item.getValue()].value == "USA";
IWDatacapture.getItem("/address/state").setVisible(flag);
IWDatacapture.getItem("/address/zip").setVisible(flag);
}
Constructions like this allow for the creation of interactive, customized forms that significantly
improve usability.
Ensuring that the value of an unbounded field is valid (for example, that a phone number
consists of ten digits), by matching its contents against a regular expression.
A bounded control is a user interface element that restricts its input to a predefined set of
choices, like a selection list or radio button. An unbounded control is a text field or textarea
that lets the user enter free-form content.
34
Ensuring that the contents of the whole form, including relationships between separate
fields, make sense (for example, that the start date is not after the end date).
When the data a user enters fails validation, the attempt to save must be aborted and the user
must be notified which fields are invalid.
FormsPublisher provides the means to specify validation rules of the first two categories
through the required and validation-regex item attributes in the DCT. For example, you can
specify that a phone number is required and must be entered in a standard format by declaring
the item like this:
<item name="phone">
<label>Phone Number</label>
<description>Enter the phone number (###-###-####)</description>
<text required="t"
validation-regex="^\d{3}-\d{3}-\d{4}$"
maxlength="12"/>
</item>
When FormsPublisher renders this item, it appends an asterisk to its label indicating that it is
required. If the user fails to enter a valid phone number and clicks the Save button, an alert
displays and FormsPublisher enters highlight mode. In this mode, all invalid entries are marked
with red labels, both on the form and in the navigation tree. FormsPublisher remains in highlight
mode until the user corrects the error and successfully saves the form.
FormAPI enhances these capabilities by providing you with the ability to dynamically query and
change an items required state (with isRequired() and setRequired()) and validation
expression (with getRegex() and setRegex()). It also provides the means to query and change
the highlight mode of the form (with IWDatacapture methods isHighlightMode() and
setHighlightMode()).
NOTE
The description of an item, which appears in a frame directly above the form, is not dynamically
accessible by FormAPI. This is important to remember if the description includes content entry
instructions that may not be accurate if the validation expression changes. In the example above,
the description says Enter the phone number (###-###-####). If the user script calls
setRegex(/\d{10}/) to require the phone number to be entered without dashes, the description
is no longer accurate. This situation is easily avoided by not relying on the description field for
content entry instructions that are variable, and by using alerts and dialogs to inform the user
instead.
The form fails save validation and automatically enters highlight mode.
Highlight mode stays in effect (with all invalid items marked red since the last redraw) until
either the user requests a save and passes validation or the user script calls
IWDatacapture.setHighlightMode(false).
35
Normally, an item is considered valid if it meets its required state and validation expression
rules that were set by the required and validation-regex attributes in the DCT or the
setRequired() and setRegEx() in the user script. These are the rules that FormsPublisher
employs when performing save validation of the form.
Many times it is important to be able to mark an item valid or invalid without having to change
its required state or validation expression. This kind of validation checking falls into the third
category described at the beginning of the sectionensuring that the field value makes sense in
the context of the entire form. FormAPI provides the setValid() method to override the other
validation rules and directly declare an item valid or invalid:
setValid(true) marks this item valid, regardless of its content or required/regex rules. The
item always passes save validation and will never be marked red in highlight mode.
setValid(false)
setValid(null)
turns off any override previously set on this item. Save validation
examines the required/regex rules on this item to determine if it is invalid.
The isValid() method returns the current validation state of the item. If the item was explicitly
marked with setValid(), that state is returned. Otherwise, the required/regex rules are
examined.
Like labels on dynamically inserted options (see Getting and Setting Item Values) and
visibility and read-only states (see Visibility and Read-Only), the user script must restore any
dynamically modified validation states or rules on load, or a reopened form will behave
differently from when it was last saved.
Examples
Here are some examples of dynamic validation:
To toggle the required state of the /a item:
item = IWDatacapture.getItem("/a");
item.setRequired(! item.isRequired());
To prevent FormsPublisher from flagging the contents of the /b item, regardless of what was
entered, register handlers for the onSave and onSaveDone events:
IWEventRegistry.addFormHandler("onSave", saveHandler);
IWEventRegistry.addFormHandler("onSaveDone", saveFinished);
The event handler overrides the validation state during the save process:
function saveHandler(item) {
IWDatacapture.getItem("/b").setValid(true);
}
function saveFinished(item) {
36
IWDatacapture.getItem("/b").setValid(null);
}
To ensure that the date in the /start field is before the date in the /end field, register a handler
on the onSaveValid event:
IWEventRegistry.addFormHandler("onSaveValid", validateForm);
It is important to return false from the validation, so that FormsPublisher aborts the save
request.
37
FormsPublisher also provides the cgi-callout mechanism to access remote resources from the
client form. The FormAPI callServer() method supersedes CGI callouts (see CGI Callouts).
The callServer() method is asynchronous. A new thread is started with the HTTP request and
completes only when it finishes executing the code returned by the server. The user script code
that made the request continues executing immediately after the call to callServer(). For this
reason, callServer() is usually the last line of code in an event handler; the logic picks up in
the hidden frame after the post is complete.
Here is an example illustrating a typical city/state/ZIP code form:
IWEventRegistry.addItemHandler("/zip", "onItemChange", fillCityState);
The fillCityState() handler is a function that queries a remote server for city and state:
function fillCityState(zipItem) {
if (zipItem.isValid()) {
var parameters = new Object();
parameters.zip = zipItem.getValue();
// Make an HTTP GET to the server.
callServer("http://myserver/getCityState", parameters, true);
}
}
38
The result from a call to the server (which will be given the request like http://myserver/
getCityState?zip=94086) returns code similar to this:
<html>
<head>
<script language="javascript">
// Get handle to the FormAPI/userscript frame.
api = parent.getScriptFrame();
// Set the city and state.
api.IWDatacapture.getItem("/city").setValue("Sunnyvale");
api.IWDatacapture.getItem("/state").setValue("CA");
</script>
</head>
<body>
</body>
</html>
One of the hazards of making a remote server request is that it may take too long to return.
Worse, it may not return at all. To guard against this problem, a user script can use the
JavaScript setTimeOut() function to handle a request that does not return within a specified
amount of time. Before it calls the server, setTimeOut() is instructed to execute an error handler
function. The code that returns from the server cancels the pending error handler call (if it is
running, the request succeeded). If the server does not return in time, the error handler is
executed.
Adjust the user script fillCityState() function to set up the time out:
...
// Error handler called in 1 minute. Save ID in global variable
// for hidden frame to cancel if it succeeds.
timeout = setTimeOut("callServerFailed", 60000);
// Make an HTTP GET to the server.
callServer("http://myserver/getCityState", parameters, true);
...
Finally, modify the JavaScript returned from the server to cancel the time out:
...
// Get handle to the FormAPI/userscript frame.
api = parent.getScriptFrame();
39
This does not handle the case where the server is not down, but simply slow. In this case, after
one minute the user is prompted that the ZIP code lookup failed, but several moments later may
suddenly see the city and state fields automatically change. To guard against this possibility,
modify the callServerFailed() function to cancel the server call:
function callServerFailed() {
alert("ZIP code lookup failed. Be sure to enter city and state.");
// Abort the request by sending a blank page to the hidden frame.
IWDatacapture.callServer("blank.html", new Object(), true);
}
This request cancels the previous request by making a new one to an empty file. This illustrates
an important point about the callServer() method: only one call can be active at a time.
Subsequent calls to callServer() will cancel any previous calls.
The location template included with FormsPublisher illustrates a complete example.
Auto-DCR Functionality
The Auto-DCR function enables unnamed DCRs to be saved with automatically generated
names. When this feature is used, the user does not need to provide a name for the DCR that is
being saved.
Auto-DCR naming:
Is applicable when saving a DCR using the Save or Finish buttons, but not when saving
with the Save As button (because this signifies intent to specify a name for the DCR file).
The Auto-DCR function uses an algorithm based on timestamps that returns unique file names
in the form iwDCRnumber_timestamp. This function may be replaced by a user-written function
that is used to automatically get the names of the saved DCR files. See Name Factory IWNameFactory on page 77 for more information.
40
NOTE
All DCR file names generated by Auto-DCR naming are relative to the data directory of the
specified category and type.
Because there is no FormAPI in view mode, all items, whether hidden or previously invisible,
are visible in view mode.
<readonly> vs setReadonly()
Before FormAPI was available, the only way to show uneditable content was to use the
<readonly> item instance. Data in a <readonly> item had to be text because <readonly> items
do not allow selections or options, and it was rendered as a simple text string in the form.
41
Because <readonly> items can be fully emulated by calling setReadOnly(true) on a text item
at startup, they are no longer required. FormAPI does not support <readonly> items. It is
anticipated that their use will be deprecated in future releases.
CGI Callouts
Before FormAPI was available, the only way to dynamically change the form was to use a CGI
callout, defined in the DCT using the <callout> element. An item with a CGI callout is
rendered with a button beside it. Clicking the button opens a new window that the template
designer can use to present the user with a dialog. The content of the new window is specified in
the url attribute of the <callout> element. This new window then updates the data capture
form.
NOTE
Before FormAPI was available, the url attribute of the <callout> subelement was required. It
is now optional.
With FormAPI, much of the need for the CGI callout is eliminated.The template designer can
achieve the same functionality more easily and with much greater flexibility in a user script. A
user script can open a new window by calling the browsers open() command, dynamically
specifying any URL it needs. This new window can access the user script code and FormAPI
methods of its parent window by calling opener().
There, are, however, two reasons why the <callout> element is still important to FormAPI:
1. You may already have callouts that you need to reuse with templates that have user scripts.
2. The <callout> element renders a button beside a form element. This is the only way to get
a simple button on the form that does not directly change the value of the data (unlike a
check box or radio button).
FormAPI supports callouts by:
42
Providing the onCallout event. This event is triggered for an item whenever the user
presses the callout button beside that item.
Making the url attribute of the <callout> element optional. Because the onCallout handler
can process the click, there may be no need for an actual callout.
If the onCallout event is registered and a url attribute is specified to the <callout> element in
the DCT, then the event handler is called first. If it returns true, the callout specified in the url is
called by opening a new window. If the event handler returns false, the callout window is not
opened.
In this way, FormAPI fully supports callouts, allowing them to be executed or not as determined
by the user script at runtime.
Note again that a <callout> element in the DCT is the only way to get a simple button on the
form. To have the button appear rendered by itself (and not beside any particular input element)
set the callout on a hidden item. For example, the DCT may look like this:
<item name="myButton">
<hidden>
<callout label="My Button"/>
</hidden>
</item>
If the buttons do not need to be on the same window as the template, user script code can also
write HTML to a new browser window to create a custom dialog with buttons, links, and
images.
43
44
Chapter 3
FormAPI Reference
This chapter provides details about the various FormAPI objects. Before using these objects,
you should be aware of the following information.
There are eight different objects exposed in this API. These objects are:
API
Item
Event Registry
DCR Information
Name Factory
Page Generation
Presentation Template
(page 46)
(page 47)
(page 55)
(page 67)
(page 73)
(page 77)
(page 78)
(page 80)
Five of these objects, API, Datacapture, Event Registry, DCR Information and Name Factory,
are singletonsusers access their methods from a single instance of the object bearing the name
of the class. Methods of the item object IWItem are accessed from a particular instance of the
item.
NOTES
45
string IWAPI.getTSTVersion ()
Returns the version of FormsPublisher.
Arguments:
None.
Returns:
A string representing the version of FormsPublisher.
string IWAPI.getVersion ()
Returns the version of the API.
Arguments:
None.
Returns:
A string representing the version of the API.
46
IWDatacapture.SAVEAS_BUTTON
IWDatacapture.SAVECLOSE_BUTTON
IWDatacapture.PREVIEW_BUTTON
IWDatacapture.GENERATE_BUTTON
Arguments:
url
Boolean indicating whether the data should be sent using an HTTP GET (true) or an
HTTP POST (false).
Returns:
Nothing.
47
IWDatacapture.close (confirmClose)
Closes the current window. Does not trigger the onClose event.
Arguments:
confirmClose
Boolean indicating if close() should behave like clicking the Close button, and prompt
the user to save or regenerate (if necessary) before closing.
Returns:
Nothing.
IWDatacapture.displayMessage (message)
Displays the given message in a frame at the bottom of the screen.
Arguments:
message
A string message. If null or omitted, the information frame displays the default
information.
Returns:
Nothing.
48
number IWDatacapture.getCurrentPageNumber ()
Returns the page number of the current page.
Arguments:
None.
Returns:
A number representing the page number of the current page. Page numbers start at 1.
string IWDatacapture.getDCRPath ()
Returns the vpath of the data content record. If no vpath was set, the empty string ("") is
returned.
Arguments:
None.
Returns:
The vpath of the data content record.
string IWDatacapture.getDCTPath ()
Returns the vpath to the data capture template.
Arguments:
None.
Returns:
The vpath to the datacapture template.
string IWDatacapture.getFormType ()
Returns the form type as determined by the data_category/data_type directory structure in
the templatedata directory.
Arguments:
None.
Returns:
49
string IWDatacapture.getGroups ()
Returns the group(s) that the currently logged-in user is a member of.
Arguments:
None.
Returns:
An array of the names of the current users groups.
If a data capture template uses tabs (through the <tab> element in datacapture.cfg) you
must include the tabs name in the item address/xpath. See Addressing and Form Tabs on
page 18 for more information.
Returns:
An IWItem object that represents the replicant instance container and supports the
setVisible and isVisible operations. Returns null if the item cannot be found.
number IWDatacapture.getPageCount ()
Returns the number of pages in this form.
Arguments:
None.
Returns:
A number representing the number of pages in this form.
50
string IWDatacapture.getRole ()
This method is deprecated. Use IWDatacapture.getRoles () instead.
string IWDatacapture.getRoles ()
Returns the role(s) that the currently logged-in user of this form has in the current workarea.
Arguments:
None.
Returns:
An array of the current users role names.
IWItem[] IWDatacapture.getRootItems ()
Returns an array of IWItem objects representing all the items at the top level of the entire form.
Custom DTD templates always return an array of exactly one element because there may be
only one top-level node. Use getChildren() for the individual item to iterate into a replicant or
container.
Arguments:
None.
Returns:
An array of IWItem objects representing the items at the top level of the entire form.
51
Returns:
The JavaScript frame object where the API and user script reside.
string IWDatacapture.getUser ()
Returns the currently logged-in user of this form.
Arguments:
None.
Returns:
A string representing the currently logged in user of this form. On a Windows server, the
returned name is in the form domain\user.
string IWDatacapture.getWorkarea ()
Returns the current workarea.
Arguments:
None.
Returns:
The current workarea.
IWDatacapture.gotoPage (pagenumber)
Redraws the form at the specified page.
Arguments:
pagenumber
A positive number representing the page to draw. Page numbers start at 1. An invalid or
missing argument does nothing.
Returns:
Nothing.
52
boolean IWDatacapture.isHighlightMode ()
Determines whether the form is in highlight mode. In highlight mode, items that are invalid as
determined by isValid() have their labels highlighted in red.
A form may be in highlight mode because either 1) it entered it automatically after the form
failed save validation, or 2) an explicit call to setHighlightMode(true) was made.
Arguments:
None.
Returns:
True if the form is in highlight mode, false if not.
boolean IWDatacapture.isModified ()
Determines whether the DCR has been modified.
Arguments:
None.
Returns:
True
if the DCR has been modified (that is, should be saved), false if not.
IWDatacapture.save ()
Saves the current DCR if there is a name to save it to. Does not trigger onSave, onSaveValid, or
onSaveNameSpecified events. Does invoke onSaveDone event.
If no name is specified, either because it is a new DCR or because setDCRName(null) was
called, save() does nothing.
Arguments:
None.
Returns:
Nothing.
53
IWDatacapture.setHighlightMode (highlightMode)
Sets the current highlight mode. In highlight mode, items that are invalid (as determined by
isValid()) have their labels highlighted in red.
Highlight mode is set automatically if the form fails save validation.
Arguments:
highlightMode
Boolean indicating whether the form should be redrawn in highlight mode (true) or not
(false).
Returns:
Nothing.
IWDatacapture.setIsModified ()
Saves a DCR even if the form has not been modified. This feature is useful if the form contains
acceptable defaults and the DCR name is automatically determined by FormAPI. In this
situation, the user clicks Finish or Next without making any changes to the form.
Arguments:
None.
Returns:
Nothing.
54
IWItem.addOption (option)
Adds an entry to the list of options for this item. This method applies only to <select>,
<checkbox>, and <radio> items.
Arguments:
option
The JavaScript Option object to add to this item. An invalid or missing argument does
nothing.
Returns:
Nothing.
55
The whole-number index of the instance to delete. The index is not zero-based. It is
ignored if index is passed as 0 or is greater than the number of current instances.
Returns:
False
IWItem[] IWItem.getChildren ()
Returns an array of children items. Applies only to <container> and <replicant> types.
Arguments:
None.
Returns:
An array of IWItem objects representing the children of this item or null if it does not have
children.
56
string IWItem.getDescription ()
Returns the string representing the description of this item.
Arguments:
None.
Returns:
The string representing the description of this item.
string IWItem.getLabel ()
Returns the string representing the label for this item.
Arguments:
None.
Returns:
The the string representing the label for this item.
string IWItem.getName ()
Returns the XPath-like address of this item.
Arguments:
None.
Returns:
The XPath-like address of this item.
Option[] IWItem.getOptions ()
Returns the options for this item. This method applies only to <select>, <checkbox>, and
<radio> items.
Arguments:
None.
Returns:
57
An array of JavaScript Option objects representing the list of options in this select,
checkbox, or radio item, in order. Returns null if this item has no options.
RegExp IWItem.getRegex ()
Returns the validation regular expression associated with this item.
Arguments:
None.
Returns:
A JavaScript RegExp object representing the validation expression for this item, or null if
there is none.
string IWItem.getType ()
Returns the type of this item.
Arguments:
None.
Returns:
A string representing this items type. Possible values are:
textarea
text
radio
checkbox
select
hidden
browser
andreplicant
orreplicant
andcontainer
orcontainer
andreplicantcontainer
orreplicantcontainer
The string unknown is returned for unsupported item types (such as the <readonly> item
type).
58
Number of selected index (zero-based) for single <select> and <radio> items.
boolean IWItem.isCollapsed ()
Returns whether the replicant, container, or replicant container is collapsed.
Arguments:
None.
Returns:
True
boolean IWItem.isMultiSelect ()
Returns whether this item supports options with multiple selections.
Arguments:
None.
Returns:
True
59
boolean IWItem.isReadOnly ()
Returns the value of the read-only flag for this item. This method is not related to the
<readonly> item type, which FormAPI does not support.
Arguments:
None.
Returns:
True
boolean IWItem.isRequired ()
Returns whether this item is a required item.
Arguments:
None.
Returns:
True
boolean IWItem.isValid ()
Returns whether the value in this item is valid.
Arguments:
None.
Returns:
if this item is valid, false if not. If setValid() has been called with true or false,
that value is returned. If setValid() has not been called or was called with null, the system
determines validity by checking the requirement status and regular expression validation
rule for this item.
True
boolean IWItem.isVisible ()
Returns the visibility state of this item.
Arguments:
None.
60
Returns:
True if this item has a true visibility state, false if it is invisible. Note that an item can have
a true visibility state and still not be seen on the screen. For example, it may be on a
different page or scrolled out of view.
boolean IWItem.isVisualFormat ()
Returns whether or not this item is a <textarea> with a VisualFormat control.
Arguments:
None.
Returns:
True
The whole-number index of the instance to be moved. The index is not zero-based. If
index is passed as less than 1 or greater than the number of current instances, it is
interpreted as 1 or the last index, respectively.
to_index
A whole number of your choice for the index of the instance. The index is not
zero-based. If index is passed as less than 1, it is interpreted as 1. If the index is greater
than the number of current instances, the item at from_index is moved to the last
position.
Returns:
False
IWItem.removeOption (index)
Removes an option from the list of options for this item. This method applies only to <select>,
<checkbox>, and <radio> items.
Arguments:
61
index
The zero-based index of the option to remove. An invalid or missing argument does
nothing.
Returns:
Nothing.
IWItem.setCollapsed (boolean)
Makes a replicant, container, or replicant container collapsed or expanded.
Arguments:
None.
Returns:
Nothing.
IWItem.setDescription (text)
Sets the description displayed in ContentCenter for this item.
Arguments:
text
IWItem.setFocus ()
Sets the focus to this item. If this item is not on the current page, the form is first redrawn at the
correct page. setFocus() has no effect if this item is currently read-only.
Arguments:
None.
Returns:
Nothing.
62
IWItem.setLabel (text)
Sets the label displayed in ContentCenter for this item.
Arguments:
text
IWItem.setOptions (options)
Sets the option list for this item. This method applies only to <select>, <checkbox>, and
<radio> items.
Arguments:
options
An array of JavaScript Option objects to set as the new list of options for this item. An
invalid or missing argument does nothing.
Returns:
Nothing.
63
IWItem.setRegex (regex)
Sets the regular expression for validation of this item. This method is only valid for <text>,
<textarea>, <hidden>, and <browser> items.
Arguments:
regex
IWItem.setRequired (required)
Sets whether this item should be required (empty value fails validation). Required items are
marked with an asterisk (*) in their label.
Arguments:
required
IWItem.setValid (value)
Specifies whether the value in this item is valid. A true argument overrides results of standard
validity tests.
Arguments:
value
true:
Mark this item as valid. The isValid() method always returns true.
false:
null: Do not mark this item. The isValid() method determines validity by
checking the required status and validation regular expression.
Mark this item as invalid. The isValid() method always returns false.
Returns:
64
Nothing.
65
IWItem.setValue (value)
Sets the value of this item.
This method does not apply to <replicant> or <container> items.
Arguments:
value
For single <select> and <radio> items, value is the number of the zero-based index
of the option to select.
For multiple <select> and <checkbox> items, value is an array of numbers of the
zero-based indices of the options to select.
IWItem.setVisible (visible)
Sets the visibility state of an item.
Arguments:
visible
True
Returns:
Nothing.
string IWItem.toString ()
Displays debugging information, including type and name properties.
Arguments:
None.
Returns:
A descriptive string showing the type and name properties.
66
Event
Description
onCallout
onClose
onCollapseOrExpand
handle_collapse
(isCollapsed)
{...}
OnGenerate
handle_generate(dcrPath)
{...}
IWEventRegistry.addFormHa
ndler("OnGenerate",
handle_generate);
67
Table 2
Event
Description
onItemChange
OnPreview
handle_preview() {...}
IWEventRegistry.addFormHa
ndler("OnPreview",
handle_preview);
OnReplicantAdded
handle_replicant_added
(item) {...}
Where item is the IWItem
OnReplicantBeforeMove
allow_replicant_add(item,
index) {...}
IWEventRegistry.addItemHa
ndler ("/contact/phone",
"OnReplicantBeforeAdd",
allow_replicant_add);
68
Table 2
Event
Description
OnReplicantDelete
handle_replicant_delete
(item) {...}
IWEventRegistry.addItemHa
ndler("/contact/phone",
"OnReplicantDelete",
handle_replicant_delete);
handle_replicant_moved
(item, old_index) {...}
Where item is the IWItem
OnReplicantMoved
onSave
onSaveNameSpecified
onSaveValid
handle_saveValid()
69
Table 2
70
Event
Description
onSaveDone
A string representing the name of the event this handler will intercept (see preceding
table).
func
A string representing the name of the event this handler will intercept (see preceding
table).
func
71
Nothing.
IWEventRegistry.removeFormHandler (eventname)
Removes the event handler for the given event from the form.
Arguments:
eventname
72
IWDCRInfo.UNAVAILABLE
IWDCRInfo.PENDING
IWDCRInfo.ERROR
NOTE
All of the query methods in this object rely on the most recent setDCRName() to have populated
the information field when the DCR was most recently named. setDCRName() is implicitly
called when:
The form is first loaded.
The form is saved either by the user or by calling IWDatacapture.save().
string IWDCRInfo.getDCRName ()
Returns the name of the DCR.
Arguments:
None.
Returns:
The current name of the DCR, or null if the DCR is currently unnamed.
number IWDCRInfo.getFileSize ()
Returns the size of the DCR file (in bytes).
Arguments:
None.
Returns:
73
A number representing the size of the file in bytes. Returns null if the DCR is currently
unnamed.
Date IWDCRInfo.getModificationDate ()
Obtains the last modification date of the DCR file.
Arguments:
None
Returns:
A JavaScript Date object which contains the last modified date of the DCR file. Returns
null if the DCR is currently unnamed.
string IWDCRInfo.getOwner ()
Determines the owner of the file. In the TeamSite file system, the owner of the file is the last
user to have modified the file.
Arguments:
None.
Returns:
A string representing the owner of the file. Returns null if the DCR is currently unnamed.
number IWDCRInfo.getStatus ()
Determines whether meta information is available. Should be checked before calling the other
methods in this object.
Arguments:
None
Returns:
IWDCRInfo.AVAILABLE:
obtain it.
74
IWDCRInfo.PENDING: the request to the server to retrieve information for the current
DCR name has not completed yet.
IWDCRInfo.ERROR:
the request to the server to retrieve information for the current DCR
name did not return in time (1 minute) and has been cancelled.
NOTE
When checking for the status of IWDCRInfo object, do not use a tight infinite loop. Instead, use
the setTimeOut() method in Java to poll for the status change. For example:
function checkInfoStatus()
{
if (IWDCRInfo.getStatus == IWDCRInfo.PENDING)
{
//Check again in 2 sec
setTimeout("checkInfoStatus()",2000);
}
else
{
//Do what you were about to do with the status.
}
}
boolean IWDCRInfo.isModifiedInWA ()
Determines whether the DCR file is marked as modified in the TeamSite workarea (different
from staging).
Arguments:
None.
Returns:
True if the DCR file is marked as modified in the TeamSite workarea, false if it is not.
Returns null if the DCR is currently unnamed.
75
Do not specify a path with references to the parent directory (..). Doing so can lead to
unpredictable results.
While the request is in progress, its status may be tracked with the getStatus() method, as
described above.
Because it involves an HTTP POST, this is an asynchronous call that spawns a new thread. To
synchronize execution with the completion of this method, specify a callback function. The
callback executes when the request completes or times out (1 minute).
If a request is still pending and setDCRName() is called again, the original request is cancelled
and the new one is initiated.
If path is null, the DCR name is explicitly unset. The callback is not executed if the path is
The system prompts the user for a DCR name when the Save button is clicked.
null.
is implicitly called when the form is opened, and when the form is saved.
Therefore, calls to IWDatacapture.save() followed immediately by a call to setDCRName() are
not safe because when the save completes, the new name will be lost.
setDCRName()
Arguments:
path
A function to execute when the implicit request to refresh the DCR information returns
or times out.
Returns:
Nothing.
76
The file paths that the function generator returns must be relative to the data directory of the
relevant data capture form. A default function is provided that uses a simple algorithm based on
timestamps to ensure unique file names.
The function will automatically return the name of the file that should be used to save the
current DCR.
function IWNameFactory.getAutoDCRPathGenerator ()
Gets the user-set automatic DCR path generator function.
Returns:
The user-set automatic DCR path generator function. If a user has not previously set the
automatic DCR path generator function, then null will be returned.
77
IWPresentationTemplate IWPageGeneration.getPresentationTemplate()
Gets the presentation template to be used for previewing and generating.
Arguments:
None.
Returns:
An IWPresentationTemplate object of the current presentation template. Null is returned if
there is no current presentation template.
IWPresentationTemplate IWPageGeneration.getValidPresentationTemplates
()
Gets an array of valid presentation templates for this data content record.
Arguments:
None.
Returns:
An array of presentation templates.
string IWPageGeneration.getOutputFile ()
Gets the output file name to be used for previewing and generating.
Arguments:
None.
Returns:
The string path representing the templatedata relative path of the file. The empty string
("") is returned if the output file has not been set.
78
The string path representing the templatedata relative path of the file.
create_directories
Creates the directory paths for filename if they do not exist (optional).
Returns:
Nothing.
79
IWPageGeneration.getValidPresentationTemplates ()
IWPageGeneration.getPresentationTemplate ()
string IWPresentationTemplate.getExtension ()
Gets the extension for the presentation template.
Arguments:
None.
Returns:
The extension attribute of the presentation template as defined in the templating.cfg file.
string IWPresentationTemplate.getName ()
Gets the name of the presentation template.
Arguments:
None.
Returns:
The name of the presentation template as defined in the templating.cfg file.
string IWPresentationTemplate.getPath ()
Gets the workarea-relative path to the presentation template. To get the full vpath to the
presentation template, concatenate this result to IWDatacapture.getWorkarea ().
Arguments:
None.
Returns:
The workarea-relative path of the presentation template.
80
Appendix A
How an event handler for a replicant field is invoked for the replicant instances.
How to loop through all the fields on the form including the replicant instances.
datacapture.cfg.
contact.dtd.
contact.js.
data.
presentation.
The Script
The following is contact.js, the user script for this example.
81
// File contact.js
// Userscript for the 'userscript/contact' Templating FormAPI example.
//
//----------------------------------------------------------------------// The init() function is executed at the end of this script.
// It register registers the event handlers.
function init() {
// Register a function to popup a confirmation window on save
// *after* the form has passed basic validation.
IWEventRegistry.addFormHandler("onSaveValid", displayContact);
// Register a function to perform Phone number validation.
// that an event handler registered on a replicant will be
// triggered for the individual replicant instances.
Note
IWEventRegistry.addItemHandler("/contact/phone", "onItemChange",
checkPhoneNumbers);
}
// This function is called when the user tries to save the form.
// displays the contact details and request confirmation.
It
function displayContact() {
// Build the confirmation message from the current form values.
var message = "Do you want to save following contact details:\n";
message += "\nName: " +
name").getValue();
IWDatacapture.getItem("/contact/
82
return confirm(message);
}
// checkPhoneNumbers() is called every time the user changes a phone
// number field.
function checkPhoneNumbers(phoneItem) {
// Is this phone number valid?
if (! phoneItem.isValid()) {
// No. Use a regular expression to extract this item's
// ordinality from its name.
var i
= phoneItem.getName().match(/\d+/)[0];
The DCT
The following is datacapture.cfg, the data capture template that invokes contact.js.
<?xml version="1.0" encoding="UTF-8"?>
<data-capture-requirements
dtd-system-identifier="http://localhost/iw/contact.dtd"
dcr-validation="none" name="">
<ruleset name="dct">
<root-container combination="and" location="contact" name="contact">
<item max="1" min="1" name="name" pathid="name">
<label>Name</label>
<description>Enter the contact name</description>
<text required="t" validation-regex="^\D+$" maxlength="50" />
</item>
<item max="6" min="1" name="phone" pathid="phone">
83
<label>Phone</label>
<description>Enter the phone number (###-###-####)</description>
<text required="t" validation-regex="^\d{3}-\d{3}-\d{4}$"
maxlength="12"/>
</item>
<description>Enter contact details</description>
</root-container>
<script language="javascript" location="template-type"
src="contact.js"/>
</ruleset>
</data-capture-requirements>
84
datacapture.cfg.
location.dtd.
getLocations.cgi.
data.
presentation.
Installation
The Location user script requires the following installation steps:
1. Copy the getLocations.cgi to iw-home/httpd/iw-bin.
2. Edit the first line of getLocations.ipl to point to the path for the iwperl interpreter and
replace '__IW_HOME__' with the location of iw-home.
3. Change the dtd-system-identifier attribute in the datacapture.cfg file to point to the
correct location of location.dtd.
85
The Script
The following is the user script for this example.
<script>
<![CDATA[
function init() {
// Register a function to validate data before for gets submitted.
IWEventRegistry.addItemHandler("/location/region", "onItemChange",
fetchLocations);
// Set the City list for the selected region(if any)
var regionItem = IWDatacapture.getItem("/location/region");
var cityItem = IWDatacapture.getItem("/location/city");
var myOptions = cityItem.getOptions();
fetchLocations(regionItem,
cityItem.getOptions()[parseInt(cityItem.getValue())].value);
}
function fetchLocations(item, defaultCity) {
var params = new Object();
var myOptions = item.getOptions();
params.region = myOptions[parseInt(item.getValue())].value;
params.defaultCity = defaultCity;
//alert the user that an external call is being made.
IWDatacapture.displayMessage("Retrieving locations in " +
myOptions[parseInt(item.getValue())].text + "...");
top.hiddenFrameRunning = true;
var server = window.location.hostname;
IWDatacapture.callServer("http://"+server+"/iw-bin/getLocations.cgi",
params);
}
function populateLocations(locations) {
//Clear the message display...
IWDatacapture.displayMessage();
var locationsItem = IWDatacapture.getItem("/location/city");
locationsItem.setOptions(locations);
}
//Now do the initialization...
IWEventRegistry.addFormHandler("onFormInit", init);
]]>
86
</script>
The DCT
The following is datacapture.cfg, the data capture template that invokes the above script.
NOTE
87
This element
-->
Use of the IWDCRInfo object to set or query the DCR associated with this form.
Protection that changes made by another user (in case of shared workareas) are not
inadvertently overwritten.
datacapture.cfg.
organization.dtd.
organization.js.
data.
presentation.
The Script
The following is organization.js the user script for this example.
// The init() function is executed at the end of this script.
// It register registers the event handlers.
function init() {
88
IWDCRInfo.setDCRName(department, null);
}
}
//
//
//
//
This function is called when user saves the form. It sets the DCR
name, if not set already. It also ensures that someone else's
changes are not being inadvertently overwritten (which can happen
in shared workareas).
function saveHandler() {
var result;
89
if (IWDCRInfo.isModifiedInWA() &&
IWDCRInfo.getOwner() != IWDatacapture.getUser()) {
// If it's been changed by another user, prompt to confirm.
var message = "DCR was modified by another user.";
message += "\nFile details are:\n";
message += "\nSize: " + IWDCRInfo.getFileSize();
message += "\nOwner: " + IWDCRInfo.getOwner();
message += "\nLast modified: " +
IWDCRInfo.getModificationDate();
message += "\n\nDo you still want to save?" ;
result = confirm(message);
} else {
// Otherwise, we're in great shape.
result = true;
}
break;
case IWDCRInfo.PENDING:
// The query for information on this DCR hasn't returned yet.
// Let the user decide if they want to proceed with the save.
90
break;
case IWDCRInfo.UNAVAILABLE:
default:
// There's no information available on the current DCR name,
// most likely because it doesn't exist. Proceed with the save.
result = true;
}
return result;
}
// Call the initialization routine on load.
IWEventRegistry.addFormHandler("onFormInit", init);
The DCT
The following is datacapture.cfg, the data capture template that invokes organization.js.
<?xml version="1.0" encoding="UTF-8"?>
<data-capture-requirements
dtd-system-identifier="http://localhost/iw/organization.dtd"
dcr-validation="none" name="">
<ruleset name="dct">
<root-container combination="and" location="organization"
name="organization">
<item max="1" min="1" name="department" pathid="department">
<label>Department</label>
<select>
<option selected="t" value="ENG" label="Engineering"/>
<option value="MKT" label="Marketing"/>
<option value="SLS" label="Sales"/>
<option value="IS" label="Information Systems"/>
<option value="FAC" label="Facilities"/>
</select>
</item>
<item max="1" min="1" name="description" pathid="description">
<label>Description</label>
<textarea />
</item>
91
<description>Organization/Department.</description>
</root-container>
<script language="javascript" location="template-type"
src="organization.js"/>
</ruleset>
</data-capture-requirements>
An event handler to make certain fields visible and required based on the value of other
field(s).
An event handler to change the validation regex of a field depending on the value of another
field.
92
datacapture.cfg.
position.dtd.
position.js.
data.
presentation.
The Script
The following is position.js the script for this example.
// File position.js
// Userscript for the 'userscript/position' Templating FormAPI example.
//
//----------------------------------------------------------------------------// The init() function is executed at the end of this script.
// It register registers event handlers, and calls them to
// set the initial state of the form.
function init() {
// Register callback handlers for changes in the values of
// position type and title.
IWEventRegistry.addItemHandler("/position/type",
"onItemChange", typeHandler);
IWEventRegistry.addItemHandler("/position/title",
"onItemChange", titleHandler);
// Register a function to validate the form before save.
// This is a form-level validation that will occur *after*
// individual fields pass regex/required validation.
IWEventRegistry.addFormHandler("onSaveValid", validateForm);
// To set the initial state of the form, call the event
// handlers now.
typeHandler(IWDatacapture.getItem("/position/type"));
titleHandler(IWDatacapture.getItem("/position/title"));
}
// The typeHandler() function changes the form based on the currently
// value of the 'type' field. It is passed a reference to the 'type'
// form item.
function typeHandler(typeItem) {
93
Turn off highlight mode. If the user entered invalid data, and
then attempted to save, highlight mode is automatically turned
on. If at this point they decide to change the position type,
we shut off highlight mode so fields that were previously
hidden don't appear to be the cause of the validation failure.
IWDatacapture.setHighlightMode(false);
}
// setItemStatus() is a helper function used by typeHandler(). It
// changes the visibility, required state, and the value of the
// specified item.
function setItemStatus(item, status) {
item.setVisible(status);
item.setRequired(status);
// If we're hiding this item and making it optional, clear
// its value. This prevents irrelevant data from being saved
// in the DCR, and avoids validation errors in hidden fields.
if (! status) {
item.setValue("");
}
}
// The titleHandler() function changes the input requirements for the
// 'yearly' field based on the current value of the 'title' field. It
// is passed a reference to the 'title' item.
function titleHandler(titleItem) {
// We only bother changing the input requirements of the 'yearly'
// field if it's visible (which is the case if this is a full-time
// position).
94
95
96
The DCT
The following is datacapture.cfg, the data capture template that invokes position.js.
<?xml version="1.0" encoding="UTF-8"?>
<data-capture-requirements dtd-system-identifier=
"http://localhost/iw/position.dtd" dcr-validation="none" name="">
<ruleset name="dct">
<root-container combination="and" location="position" name="position">
<item max="1" min="1" name="title" pathid="title">
<label>Job title</label>
<select>
<option selected="t" value="ENG" label="Software Engineer"/>
<option value="MGR" label="Engineering Manager"/>
<option value="DIR" label="Engineering Director"/>
<option value="CIO" label="Chief Information Officer"/>
<option value="CEO" label="Chief Executive Officer"/>
<option value="COO" label="Chief Operating Officer"/>
<option value="CTO" label="Chief Technology Officer"/>
</select>
</item>
<item max="1" min="1" name="type" pathid="type">
<label>Fulltime/Temporary</label>
<radio>
<option selected="t" value="F" label="Full time"/>
<option value="T" label="Temporary"/>
</radio>
</item>
<item max="1" min="1" name="rate" pathid="rate">
<label>Hourly Rate</label>
<description>Hourly rate (required for temporary positions only)
</description>
<text maxlength="4" validation-regex="^\d+$" />
97
</item>
<item max="1" min="1" name="hours" pathid="hours">
<label>Hours Per Week</label>
<description>Number of hours per week(required for temporary
positions only)</description>
<text maxlength="2" validation-regex="^[0-9]+$"></text>
</item>
<item max="1" min="1" name="yearly" pathid="yearly">
<label>Yearly Salary</label>
<description>Job Listing(required for permanent positions only)
</description>
<text maxlength="10" validation-regex="^\d{3,5}$" />
</item>
<description>Job Listing</description>
</root-container>
<script language="javascript" location="template-type"
src="position.js"/>
</ruleset>
</data-capture-requirements>
98
Index
A
addFormHandler 71
addInstance 55
addItemHandler 71
addOption 23, 55
addressing 18
syntax 19
using item 20
API version 46
B
buttons
defining 47
C
callServer 38, 47
CGI callouts 42
close 48
contact user script 81
D
data capture template
path 49
DCR
file size 73
generate names 77
information 73
meta information 74
modification date 74
modified 53, 75
name 73, 76
obtaining information 73
owner 74
path 49
path generator 77
saving 53, 77
saving unchanged 54
DCT
path 49
debugging 66
deleteInstance 56
displayMessage 48
DTD
changes to 15
dynamic options 24
E
eableImagePreview 48
errata 11
error handling
server time-out 39
event handlers 26, 67
onSave 30
registering 18
removing 72
specifying 71
EventRegistry 67
events 68
available to user scripts 67
onCallout 43, 67
onClose 67
onCollapseOrExpand 67
OnGenerate 67
onItemChange 27, 68
OnPreview 68
OnReplicantAdded 68
OnReplicantBeforeMove 68
OnReplicantDelete 69
OnReplicantMoved 69
onSave 29, 69
99
Index
onSaveDone 31, 70
onSaveNameSpecified 31, 69
onSaveValid 30, 69
when triggered 26
F
Form Settings
modify 78
form type
obtaining 49
FormAPI
changes to FormsPublisher 41
forms
highlighted 54
items in 51
items on 55
methods for 47
redrawing 52
validation 30
FormsPublisher version 46
frame
obtaining 51
G
getAutoDCRPathGenerator 77
getChildByName 56
getChildren 56
getCurrentPageNumber 49
getDCRName 73
getDCRPath 49
getDCTPath 49
getDescription 57
getExtension 80
getFileSize 73
getFormType 49
getGroups 50
getItem 50, 58
getLabel 57
getModificationDate 74
getName 57, 80
getOptions 23, 57
getOutputFile 78
100
getOwner 74
getPageCount 50
getPath 80
getPresentationTemplate 78
getRegex 58
getRoles 51
getRootItems 51
getScriptFrame 51
getStatus 74
getTSTVersion 46
getUser 52
getValidPresentationTemplates 78
getValue 23, 59
getVersion 46
getWorkarea 52
gotoPage 52
groups 50
H
handler 26
I
instances
moving 61
invalid items
highlighting 53
isCollapsed 59
isHighlightMode 53
isModified 53
isModifiedInWA 75
isMultiSelect 59
isReadOnly 32, 60
isRequired 60
isValid 36, 60
isVisible 32, 60
items
children 56
collapsed 59
multiple selections 59
name 57
options 55, 57
read-only 63
removing options 61
required 60, 64
setting description 62
setting focus 62
setting label 63
setting value of 66
type of 58
valid 60
value of 59
visible 60, 66
VisualFormat 61
IWAPI 46
IWDatacapture 20, 24, 47
IWDCRInfo 73
constants 73
IWEventRegistry 20, 27, 67
IWItem 32, 55
IWNameFactory 77
IWPageGeneration 78
IWPresentationTemplate 80
L
labels
highlighted in red 53, 54
lists of options 55
location user script 85
M
message
displaying 48
methods
addFormHandler 71
addInstance 55
addItemHandler 71
addOption 23, 55
callServer 38, 47
close 48
deleteInstance 56
displayMessage 48
enableImagePreview 48
getAutoDCRPathGenerator 77
getChildByName 56
getChildren 56
getCurrentPageNumber 49
getDCRName 73
getDCRPath 49
getDCTPath 49
getDescription 57
getExtension 80
getFileSize 73
getFormType 49
getGroups 50
getItem 50, 58
getLabel 57
getModificationDate 74
getName 57, 80
getOptions 23, 57
getOutputFile 78
getOwner 74
getPageCount 50
getPath 80
getPresentationTemplate 78
getRegex 58
getRoles 51
getRootItems 51
getScriptFrame 51
getStatus 74
getTSTVersion 46
getUser 52
getValidPresentationTemplates 78
getValue 23, 59
getVersion 46
getWorkarea 52
gotoPage 52
iscCollapsed 59
isHighlightMode 53
isModified 53
isModifiedInWA 75
isMultiSelect 59
isReadOnly 32, 60
isRequired 60
isValid 36, 60
isVisible 32, 60
isVisualFormat 61
moveInstance 61
removeFormHandler 72
101
Index
removeItemHandler 72
removeOption 23, 61
save 53
setAutoDCRPathGenerator 77
setCollapsed 62
setDCRName 76
setDescription 62
setFocus 62
setHighlightMode 54
setIsModified 54
setLabel 63
setOptions 23
setOutputFile 79
setPresentationTemplate 79
setReadOnly 32, 63
setRegex 64
setRequired 64
setValid 36
setValue 23, 66
setVisible 32, 66
toString 66
moveInstance 61
O
objects
IWAPI 46
IWDatacapture 20, 24, 47
IWDCRInfo 73
IWEventRegistry 20, 27
IWItem 32, 55
IWNameFactory 77
IWPageGeneration 78
IWPresentationTemplate 80
returning 50
onCallout 43, 67
onClose 67
onCollapseOrExpand 67
OnGenerate 67
onItemChange 27, 68
OnPreview 68
OnReplicantAdded 68
OnReplicantBeforeAdd 68
OnReplicantBeforeMove 68
102
OnReplicantDelete 69
OnReplicantMoved 69
onSave 29, 69
onSaveDone 31, 70
onSaveNameSpecified 69
onSavenameSpecified 31
onSaveValid 30, 69
options
IWEventRegistry 67
removing 61
organization user script 88
output file 79
outputfile 78
P
page number
obtaining 49
pages
number of 50
paths
absolute 19
position user script 92
presentation template 78, 79, 80
extension 80
name 80
path 80
previewing 78, 79
R
read-only 32
example 33
read-only flag 60
read-only items 63
redraw
specified page 52
regular expressions 58, 64
removeFormHandler 72
removeItemHandler 72
removeOption 23, 61
replicants
adding 55
collapsing 62
deleting 56
expanding 62
required items 60, 64
roles 51
location 85
location of 16
naming guidelines 17
organization 88
position 92
S
save 53
script tag 15
server
time-out 39
setAutoDCRPathGenerator 77
setCollapsed 62
setDCRName 76
setDescription 62
setFocus 62
setHighlightMode 54
setIsModified 54
setLabel 63
setOptions 23
setOutputFile 79
setPresentationTemplate 79
setReadOnly 32, 63
setRegex 64
setRequired 64
setValid 36
setValue 23, 66
setVisible 32, 66
V
validation 58, 60, 64
dynamic 36
form 30
save 36
version
API 46
FormsPublisher 46
visibility 32, 60, 66
VisualFormat control 61
W
window
close 48
T
thumbnails
displaying 48
toString 66
U
URL 47
user 50, 51
groups 50
obtaining name 52
obtaining workarea 52
roles 51
user script
contact 81
103
Index
104