The Client Framework provides a binding language called Tag Definition Language (TDL), which is XML compliant and has its foundations in object oriented programming languages. It provides a set of elements and attributes required for the creation of new widgets or tags. TDL serves as a means to bind classes to document-level markup elements. Our implementation of XHTML and all of our Backbase Tag Library (BTL) widgets are constructed with the TDL.
Overview
The Widget Development Guide explains how to use the TDL to build or extend rich widgets. In this tutorial we illustrate a particular aspect: composition.
Like most modern software development languages, TDL is a language that supports object orientation, which has two major aspects: inheritance and composition. Inheritance is the concept of extending the behavior of an existing widget. Composition is a feature of TDL that allows you to build complex widgets from simple ones.
The example we use is a road crossing with a set of traffic lights, where the traffic lights can be operated by pressing a switch button repeatedly. The traffic lights will then change color in the appropriate order. We start out with a single lamp, then we use two lamps to form a pedestrian light, and three lamps to form a traffic light. Finally, we put them all on a page with a switch to control them. You can try the complete example at the end of this page.
We realize that most of you are not developing applications that require traffic lights. Our motivation for choosing this example is that it clearly shows the building block facilities of TDL. In the Widget Development Guide, there are other examples that may be more directly applicable to your situation.
A Simple Lamp
In the Widget Development Guide, we define a simple lamp with a specific color that can be switched on and off, and explain how it is coded. We are using this definition here and for the purpose of this tutorial, you do not need to know what this code looks like. This is an important concept to keep in mind: to be able to use a widget, or to extend it, you need to know its interface, not its inner structure. If you wish to see the source code, it is provided with the Widget Development Guide in the Client Framework package.
It is good practice to keep the source code of widgets in separate library files, which makes it easier to reuse widgets in various settings. TDL has a tag that allows you to include the definition of a widget from a file: the d:uses tag. For our example, we can include the definition of the lamp widget like this:
<d:namespace xmlns:yp="http://www.example.com/yourNamespace" name="http://www.example.com/yourNamespace">
<d:uses element="lamp" src="data/tdl_lamp_definition.xml" />
</d:namespace>
</d:tdl>
Snippet 1: Namespace declaration
The live demo below shows the single lamp in action:
Live Demo 1: Single Lamp Example
In order to use the lamp in a pedestrian or traffic light as a building block, we need to know its interface. This is simply illustrated by showing the code that is used in the example above:
<!-- Define the lamp and a button to switch it on and off -->
<yp:lamp id="lamp1" color="yellow" state="on"/>
<br/>
<button>
<e:handler event="DOMActivate" type="text/javascript">
var lamp = bb.document.getElementById('lamp1');
lamp.switchLamp();
</e:handler>
Lamp Switch
</button>
</div>
Snippet 2: Lamp definition
The usage of the lamp in the example shows:
- The
colorattribute that defines the color of the lamp. - The
stateattribute that defines whether the lamp is initially on or off. - The
switchLamp()method that is used to switch the lamp on or off.
This is all we need to know about the interface of a simple lamp.
We now continue with showing you how two lamps can be used to form a traffic light.
Composition of the Traffic Light
Of course, we could compose a pedestrian light on our application page as follows:
<yp:lamp color="red" state="on" id="red1" />
<yp:lamp color="green" id="green1" />
</div>
Snippet 3: Colors definition
This would be fairly easy if there was just one pedestrian light in our application, and if its definition was as simple as above. However, if you want to use many lights, or if you would like to build further structures out of them, then it could be both time and cost effective to spend development effort on building complex widgets out of simple ones. Consider also that we can encapsulate the behavior of a pedestrian light in the widget itself, making our code more modular and easier to maintain.
The Visual Part of the Pedestrian Light
First, we will look at the visual part of defining a pedestrian light. As you can see, the constructor part looks the same as the code snippet above. It is embedded in a c:create command to actually build the pedestrian light.
Be aware that we cannot use a d:template tag to compose the pedestrian light widget, because it can contain only XHTML. Therefore, the constructor is used to compose the widget. Instead of putting the c:create command in the constructor, we could compose the widget in the handler of the DOMNodeInsertedIntoDocument event with the same result.
The c:create command that is used to build a set of DOM elements must have a destination to attach the nodes to. Therefore, a d:template with a d:content tag is added to the widget, which can receive the destination="." nodes that are created.
<d:namespace xmlns:yp="http://www.example.com/yourNamespace" name="http://www.example.com/yourNamespace">
<d:uses element="lamp" src="data/tdl_lamp_definition.xml" />
<d:element name="pedestrianLight">
<d:constructor type="application/xml">
<c:create destination=".">
<yp:lamp color="red" state="on" />
<yp:lamp color="green" />
</c:create>
</d:constructor>
<d:template type="application/xhtml+xml">
<div xmlns="http://www.w3.org/1999/xhtml">
<d:content />
</div>
</d:template>
</d:element>
</d:namespace>
</d:tdl>
Snippet 4: Visual Part of the Pedestrian Light
If we want to use a pedestrian light now, we can just put this on the page: <yp:pedestrianLight />
To make the pedestrian light more useful, we must add behavior to the pedestrian light.
Behavior for the Pedestrian Light
We need to write a piece of code that switches the lamps on and off in the right order, and we need to put this code into methods. As a result, we will have a pedestrian light that you can use without exposing the interfaces of the two lamps that compose it. Again, this will make your code more modular and easier to maintain.
Briefly, the behavior of the pedestrian light is as follows: When the red light is on, the green light should be off and vice versa. We do this by defining a toggle() method:
<d:body type="text/javascript">
// switch the state for both lamps
var oRed = this.getProperty('redLamp');
oRed.switchLamp();
var oGreen = this.getProperty('greenLamp');
oGreen.switchLamp();
</d:body>
</d:method>
Snippet 5: Toggle method definition
We only use the switchLamp() method of the two lamps, and we need to know nothing else about the inner workings of the simple lamps. The initial colors and state were defined in the visual part, as shown above. There are two assumptions though: we must have a reference to each lamp, by way of a property, and we must assign the proper starting state to each lamp. The properties look like this:
<d:property name="greenLamp" type="object" />
Snippet 6: Properties definition
We also add two lines to the constructor to initialize the properties with a reference to the right lamp:
<e:set property="greenLamp" select="yp:lamp[@color = 'green']" />
Snippet 7: Colors definition
As in the single lamp example above, you can see the complete code in the Widget Development Guide. It is also explained there, and it shows you how to use JavaScript instead of XEL in the constructor of the pedestrian light widget. We used XEL here, because it demonstrates more clearly the building blocks used to compose the pedestrian light. In practice, you may prefer to use JavaScript if you are building a heavily used widget, because it will avoid the overhead of interpreting XEL.
The live demo below shows the pedestrian light in action:
Live Demo 2: Pedestrian Light Example
Because of all the work we did above, the code to use the pedestrian light is now very simple: you just put the yp:pedestrianLight on the page, along with a button that invokes the toggle() method on the light when clicked.
<yp:pedestrianLight id="ped1" />
<br />
<button>
<e:handler event="DOMActivate" type="text/javascript">
var oLight = bb.document.getElementById('ped1');
oLight.toggle();
</e:handler>
Click me!
</button>
</div>
Snippet 8: Pedestrian Light definition
Road Crossing with Traffic Lights
The same principles that we used to construct a pedestrian light from two simple lamps can be used to construct a traffic light with three lamps. Once we define these, we can put a set of lamps on a road with a crossing for pedestrians.
The lights for pedestrians are composed of two lamps, red and green. The lights for traffic are composed of three lamps: red, yellow and green. There is a button in the lower left corner that, when clicked, causes the lights to change color in the right order.
Live Demo 3: Road Crossing Example
The code to build these lamps is explained in the Widget Development Guide. There are some additional features that have to be taken care of, which are explained in this document:
- We need to position the lights.
- The lights have various orientations.
- The traffic lights with three lamps have more complex behavior.
We encapsulated this extra behavior in various methods that we added to the definition of both pedestrian and traffic lights. Once this is done, the code required to use our lamps is again simple:
<div id="road1-container">road1
<yp:roadLightH id="road1"/>
</div>
<div id="road2-container">road2
<yp:roadLightHR id="road2"/>
</div>
<div id="ped1-container">ped1
<yp:pedestrianLight id="ped1"/>
</div>
<div id="ped2-container">ped2
<yp:pedestrianLightR id="ped2"/>
</div>
<div id="button-container">
<button>
<e:handler event="DOMActivate" type="text/javascript">
var road1 = bb.document.getElementById('road1');
var road2 = bb.document.getElementById('road2');
var ped1 = bb.document.getElementById('ped1');
var ped2 = bb.document.getElementById('ped2');
road1.toggle();
road2.toggle();
if (road2.getProperty('currentLampOn') != 1) {
ped1.toggle();
ped2.toggle();
}
</e:handler>
Switch
</button>
</div>
</div>
Snippet 9: Road Crossing definition
Conclusion
There are now four different widgets that are placed on the road. These widgets are built as simple extensions from a more generic traffic light class, showing the inheritance features of TDL. To find out more about this, refer to the resources below.
Download
You can download a zipped version of the examples provided on this page to try them out for yourself.
Note: Make sure to extract the content of this zip file to the root folder of your web server or application server (for example, htdocs), and then run it from your local development environment.
Additional Resources
For more information on TDL, refer to the following documentation:
