XPages comes with a set of client side
JavaScript libraries that are pre-installed within the Domino Server. The
functionality they provide can be used to enhance XPage designs and, furthermore,
can be extended using your own custom JavaScript functions. This article
discusses these libraries and provides detailed examples of how they can
be incorporated into your Domino Applications.
\data\domino\js\Dojo-1.1.1\ibm\xsp\widget\layout\.
These directories contain multiple versions of the JavaScript files with
varying levels of compression. For example, the ibm\xsp\widget\layout\
directory includes XSPClientDojo.js.gz, XSPClientDojo.js and XSPClientDojo.js.uncompressed.js.
The gzipped file (.gz) is the smallest and is used if the client's web
browser supports this file type. Otherwise, the JavaScript source file
(.js), which is a compressed version of the source code, is used. The uncompressed
JavaScript file (uncompressed.js) is a more readable version of the source
code and is available for debugging purposes. In order to debug one of
the client side libraries, the .gz and .js files should be removed from
the directory and the uncompressed.js file should be renamed to .js. This
allows you to see more clearly the implementation details and thus determine
the cause of any unexpected behavior in an XPage.
Dojo
Dojo is an open source JavaScript library
which enables developers to program dynamic behavior into web applications.
An extensive widget library, event handling system and tools to aid internationalization
are some of the features that it provides which can be used to build interactive
user interfaces with ease. Within XPages, this toolkit is used in the implementation
of some of the controls, including the Rich Text Editor and Date Time Picker,
and to provide functionality such as AJAX type ahead and partial update.
The inclusion of this library as part of the XPages engine makes it possible
to directly incorporate Dojo widgets into XPage designs.
In order to utilize a Dojo widget in an XPage, the appropriate Dojo module
should first be loaded. On an XPage, this is achieved by adding a Dojo
module resource and specifying the name of the desired widget. This adds
the required resources to the XPage for the chosen widget and thus enables
us to use it in our design. Enabling the Dojo parsing infrastructure may
also be required to ensure that a Dojo widget is rendered correctly when
the XPage loads. The XPages dojoParseOnLoad property achieves this. Also
Dojo provides a number of themes that are used to give a consistent look
and feel to its widget library. They can be incorporated into an XPage
by using the dojoTheme XPage property. The XPages theme files define the
Dojo themes to use when this property is set. Any XPage control that uses
the Dojo toolkit in its implementation forces the dojoTheme property to
true to ensure that the required theme resources are available. Dojo module
resources as well as the dojoParseOnLoad and dojoTheme properties can also
be set for a custom control. Any XPage that contains this custom control,
will also include these Dojo properties and resources.
The following examples demonstrate how to apply these settings to
incorporate Dojo widgets into an XPage and furthermore how to link a Dojo
widget to a Domino data source.
Example 1: Adding a Dojo widget to an XPage
This example outlines the method used to incorporate a Dojo Progress Bar
widget into an XPage. It is based on the Dojo
Progress Bar sample available
on the Dojo Toolkit website.
- Open the XPage that you wish to add the Dojo Progress
Bar to in the XSP editor.
- Select the XPage
and on the All Properties tab, expand the basics category.
- Select resources and click on the Add
icon. Select xp:dojoModule from the list and enter dijit.ProgressBar
as the value for the name field of this resource. These steps are outlined
in Figure 1.

Figure 1: Adding a Dojo module to an XPage
- Remain in the All Properties tab, within the basics
category. Set both the dojoParseOnload and the dojoTheme
property values to true.
- Change to the source
tab on the XSP editor and copy in the following code wherever you want
the progress bar to be placed:
- Save the XPage and view the outcome in a web browser. A Dojo
Progress Bar, as shown in Figure 2, now appears on the XPage.

Figure
2: A Dojo progress bar widget
XPage Source Sample 1 attached to this article expands on this example
to demonstrate how this progress bar can be activated on the onClick event
of a button.
Example 2: Linking a Dojo widget to a Domino data source
In addition to creating Dojo widgets using HTML as in the above example,
it is also possible to create them programmatically. This makes it possible
to link Dojo widgets to a Domino data source, thus making it possible to
use Dojo controls to enter, view and edit information in a Domino Application.
For example, a Dojo Number Spinner widget can be used on an XPage to retrieve
user input for a numeric field. The Number Spinner widget allows the user
to select a numeric value by either typing in a number or by adjusting
a default value using up and down arrow buttons. In order to input the
data from this Dojo control into a Domino data source, the Number Spinner
needs to be attached to an XPage control which is bound to a numeric field
in a Domino Document. This following steps demonstrate how this is achieved:
- Open the XPage that allows users to enter information
into a new Domino Document. Make sure that one of the available fields
is setup to accept a numeric value. In this example, the XPage uses an
Edit Box control to accept a value for the number of sales for a
business in one day.
- As in the previous example,
set the dojoTheme property value to true and add a Dojo module
resource to the XPage with dijit.form.NumberSpinner as the name
value.
- Use an Output Script control to attach
the Dojo Number Spinner widget to the Edit Box. (To add an Output
Script control, select Other.... on the controls palette, expand
the Other Controls category and select Output Script. Click
OK.).
- Select the control in the XSP editor
and on the properties tab, expand data and compute the value
field. As shown in Figure 3, select Custom in the language drop
down menu and enter the following in the script editor:
new dijit.form.NumberSpinner({name:"#{id:numSales}",
value:50, smallDelta:1, constraints:{min:0,places:0}},
XSP.getElementById("#{id:numSales}"));

Figure 3:
Computing the value of the Output Script control
This code invokes the constructor of the Dojo
Number Spinner widget. The
first parameter is an object, the properties of which map to the properties
of the Dojo widget. The second parameter is the HTML DOM object node associated
with the Edit Box control used to enter the number of sales. “numSales”
is the name of this Edit Box and #{id:numSales} is used to
get its client ID value. Saving the XPage and viewing it in a web browser,
the Dojo Number Spinner widget should now appear instead of the Edit
Box (see Figure 4). The value selected on this Dojo widget will be
the number saved into the Domino Document when the data is submitted.

Figure 4: A Dojo Number Spinner widget on an XPage
In this example, a default value of 50
is specified for the Number Spinner widget. Therefore if a user uses the
same XPage to open the Domino Document just created, the value displayed
for the number of sales field will be 50. The example can be further enhanced
so that if a user views a stored Domino Document, the value displayed in
this field is the previously stored value. To achieve this, the value for
the Number Spinner needs to be dynamically calculated. Replacing the value
of the Output Script control above with the following code accomplishes
this:
var myvalue
= "#{javascript:
var value;
if(getComponent("numSales").getValue() != null){
value = getComponent("numSales").getValue().intValue();
}else{
value = 50;
}
return value.toFixed(0);}";
new dijit.form.NumberSpinner({name:"#{id:numSales}",
value:myvalue,
smallDelta:1, constraints:{min:0,places:0}},
XSP.getElementById("#{id:numSales}"));
This retrieves the value stored in the document and displays it in the
Number Spinner widget when the document is opened in read or edit mode.
If a new document is being created, a default value of 50 is used. Save
the XPage once again and view in a web browser. Now if you enter a value
into a Domino Document and then view that document in read or edit mode
using the same XPage, the number spinner control will display the value
stored in the document rather than the default value, as shown in figure
5.

