JavaScript
- Define a class for your component
- Call methods of your class on XForms events
- Read-only parameters
- Sending events from JavaScript
Define a class for your component
The XBL component shipped with Orbeon Forms are stored in their own directory under /xbl/orbeon
. For instance, all the files for the currency component are under /xbl/orbeon/currency
. To include a JavaScript file, use the <xbl:script>
element directly inside the <xbl:xbl>
:
<xbl:xbl>
<xbl:script src="/xbl/orbeon/currency/currency.js"/>
<xbl:binding id="fr-currency" element="fr|currency">
....
</xbl:binding>
</xbl:xbl>
In the JavaScript file corresponding to your component, declare a class as follows:
YAHOO.namespace("xbl.fr");
YAHOO.xbl.fr.Currency = function() {};
ORBEON.xforms.XBL.declareClass(YAHOO.xbl.fr.Currency, "xbl-fr-currency");
YAHOO.xbl.fr.Currency.prototype = {
attribute1: null,
attribute2: null,
init: function() {
...
},
valueChanged: function() {
...
},
...
};
YAHOO.namespace("xbl.fr")
defines a namespace for your class. All the XBL components components that ship with Orbeon Forms are in thexbl.fr
namespace. If you are defining a component for your company or project named Acme, you could use the namespacexbl.acme
.ORBEON.xforms.XBL.declareClass()
defines your class as an XBL class:- It takes 2 parameters: your class, and the CSS class found on the most HTML element that contains the markup for your components. This element is generated by Orbeon Forms, and the class name is derived from the id of your
<xbl:binding>;
for instance, if the id isfr-currency
, the class name isxbl-fr-currency
. - It adds a static method to your class called
instance()
. It is a factory method, which you will use to get or create an object corresponding to the "current" component (more on this later). It define a staticcontainer
attribute. In your JavaScript code, you can refer to this.container
to retrieve the most outer HTML element corresponding to your component. For instance, if you know you have an input with the class xbl-fr-currency-xforms-input inside your component, you get the HTML element corresponding to that input with:
- It takes 2 parameters: your class, and the CSS class found on the most HTML element that contains the markup for your components. This element is generated by Orbeon Forms, and the class name is derived from the id of your
YAHOO.util.Dom.getElementsByClassName(
"xbl-fr-currency-xforms-input",
null,
this.container
)[0];
Call methods of your class on XForms events
You can call a JavaScript method defined in your JavaScript class when an XForms event occurs. For instance, to call the init()
method when on xforms-enabled
, write:
<xxf:script ev:event="xforms-enabled">YAHOO.xbl.fr.Currency.instance(this).init();</xxf:script>
The instance()
method acts as an object factory for your component: it returns an instance of your class corresponding to the "current" component. It creates an instance of your class as necessary, and keeps track of existing objects, maintaing a 1-to-1 mapping between instances of the XBL component in the form and instance of your JavaScript class.
Read-only parameters
So your JavaScript can access the current value of parameters and be notified when their value changes, include the oxf:/oxf/xslt/utils/xbl.xsl
XSL file, and call xxbl:parameter()
function for each parameter, as in:
<xbl:xbl>
<xbl:script src="/xbl/orbeon/currency/currency.js"/>
<xbl:binding id="fr-currency" element="fr|currency">
<xbl:template xxbl:transform="oxf:unsafe-xslt">
<xsl:transform version="2.0">
<xsl:import href="oxf:/oxf/xslt/utils/xbl.xsl"/>
<xsl:template match="/*">
...
<xsl:copy-of select="xxbl:parameter(., 'prefix')"/>
<xsl:copy-of select="xxbl:parameter(., 'digits-after-decimal')"/>
...
</xsl:template>
</xsl:transform>
</xbl:template>
</xbl:binding>
</xbl:xbl>
The arguments of xxbl:parameter()
are:
- The element corresponding to your component, e.g. the
<fr:currency>
element written by the user of your component. If your template matches on/*
, this will be the current node. - The name of the parameter.
Then in JavaScript, you can access the current value of the property with:
var prefixElement =
YAHOO.util.Dom.getElementsByClassName(
"xbl-fr-currency-prefix",
null,
this.container
)[0];
var prefix =
ORBEON.xforms.Document.getValue(prefixElement.id);
Whenever the value of a parameter changes, a method of your JavaScript class is called. The name of this method is parameterFooChanged
if "foo" is the name of your property. Parameters names are in lowercase and use dash as a word separator, while the method names use camel case. E.g. if your parameter name is digits-after-decimal
, you will defined a method parameterDigitsAfterDecimalChanged
.
Sending events from JavaScript
You can dispatch custom events to bindings from JavaScript using the ORBEON.xforms.Document.dispatchEvent()
function. If you are calling it with custom events, make sure you are allowing the custom event names on the binding first:
<xbl:binding xxf:external-events="acme-super-event acme-famous-event">
<xbl:handlers>
<xbl:handler event="acme-super-event" phase="target">
...
</xbl:handler>
</xbl:handlers
...
</xbl:binding>