The first thing that we need to do when creating a custom control is to decide how we want it to be used, i.e., what is the mark-up that authors should use to make use of our new features?
One custom control that we're going to create will have an image that is a map, centred on a specified longitude and latitude. We'll therefore use the 'value' of the control to provide that location. However, we'd like to also control the size of the map, since sometimes we'd like to have thumbnails, and sometimes much larger images. The obvious way to do this would be to make use of the CSS properties width and height, and allow them to govern the size of the map. Finally, since we don't want the user to be able to update the value of the location we'll use xf:output as the control that we'll be modifying.
A typical usage of this 'interface' might be:
<xf:output value="'51.523004;-0.106859'" appearance="geolocation" style="width: 200px; height: 100px;" />
which gives us a map centred on the formsPlayer office in London.
We'll also create a number of clock custom controls, to illustrate the many different ways we could approach this. For our LED clock, we might want the background colour of our control to be used to determine the background of the clock, and we might want the text colour to set the colour of the digits. As before, since we don't want the user to be able to update the time we would use an xf:output, so our 'interface' might look like this:
<xf:output value="'14:52:00'" appearance="fp:LED" style="color: red; background-color: black;" />
Custom controls are extensions to more basic controls so we'll always need some control to enhance. But it's a good idea to choose a base control that reflects in some way the functionality of the control you are trying to build. For example, if you are creating a video player widget, base it on xf:output rather than xf:range or xf:upload. Similarly, even if you are creating a complex control that is more like a dialog-box which is made up of lots of other controls--if ultimately all this control does is to allow a user to choose a colour from a palette then it can be based on xf:select1.
By building on a control that already has some of the behaviour you require, you automatically get a good fall-back mechanism if your forms are used on processors that don't support custom controls, and perhaps more interestingly, you also create the possibility of users replacing your custom control with one of their own choosing, from a personalised stylesheet.
Since we are going to want some of our controls to be maps and others to be clocks, we need to provide a 'hook' that identifies which controls need to be extended.
Extensions are added based on rules defined using XPath, so we can add pretty much any hook we want. A common convention is to use the class attribute from XHTML or the appearance attribute from XForms. However, it is also possible to use a more dynamic approach, and add extensions based on the underlying data type in the XForms model. In both of our examples above we used the XForms appearance attribute:
<xf:output value="'52;4'" appearance="geolocation" /> <xf:output value="'14:52:00'" appearance="fp:LED" />
But we could also have used the HTML class attribute. In the following example, if a user browsed to our form using an XForms processor that did not have a clock custom control, they would still see the time in green:
<style type="text/css"> .clock { color: green; } </style> <xf:output value="'14:52:00'" class="clock" />
In the next section we'll look at how the custom controls we create can be made available to authors.