Figure 5: Creating and editing a document that uses a Number Spinner widget.
XSPClientDojo
The XSPClientDojo library defines a global XSP object which exposes some
JavaScript functions to the XPages runtime. As its name suggests, XSPClientDojo
utilizes the Dojo JavaScript library, however other implementations may
be developed in the future (for example, when supporting handheld devices).
The global XSP object provides a number of different functions which can
be applied in client side scripts. In Example 2 above, the following function
call is used:
XSP.getElementById("#{id:numSales}")
This uses the getElementById function of the XSP object to obtain access
to the object node of an XPage control with a specified client ID. Note
this is different to document.getElementById() and works consistently for
all browsers. In the function call above, the client ID corresponds to
an Edit Box control and its object is obtained so that a Dojo widget can
be applied to it. However, a more typical use for this function would be
to access various properties of a DOM object node that corresponds to an
XPage control. The following example provides access to the value, type,
and disabled properties of a HTML input field i.e. an XPages Edit Box control.
var name =
XSP.getElementById("#{id:name}");
var nameValue = name.value;
var nameType = name.type;
var nameDisabled = name.disabled;
The XSP object also provides a number of converters which manipulate the
values entered by users into a desired data type. A range of validators
are also available which can then be applied to verify that the input is
valid. For example, if a field on an XPage should accept an integer input,
a converter can be applied to that field and an error message can be displayed
if the wrong value type is entered. The following call of the XSP attachValidator
function adds an integer converter to an XPage field which represents the
user's age.
XSP.attachValidator("#{id:age}",null,new
XSP.IntConverter("Incorrect age value entered. Please enter
an integer"));
The first parameter passed to this function is the clientID of the age
field on the XPage. “age” is the name of the Edit Box control used for
the age field. The next parameter specifies whether this is a required
field. In this case, the user is not obliged to enter their age. The final
parameter specifies the converter which should be applied to the entered
value. In this case, the XSP IntConvertor is applied which converts the
user input to an integer. If the value cannot be converted to an integer,
the specified error message is displayed.
This converter can be attached to the age input field when the XPage has
loaded in the web browser. To achieve this, we encapsulate the function
call within the Output Script control as before and use the XSP
addOnLoad function. Note the onLoad attribute of the HTML body tag should
never be used to accomplish this. The value for the Output Script
control should be the following:
XSP.addOnLoad(
function addAgeValidator() {
XSP.attachValidator("#{id:age}",null,new XSP.IntConverter("Incorrect
age value entered. Please enter an integer"));
}
);
When the XPage is displayed through a
web browser, only integer values will be accepted for the age field as
shown in Figure 6.

Figure 6. The Age field will only accept integer values
This example can be further expanded
to make age a required field on the XPage and to limit the age value entered
to a specified range (see Figure 7). The attachValidator function call
in this case would be:
XSP.attachValidator("#{id:age}",
new XSP.RequiredValidator("You must enter an age"),
new XSP.IntConverter("Incorrect value entered, please enter
an integer"),
new XSP.NumberRangeValidator(18, 65, "Incorrect age value
entered. Age must be between 18 and 65"));
Figure 7: Age is now a required field and its value must be between 18
and 65
It is also possible to contribute custom
convertors and validators and apply them using the XSP object. The following
example shows how to define a new validator and apply it to an XPage control.
In this example, the user is asked to enter and submit their employee number
through an XPage. A new validator is defined to verify that the employee
number entered is valid.
Firstly, define the employeeIDValidator function as outlined in the following
steps and shown in Figure 8.
- In the Application Navigator,
expand the Code resources.
- Double Click on Script Libraries
and select New JavaScript Library. Type a name for the new JavaScript
library e.g. myValidators.
- Copy the following function into the
script editor and save the file.
var
EmployeeIDValidator = function EmployeeIDValidator(message){
this.validate = function xeidv_v(clientId,value){
if(typeof value =="string"){
var len = value.length;
if(len != 8 || !XSP.startsWith(value,"P")){
XSP.validationError(clientId,message);
return
false;
}
}
return true;
}
}

Figure 8. Defining a new Validator function
This is a very basic validation rule which requires the employee ID entered
to start with “P” and to be 8 characters long. To utilize this function,
the new JavaScript library needs to be added as a resource to the XPage
which contains the employee ID field and then attach the new validator
to the employee ID field.
- Open the XPage which contains the employee
ID field. Select the XPage and on the Resources tab, click Add
Script Library.
- Select the Script library which contains
the employeeIDValidator. Its functions can now be used in controls on the
current XPage.
- Add an Output Script control
to the XPage as before and enter the following code as its value
XSP.addOnLoad(
function addEmployeeIDValidator() {
XSP.attachValidator("#{id:employeeID}",new XSP.RequiredValidator("You
must enter an employee number"), null,
new XSP.EmployeeIDValidator(“Error, incorrect employee
number entered"));
}
);
This specifies that the employee ID field
is required and that it will not be submitted unless it passes the validation
criteria specified in the EmployeeIDValidator function. Note a convertor
is not applied in this case, since the employee ID is treated as a string.
Figure 9 shows the outcome of this code sample.

Figure 9: The Employee Number field is required and it must satisfy the
validation criteria from the EmployeeIDValidator function
The XSP object also provides a useful
logging facility. Using this, messages can be output to a logging window
as an XPage is navigated. This can be used to track user actions or to
output status messages and is a valuable resource for testing and debugging.
The following function call results in the logging window shown in Figure
10.
XSP.log("Submit button
clicked with values: Company Name: "
+XSP.getElementById("#{id:topic}").value+" and #Sales:
"+XSP.getElementById("#{id:numSales}").value);

Figure 10: Logging window facility provided by the XSP object
Summary
Two client-side
JavaScript libraries are included in XPages: Dojo and XSPClientDojo. This
article discusses these libraries highlighting the main functionality they
provide and giving examples of how they can be utilized within your Domino
Applications. The Dojo examples provided demonstrate how easily Dojo widgets
can be incorporated into XPages and how they can be linked to Domino data
sources. The latter part of this article focuses on the utilities that
the global XSP object defined in the XSPClientDojo JavaScript library provide.
For more information on the Dojo toolkit, see The
Dojo Toolkit website.
For details on further functions available in the XSPClientDojo library,
see the XSPClientDojo.js.uncompressed.js file included in your Domino install
directory.
Sample Code
XPage Source 1: Adding a Dojo progress
bar widget to an XPage
"1.0"
encoding="UTF-8"?>
"http://www.ibm.com/xsp/core"
dojoTheme="true"
dojoParseOnLoad="true"
"dijit.ProgressBar"
"dijit.ProgressBar"
style=
"width:300px"
jsId=
"jsProgress"
id=
"downloadProgress"
"Start"
id="button1"
"onclick"
submit="false"
"text/javascript"
  Split up bar
into 7% segments
numParts = Math.floor(100/7);
jsProgress.update({
maximum: numParts, progress:0 });
for (var i=0; i<=numParts;
i++){
This plays update({progress:0}) at 1nn milliseconds,
update({progress:1}) at 2nn milliseconds, etc.
setTimeout("jsProgress.update({ progress: " + i
+ " })",
(i+1)*100 + Math.floor(Math.random()*100));
}
]]>
xp:view>