One of the greatest challenges faced by RIA developers is that of browser compatibility. Since OpenLaszlo is based on the Java™ language paradigm of write-once-run-everywhere, it ensures that applications based on OpenLaszlo run uniformly in various browsers across multiple operating systems.
The following figure shows the server side and the client-side architecture of OpenLaszlo.
Figure 1. OpenLaszlo server and client subsystems
The OpenLaszlo Server is a Java servlet/JSP application. This server makes LZX application development a breeze.
The OpenLaszlo Server comprises five main subsystems:
- The Interface Compiler — The Interface Compiler consists of an LZX Tag Compiler and a Script Compiler, which convert the source files into executable (SWF) files and serve them either as bytecode to a plug-in that runs in the client's browser (such as Flash or J2ME), or as JavaScript (DHTML) executed by the browser itself.
- The Media Transcoder — The Media Transcoder converts a full range of media assets into a single format for rendering by OpenLaszlo's target client-rendering engine. This enables an OpenLaszlo application to present supported media types in a unified manner on a single canvas, without multiple helper applications or supplemental playback software. The Media Transcoder automatically renders the following media types: JPEG, GIF, PNG, MP3, TrueType, and SWF (art/animation only).
- The Data Manager — The Data Manager acts as an interface between OpenLaszlo applications and other applications across the network, such as databases and XML Web services. It consists of a data compiler that converts data into a compressed binary form and a series of data connectors that enable OpenLaszlo applications to retrieve data via XML/HTTP.
- The Cache — The Cache contains the most recently compiled version of any application. The first time an OpenLaszlo application is requested, it is compiled, and the resultant SWF file is sent to the client. A copy is also cached on the server, so subsequent requests do not have to wait for compilation.
OpenLaszlo's client-side architecture mainly consists of the Laszlo Foundation classes, which provides the runtime environment for running a OpenLaszlo applications. Whenever a client invokes an OpenLaszlo application by its URL, the required runtime libraries are also downloaded along with source. The client always maintains a connection with the server.
The OpenLaszlo client consists of following main subsystems:
- The Event System — The Event System is responsible for handling various user-based events, such as mouse clicks or data submissions. It also improves the performance of an application by performing various operations on the client side, such as sorting and validation, rather than passing those to the server.
- The Data Loader/Binder — The Data Loader receives the data dispatched from the server side and binds those to respective UI elements, such as menus, text fields, and text areas on the client side.
- The Layout and Animation System — The Layout and Animation System handles various animation-related algorithms, enabling the user to view components in a visually continuous manner. It also handles the position of various components using relative and absolute pixel positioning with minimal programming.
A typical request flow takes the following path:
- User sends a request for a resource in the form of a URL via the browser.
- The OpenLaszlo server retrieves the resource based on the URL and sends it to the Interface Compiler for compilation.
- The Interface Compiler converts the LZX application description tags and JavaScript into executable (SWF) bytecode for transmission to the OpenLaszlo client environment. This code is placed into the cache, from which it is sent to the client.
- Depending on how the application is invoked, it is transmitted as an SWF file or as an HTML file with an embedded SWF object, along with the appropriate Laszlo foundation classes.
- The browser displays the application in the case of an HTML-formatted response. The Flash player plays the application in the case of an SWF-formatted response.
- The user enters some request data on the client side and submits the data.
- The OpenLaszlo server invokes the appropriate data connector, which, in turn, fetches the XML data.
- The OpenLaszlo server sends the data back to the client.
- The Laszlo foundation classes on the client side bind the data to the appropriate UI objects. Screen elements are updated with the response data.
Figure 2 shows a typical OpenLaszlo application request cycle as described above.
Figure 2. Request cycle
Your first OpenLaszlo application
Developing an OpenLaszlo application involves:
- Writing the OpenLaszlo program (in XML and JavaScript) using a text editor.
- Saving the file as an LZX file.
- Compiling the LZX file to an SWF file or DHTML, manually or by using the OpenLaszlo server and viewing the output in a browser.
Writing an OpenLaszlo application
As mentioned, an OpenLaszlo application is an XML document. Therefore, you can use any text editor to write your code. The code in Listing 1 is a simple HelloWorld LZX application.
Listing 1. HelloWorld.lzx
<canvas height="350" width="1050" bgcolor="#FFBE7D" >
<view width="500" height="250" align="center" valign="middle" bgcolor="#FFFF66">
<text align="center" valign="middle">
<font size="25">Welcome to Hello World!</font>
</text>
</view>
</canvas>
|
Now, save the script as HelloWorld.lzx. The file must be saved somewhere within the Server/lps-4.0.x directory, which is found in the OpenLaszlo Server installation directory.
Compiling and running the script
The easiest way to compile an LZX file is by using the OpenLaszlo server. Make sure Apache Tomcat is running on your computer and direct your browser to the following URL: http://localhost:8080/lps-4.0.x/path. Here, path is the path to the LZX file relative to the Server/lps-4.0.x directory.
For example, if the script is saved as Server/lp2-4.0.x/hello/HelloWorld.lzx, the URL to compile the OpenLaszlo application would be http://localhost:8080/lps-4.0.x/hello/HelloWorld.lzx, shown in Figure 3. The servlet container will pass the HTTP request to the OpenLaszlo server. The server opens and compiles the correct LZX file, generates the output, and saves it in a temporary directory.
The OpenLaszlo server then sends the generated output to the browser. If the application is compiled as Flash, the generated SWF file and related files are cached. Subsequent requests for the same unmodified LZX file will be much faster because no recompilation needs to be performed. If the compilation fails, an error message will be displayed on the browser.
Figure 3. Sample hello world OpenLaszlo application
The bottom part of the display shows a development tool containing buttons that allow you to view your OpenLaszlo source code, deploy your application, recompile the source code, and perform other functions. The development tool can be avoided by passing appropriate request type and runtime target as parameters. For example:
http://127.0.0.1:8080/lps-4.3.0/helloWorld/HelloWorld.lzx?lzr=swf9&lzt=html |
and:
http://127.0.0.1:8080/lps-4.3.0/helloWorld/HelloWorld.lzx?lzr=dhtml&lzt=html |
Figure 4 shows an example of the helloWorld application run with parameters to suppress the toolbar.
Figure 4. Sample Hello World OpenLaszlo application
OpenLaszlo comes with a set of classes that
represent simple and rich components, making LZX programming easier and
more rapid. The BaseComponent class is a
subclass of LzView and the superclass of all
LZX components.
The canvas tag represents
the topmost container for all views and elements in an LZX application.
There is exactly one canvas for each LZX application. The LzCanvas class is
instantiated when the LZX compiler encounters the canvas tag. For example, the code in Listing 2 shows how to
use the canvas tag and some of its
attributes.
Listing 2. Canvas.lzx
<canvas width="450" bgcolor="#6699FF" height="200" title="Canvas">
<text align="center" valign="middle">
<font size="25">Openlaszlo World!</font>
</text>
</canvas>
|
The above application can be invoked using http://localhost:8080/lps-4.0.x/canvas/Canvas.lzx. Figure 5 shows the generated output.
Figure 5. Canvas
A view
represents a rectangular area that can display text and other elements.
You can create a view using the view tag or by
instantiating the LzView class. As an example,
Listing 3 displays an LZX application that uses the view tag.
Listing 3. View.lzx
<canvas width="300" bgcolor="#ddddee" height="200">
<view align="center" valign="middle" bgcolor="#6699FF" width="300" height="150"/>
</canvas>
|
Above application can be viewed using http://localhost:8080/lps-4.0.x/view/View.lzx. Figure 6 shows the output generated from the view.lzx file.
Figure 6. Using View
In a typical LZX application, you will often use multiple views, nested within each other. Listing 4 shows an LZX application with nested views.
Listing 4. NestedView.lzx
<canvas height="370">
<view width="150" height="150" bgcolor="black">
<view width="100" height="100" bgcolor="white">
<view width="50" height="50" bgcolor="gray"/>
</view>
</view>
</canvas>
|
The above application can be invoked by browsing to http://localhost:8080/lps-4.0.x/view/NestedView.lzx. Figure 7 shows the generated output.
Figure 7. Using nested views
One can also use the view tag to display or play
external resources, such as images, MP3 files, and other Flash files. The
media types supported are JPG, GIF, PNG, MP3, and SWF. Note that support
for MP3 is limited to audio files sampled at 44.1 KHz, 22 KHz, 11 KHz, 8
KHz, and 5.5 KHz. Listing 5 shows an example LZX application that uses
view to display an
image.
Listing 5. ResourceView.lzx
<canvas width="300" bgcolor="#ddddee" height="200">
<view align="center" resource="IBMLogo.jpg" valign="middle" bgcolor="#6699FF"
width="300" height="150"/>
</canvas>
|
The above application can be invoked using http://localhost:8080/lps-4.0.x/view/ResourceView.lzx. Figure 8 shows the generated output.
Figure 8. Using Resource View
A Window
object represents a resizable window. The Window class is a subclass of WindowPanel, which is a subclass of BaseWindow. BaseWindow is a direct
child of BaseComponent. The Window.lzx file in
Listing 6 is an LZX application that displays a resizable window.
Listing 6. Window.lzx
<canvas width="450" bgcolor="#6699FF" height="200" title="Canvas">
<window align="center" valign="middle" resizable="true" width="300" height="150">
<text>OpenLaszlo World!</text>
</window>
</canvas>
|
The above application can be invoked using with http://localhost:8080/lps-4.0.x/window/Window.lzx. Figure 9 shows the generated output.
Figure 9. Window
An Alert
object represents a modal dialog box to display a message. An Alert box
comes equipped with an OK button. They are not displayed by default. You
must call they Alert's open method to make it
visible. The Alert class is a subclass of the
ModalDialog class, which is derived from
WindowPanel. A Modal Dialog object
represents a movable floating view. The code in Listing 7 shows how to
use the Alert
box.
Listing 7. Alert.lzx
<canvas>
<alert name="warning">Press OK to continue.</alert>
<script>
canvas.warning.open ();
</script>
</canvas>
|
The above application can be invoked using http://localhost:8080/lps-4.0.x/alert/Alert.lzx. Figure 10 shows the generated output.
Figure 10. Alert box
Listing 8. AlertWithButtons.lzx
<canvas>
<alert name="warning" buttonl="OK" button2="No">
Click OK to Process.
<handler name="onresult">
if (this.result) {
parent.message.setText("Processing Started");
} else {
parent.message.setText ("Processing Stopped'");
}
</handler>
</alert>
<script>
canvas.warning.open ();
</script>
<text name="message"> Do you want to start processing?</text>
</canvas>
|
AlertWithButtons asks for confirmation from the user in the form of an alert box with Yes/No buttons and takes the appropriate action.
A Button object
represents a clickable button, which raises an event, so you can perform
an action upon a click. This class is a subclass of BaseButton, which in turn is a subclass of BaseComponent. The Button.lzx file in Listing 9
is an LZX application using a button. The button's text says, "Hello
World!!"
Listing 9. Button.lzx
<canvas width="450" bgcolor="#6699FF" height="200">
<button width="200" height="80" align="center" valign="middle">
Hello World!!</button>
</canvas>
|
Run the example by browsing to http://localhost:8080/lps-4.0.x/layout/Button.lzx. Figure 11 shows the generated output.
Figure 11. Canvas with button
Layout managers allows one to lay out components in a
container. The LzLayout class is a subclass of
LzNode, which is responsible for laying out
views. The LzLayout class is the base class
that provides this functionality. You will never instantiate this class
directly, but always create an instance of its subclass. Subclasses of
LzLayout are shown below.
SimpleLayout is used to place components next to each other,
horizontally or vertically. An instance is created by using the
simplelayout tag, as shown below.
Listing 10. SimpleLayout.lzx
<canvas width="450" bgcolor="#6699FF" height="200">
<simplelayout axis="x" spacing="4"/>
<view align="center" valign="middle" bgcolor="silver" width="100" height="100"/>
<view align="center" valign="middle" bgcolor="gray" width="100" height="100"/>
<view align="center" valign="middle" bgcolor="blue" width="100" height="100"/>
</canvas>
|
Invoke the sample using http://localhost:8080/lps-4.0.x/layout/SimpleLayout.lzx. Figure 12 shows the generated output.
Figure 12. Simple layout
ResizeLayout is similar to SimpleLayout, allowing you to position views horizontally or
vertically. However, with ResizeLayout you can
also resize the views being managed as shown in Listing 11.
Listing 11. ResizeLayout.lzx
<width="450" bgcolor="#6699FF" height="200">
<resizelayout axis="y" spacing="20"/>
<view valign="middle" width="100" height="100" bgcolor="silver"/>
<view valign="middle" width="100" height="100" bgcolor="gray"/>
<view valign="middle" width="100" height="100" bgcolor="blue"
options="releasetolayout"/>
</canvas>
|
The above application can be invoked using http://localhost:8080/lps-4.0.x/layout/ResizeLayout.lzx. Figure 13 shows the generated output.
Figure 13. Resize layout
SimpleBoundsLayout positions views horizontally
or vertically like SimpleLayout. However, SimpleBoundsLayout makes sure that no view
overlaps another when a one is rotated. An example is shown below in
Listing 12.
Listing 12. SimpleBoundsLayout.lzx
<canvas width="450" bgcolor="#6699FF" height="200">
<simpleboundslayout axis="x"/>
<view valign="middle" width="100" height="100" bgcolor="silver"/>
<view valign="middle" width="100" height="100" bgcolor="gray" rotation="30"/>
<view valign="middle" width="100" height="100" bgcolor="blue"/>
</canvas>
|
This application can be invoked using http://localhost:8080/lps-4.0.x/layout/SimpleBoundsLayout.lzx. Figure 14 shows the generated output.
Figure 14.
SimpleBoundsLayout
With ReverseLayout, views are laid out from the right to the left
(along the x axis) or from the bottom to the top (along the y axis). Listing
13 shows an LZX application that uses ReverseLayout.
Listing 13. ReverseLayout.lzx
<canvas width="450" bgcolor="#6699FF" height="200">
<reverselayout axis="x" end="false" spacing="20"/>
<view align="center" valign="middle" width="100" bgcolor="silver"/>
<view align="center" valign="middle" width="100" bgcolor="gray"/>
<view align="center" valign="middle" width="100" bgcolor="blue"/>
</canvas>
|
Run the example with http://localhost:8080/lps-4.0.x/layout/ReverseLayout.lzx. Figure 15 shows the generated output.
Figure 15. Reverse layout
This layout places views on top of
each other. As with SimpleLayout, you specify
the axis attribute. ContantLayout then shifts each view the number of
pixels specified in the values xoffset and
yoffset. The result is a cascade of the
views offset by these
values.
Listing 14. ConstantLayout.lzx
<canvas width="450" bgcolor="#6699FF" height="200">
<constantlayout axis="x" value="10"/>
<view valign="middle" width="300" height="150" bgcolor="silver"/>
<view valign="middle" width="200" height="80" bgcolor="gray" xoffset="-15"/>
<view valign="middle" width="40" height="40" bgcolor="blue" xoffset="-50"/>
</canvas>
|
The above application can be invoked using http://localhost:8080/lps-4.0.x/layout/ConstantLayout.lzx. Figure 16 shows the generated output.
Figure 16. Constant layout
WrappingLayout wraps the views it manages by changing lines or
columns when it runs out of space. Listing 15 shows an
example.
Listing 15. WrappingLayout.lzx
<canvas width="450" bgcolor="#6699FF" height="200">
<wrappinglayout axis="x" spacing="20"/>
<view align="center" valign="middle" bgcolor="silver" width="200" height="100"/>
<view align="center" valign="middle" bgcolor="gray" width="200" height="100"/>
<view align="center" valign="middle" bgcolor="blue" width="200" height="100"/>
</canvas>
|
Invoke the application above using http://localhost:8080/lps-4.0.x/layout/WrappingLayout.lzx. Figure 17 shows the generated output.
Figure 17. Wrapping layout
To make programs more interactive,
OpenLaszlo objects can raise events in response to a user's action, such as
buttonclick. This is done by wiring the
event to an event handler containing the code to be executed when the
object raises the event. There are several ways to wire an event to an
event handler. One is to assign the name of the event handler to
the event name in the tag declaration of the object, as shown in Listing
16. The tag shown below creates a Window object whose onx event is wired to the event handler myHandler.
Listing 16. window.lzx
<window name="win" onx="myHandler">
|
Another
approach is to write a method nested in the tag declaration of an object
and assign the event handler to the event attribute of that method.
The snippet in Listing 17 wires a button's onclick event to the event handler within its tags.
Listing 17. Window.lzx
<button>
<handler name="onclick">
// Event handler code
</handler>
</button>
|
The
example in Listing 18 shows the onclick
event emitted by a button being mapped to an event
handler.
Listing 18. EventWiring.lzx
<canvas width="450" bgcolor="#6699FF" height="200">
<button width="200" height="80" align="center" valign="middle">Hello Button
<handler name="onclick">
setAttribute("text", "Hello Button Clicked");
setAttribute ('width', 200);
</handler>
</button>
</canvas>
|
You can execute the example EventWiring.lxz by browsing to http://localhost:8080/lps-4.0.x/event/EventWiring.lzx. Figure 18 shows the generated output initially and the output after the event has been fired by clicking the button.
Figure 18. Event handling
Alternatively, event handler code could also have been embedded within the object tag, as shown in Listing 19.
Listing 19. EmbeddedEventHandling.lzx
<canvas width="450" bgcolor="#6699FF" height="200">
<button width="200" height="80" align="center" valign="middle"
onclick="setAttribute ('text', 'Hello Button Clicked');
setAttribute ('width', 200);">
Hello Button
</button>
</canvas>
|
Global event handlers can be written with JavaScript
functions that can be called from multiple objects. For example, the code
in Listing 20 defines the myHandler function
that can be called from any point in the program.
Listing 20. GlobalEventHandler.lzx
<canvas width="450" bgcolor="#6699FF" height="200">
<button width="200" height="80" align="center" valign="middle" id="button1"
onclick="globalHandler()"> Hello Button
</button>
<script>
<![CDATA[
function globalHandler () {
button1.setAttribute ("text", "Hello Button Clicked");
button1.setAttribute ('width', 200);
}
]]>
</script>
</canvas>
|
The above application can be compiled and invoked using http://localhost:8080/lps-4.0.x/event/GlobalEventHandler.lzx.
In OpenLaszlo, one can even pass an object reference to a method as shown in Listing 21.
Listing 21. PassingObjectReference.lzx
<canvas width="450" bgcolor="#6699FF" height="200">
<simplelayout axis="x"/>
<button width="200" height="80" align="center" valign="middle" id="button1"
onclick="globalHandler (this)"> Hello Button 1
</button>
<button width="200" height="80" align="center" valign="middle" id="button2"
onclick="globalHandler (this)"> Hello Button 2
</button>
<script>
<![CDATA[
function globalHandler (b) {
b.setAttribute ("text", "Hello Button Clicked");
b.setAttribute ('width', 200);
}
]]>
</script>
</canvas>
|
This application can be compiled and invoked using http://localhost:8080/lps-4.0.x/event/PassingObjectReference.lzx.
In general, animation of an
object can be achieved by dynamically changing the value of its x and y
coordinates. Animation in OpenLaszlo is easy via the use of the animator and animatorGroup tags. The animator
tag is used within an object to perform a movement while the animatorGroup tag is used to group multiple
animator tags to perform more than one type of animation. The LZX
application in Listing 22 shows a button that moves along a horizontal
line.
Listing 22. SimpleAnimation.lzx
<canvas width="450" bgcolor="#6699FF" height="200">
<button width="200" height="80" align="center" valign="middle"
text="Animated Stuff">
<animator attribute="x" from ="0" to="300" duration="5000"/>
</button>
</canvas>
|
The button in the above example cruises from x=0 to x=450 in 5000 milliseconds. You can execute this example with http://localhost:8080/lps-4.0.x/animation/SimpleAnimation.lzx. Figure 19 shows the generated output.
Figure 19. Simple animation
By employing more than one animator tag, you can move an object simultaneously in two or more directions. It will rotate as it moves along the x axis. Listing 23 shows code using multiple animator tags.
Listing 23. MultipleAnimation.lzx
<canvas width="450" bgcolor="#6699FF" height="200">
<view width="100" height="60" align="center" valign="middle"
resource="IBMLogo.jpg>
<animator attribute="x" from ="0" to="450" duration="5000"/>
<animator attribute="rotation" to="360" duration="5000"/>
</view>
</canvas>
|
The button in the above application cruises from x=0 to x=450 and rotates 360 degrees in 5,000 milliseconds. Execute the example by browsing to http://localhost:8080/lps-4.0.x/animation/MultipleAnimation.lzx. Figure 20 shows the generated output.
Figure 20. Multiple animation
The animation in the previous examples start to move as soon as the
generated application loads. It can be made to start based on an event
such as onClick by setting the animator tag's
start attribute to false and calling the
doStart method on the animator object.
This is done in Listing 24.
Listing 24. ManualAnimationStart.lzx
<canvas width="450" bgcolor="#6699FF" height="200">
<button width="100" height="60" valign="middle"
text="Start Animation" onclick="this.a.doStart()">
<animator name="a" attribute="x" start="false"
from ="0" to="450" duration="1000" motion="easein"/>
</button>
</canvas>
|
The above application can be compiled and invoked using http://localhost:8080/lps-4.0.x/animation/ManualAnimationStart.lzx.
The repeat
attribute of the animator tag can be set to determine how many times the
animation cycles. Set it to "Infinity" to make the animation repeat
indefinitely. For example, the OpenLaszlo application in Listing 25 shows
an animation that is repeated three times.
Listing 25. RepeatAnimation.lzx
<canvas width="450" bgcolor="#6699FF" height="200">
<view width="100" height="60" align="center" valign="middle"
resource="IBMLogo.jpg>
<animator attribute="rotation" from ="0" to="360" duration="3000"
repeat="3"/>
</view>
</canvas>
|
Run this example with http://localhost:8080/lps-4.0.x/animation/RepeatAnimation.lzx.
Listing 26 shows a view that circles another view.
Listing 26. CircularAnimation.lzx
<canvas width="450" bgcolor="#6699FF" height="200">
<view valign="middle" align="center" bgcolor="#ddddee" width="350" height="150"/>
<view width="40" height="40" bgcolor="silver"
x="${ 180 + 30 * Math.cos (angle*Math.PI/180) }"
y="${ 100 + 30 * Math.sin (angle*Math.PI/180) }">
<attribute name="angle" value="0"/>
<animator motion="linear" attribute="angle" from ="0"
to="360" duration="2000" repeat="Infinity"/>
<animator motion="linear" attribute="rotation" from ="0"
to="360" duration="2000" repeat="Infinity"/>
</view>
</canvas>
|
See this example with http://localhost:8080/lps-4.0.x/animation/CircularAnimation.lzx. Figure 21 shows the generated output.
Figure 21. Circular animation
The animatorgroup tag can be used to group multiple animator tags. The process attribute determines how these tags are run. Set the
process attribute to "simultaneous" to have
all events occur at the same time. Set process
to "sequential" to have them run one after the other. By default, the
process attribute is sequential. Listing 27
shows the use of animatorGroup.
Listing 27. AnimatorGroup.lzx
<canvas height="400">
<button width="70" text="Click here">
<animatorgroup process="sequential">
<animator attribute="x" from ="0" to="300" duration="1000"/>
<animator attribute="rotation" from ="0" to="90" duration="1000"/>
</animatorgroup>
</button>
</canvas>
|
A timer is an object that can be set to invoke a method after the specified period of time elapses. For example, an alert message can be displayed after ten minutes of user inactivity as shown in Listing 28.
Listing 28. Timer.lzx
<canvas width="450" bgcolor="#6699FF" height="200">
<alert id="alertBox" width="250">10 minutes left for Completion!</alert>
<handler name="oninit">
var delegate = new LzDelegate (this, "showAlertBox");
lz.Timer.addTimer (delegate, 3000);
</handler>
<method name="showAlertBox">
alertBox.open();
</method>
</canvas>
|
The above example can be compiled and invoked using http://localhost:8080/lps-4.0.x/animation/Timer.lzx. Figure 22 shows the generated output.
Figure 22. Timer service
Another example in Listing 29 shows a digital clock.
Listing 29. DigitalClock.lzx
<canvas fontsize="45" width="450" bgcolor="#6699FF" height="200">
<text id="display" width="250" bgcolor="#ddddee" align="center" valign="middle"/>
<handler name="oninit">
lz.Timer.addTimer (new LzDelegate (this, "refreshClock"), 1000);
</handler>
<method name="refreshClock">
lz.Timer.addTimer (new LzDelegate (this, "refreshClock"), 1000);
var now = new Date ();
var hour = now.getHours ();
var minute = now.getMinutes();
var second = now.getSeconds();
display.setText (hour + ":" + minute + ":" + second);
</method>
<![CDATA[
if (n < 10) {
return "0" + n;
} else {
return n;
}
]]>
</canvas>
|
Run this example with http://localhost:8080/lps-4.0.x/animation/DigitalClock.lzx. Figure 23 shows the generated output.
Figure 23. Digital clock
OpenLaszlo provides users with a rich set of components that can readily be used for any LZX applications. Figure 24 shows the class hierarchy of some of the built-in components in OpenLaszlo.
Figure 24. Component class hierarchy
The Slider
is a component that allows the selection of a value by dragging a button.
The slider class is the template for all
sliders. It is a direct child class of Baseslider. The Baseslider class in
turn extends the Basevaluecomponent class, a
direct descendant of Basecomponent. The code in
Listing 30 uses the slider to control the opacity of a view.
Listing 30. Slider.lzx
<canvas width="450" bgcolor="#6699FF" height="200">
<slider name="s" valign="middle" align="center" height="100"
showvalue="true" width="200" value="50"/>
</canvas>
|
The above application can be compiled and invoked using http://localhost:8080/lps-4.0.x/richComponents/Slider.lzx. Figure 25 shows the generated output.
Figure 25. Slider component
As the name implies, the datepicker component allows
you to easily select a date. This component is represented by the datepicker class, which is a direct descendant of
the Basedatepicker class. Basedatepicker is an abstract class and is a subclass of Basecomponent. For example, the code in Listing
31 allows the user to select a date and displays the selected date in a
text tag.
Listing 31. Datepicker.lzx
<canvas width="450" bgcolor="#6699FF" height="200">
<script>
var today = new Date ();
var lastYear = new Date (today.getFullYear () - 1,
today.getMonth (), today.getDate ());
var nextYear = new Date (today.getFullYear () + 1,
today.getMonth (), today.getDate ());
</script>
<simplelayout axis="y" spacing="5"/>
<datepicker earliestdate="${lastYear}"
selecteddate="${today}"
latestdate="${nextYear}">
<handler name="onselecteddate">
if ( this.selecteddate != null ) {
display.year.setText (
this.selecteddate.getFullYear() );
display.month.datapath.setXPath(
"datepicker_strings_en:/months/month[@index='" +
this.selecteddate.getMonth() + "']/@full" );
display.date.setText ( this.selecteddate.getDate() );
}
</handler>
</datepicker>
<view id="display">
<text name="month" resize="true" datapath="."/>
s<text name="date" resize="true"/>
<text name="year" resize="true"/>
<simplelayout axis="x" spacing="2"/>
</view>
</canvas>
|
Compile and invoke the example above by using http://localhost:8080/lps-4.0.x/richComponents/DatePicker.lzx. Figure 26 shows the generated output.
Figure 26. Date picker
The
scrollbar component is represented by the scrollbar class. It is a subclass of Basescrollbar, which is a direct subclass of Basecomponent. The code in Listing 32 shows an
LZX application that uses one vertical scrollbar and one horizontal
scrollbar.
Listing 32. ScrollBar.lzx
<canvas width="450" bgcolor="#6699FF" height="200">
<view name="main" width="100" height="100" clip="true">
<text multiline="true">
OpenLaszlo is an open source platform invented by Laszlo Systems,
a company based in San Mateo, California for the development and
deployment of rich Internet based applications.It is released
under the Open Source Initiative-certified Common Public License.
One of the greatest challenge faced by Rich Interactive
Applications (RIA) developers today is that of Browser
Compatibility. Since OpenLaszlo is based on the famous Java
paradigm of write-once-run-everywhere, it ensures that
applications based on OpenLaszlo runs uniformly in various
browsers in multiple operating systems.
</text>
<scrollbar axis="y"/>
<scrollbar axis="x"/>
</view>
</canvas>
|
The example can be compiled and invoked using http://localhost:8080/lps-4.0.x/richComponents/ScrollBar.lzx. Figure 27 shows the generated output.
Figure 27. ScrollBar
A tab is a view that can contain tab panes. Each tab pane has a title and can store other components. The tab and tab panes are a good way to arrange components in a small area as shown in Listing 33.
Listing 33. TabbedPane.lzx
<canvas width="450" bgcolor="#6699FF" height="300">
<form inset_top="10">
<tabs tabalign="right">
<tabpane bgcolor="silver" text="Name" tabwidth="80">
<simplelayout axis="y"/>
<text>Customer Name</text>
<edittext name="customerName"/>
<text>Email</text>
<edittext name="email"/>
<radiogroup name="customerType">
<radiobutton>Silver</radiobutton>
<radiobutton>Gold</radiobutton>
</radiogroup>
<button>Submit</button>
</tabpane>
<tabpane bgcolor="silver" text="Address" tabwidth="80">
<simplelayout axis="y"/>
<text>Address</text>
<edittext name="address"/>
<text>City</text>
<edittext name="city"/>
<text>State</text>
<edittext name="astate"/>
<text>Pin Code</text>
<edittext name="pincode"/>
</tabpane>
</tabs>
</form>
</canvas>
|
Invoke the example above by browsing to http://localhost:8080/lps-4.0.x/richComponents/TabbedPane.lzx. Figure 28 shows the generated output.
Figure 28. TabbedPane
A tree is an
OpenLaszlo component to display hierarchical data, such as XML. The tree class represents a tree and is a subclass of
Basetree. Basetree is a child class of Basecomponent. The code in Listing 34 shows how to construct
and use a tree.
Listing 34. TreeView.lzx
<canvas width="450" bgcolor="#6699FF" height="200">
<view valign="middle" align="center" width="200" height="150">
<tree open="true" text="OpenLaszlo Article">
<tree text="Chapter 1: Overview" isleaf="true"/>
<tree open="true" text="Chapter 2: Basic Components">
<tree text="Section 1: Slider" isleaf="true"/>
<tree text="Section 2: ScrollBar" isleaf="true"/>
</tree>
</tree>
</view>
</canvas>
|
Use http://localhost:8080/lps-4.0.x/richComponents/TreeView.lzx to run the example. Figure 29 shows the generated output.
Figure 29. Tree View
OpenLaszlo can be used to display and manipulate
data using XPath, a language for retrieving data from an XML
document. The LzDataset class is used to hold
the XML data and also to retrieve data via HTTP GET or POST requests.
Figure 30 shows the LzDataset class
hierarchy.
Figure 30.
LzDataset
class hierarchy
Data in the dataset can be manipulated using <datapath> and <datapointer>.
Datapath can be used to access the data contained in the dataset using XPath as shown below. As an example, the code in Listing 35 shows how to use a DataPath.
Listing 35. Using DataPath.lzx
<canvas width="600" bgcolor="#6699FF" height="220">
<dataset name="myData" request="true" type="http" src="data.xml"/>
<grid height="100" valign="middle" datapath="myData:/company"
contentdatapath="department">
<gridcolumn width="100">
Name
<text datapath="name/text ()"/>
</gridcolumn>
<gridcolumn width="100">
ID
<text datapath="id/text ()"/>
</gridcolumn>
<gridcolumn width="200">
Description
<text datapath="desc/text ()"/>
</gridcolumn>
<gridcolumn width="100">
Location
<text datapath="location/text ()"/>
</gridcolumn>
<gridcolumn width="70">
<view datapath="position ()">
<button text="delete">
<handler name="onclick">
parent.datapath.deleteNode ();
</handler>
</button>
</view>
</gridcolumn>
</grid>
</canvas>
|
Listing 36 shows the contents of data.xml.
Listing 36. Contents of data.xml
<company>
<department headCount="19">
<name>HR</name>
<id>Comp-HR-01</id>
<location>First-Flr</location>
<desc>Looks after Human resources</desc>
</department>
<department headCount="200">
<name>Manufacturing</name>
<id>Comp-MFG-02</id>
<location>Ground-Flr</location>
<desc>Manufactures Components</desc>
</department>
<department headCount="65">
<name>Marketing</name>
<id>Comp-Mktg-01</id>
<location>Third-Flr</location>
<desc>Markets the product</desc>
</department>
</company>
|
The above application can be compiled and invoked using http://localhost:8080/lps-4.0.x/data/UsingDataPath.lzx Figure 31 shows the generated output.
Figure 31. Using Datapath
DataPointer acts as a cursor in a dataset. DataPointer can be used to sequentially move through records contained in the dataset. Listing 37 shows how to use a DataPointer.
Listing 37. UsingDataPointer.lzx
<canvas width="450" bgcolor="#6699FF" height="200">
<simplelayout spacing="5"/>
<script>
var isLast = false;
</script>
<dataset name="mydata" request="true" type="http" src="data.xml"/>
<alert name="myalert"/>
<view id="tt" height="60" valign="middle" width="450" font="verdana" fontsize="20">
<text name="output" y="30" align="center"/>
</view>
<view height="150" align="center" valign="middle" >
<simplelayout axis="x" spacing="4" />
<datapointer id="mydp" xpath="mydata:/company/department[1]"/>
<button font="verdana" fontsize="15"> Next Record
<handler name="onclick">
isFirst = false;
var s = mydp.xpathQuery('name/text()');
if(isLast){
s = 'Last Record!';
}
if(!mydp.selectNext()){
isLast = true;
}
tt.output.setText(s);
</handler>
</button>
</view>
</canvas>
|
Run the example with http://localhost:8080/lps-4.0.x/data/UsingDataPointer.lzx. Figure 32 shows the generated output.
Figure 32. Using
DataPointer
In software development, good debugging tools help make applications more robust and defect-free. OpenLaszlo comes equipped with an enhanced debugging tool that allows the developer to view runtime error messages, evaluate variable values, etc.
To display the Debugger window do the following:
- Set the
debug attribute of the canvas tag to true:
<canvas debug="true"> - Append the query parameter
debug=trueat the end of the URL used to request the OpenLaszlo application. For instance:http://localhost:8080/lps-4.0.x/app14/debugTest.lzx?debug=true - Click the Debug radio button and the Compile button
As an example, the code in Listing 38 shows a button in a canvas.
Listing 38. DebugButton.lzx
<canvas width="450" bgcolor="#6699FF" height="800">
<button id="buttonId" width="200" height="80" align="center" valign="middle">
Hello World!!</button>
</canvas>
|
The
above application can be invoked with debugging enabled by opening its
URL with the debug=true parameter:
http://localhost:8080/lps-4.0.x/debug/DebugButton.lzx?debug=true.
This will load the application and open a Laszlo Debugger window with an
input text field at the bottom.
Type the button ID buttonId and press Enter. The input text will
be echoed in green, and the debugger will print out the object as a
blue hyperlink.
Next, click on the object link in the debugger
window <<button>#0| #buttonId>>. The debugger will print
out the attributes of the JavaScript object as shown below in Figure
33.
Figure 33. Debugger window
Typing a JavaScript expression into the debugger will compile the expression
and print out the result. For example, buttonId.width will return the
value of the width attribute. Similarly, entering the command
buttonId.setAttribute('width', 400) will change the width of the
displayed button on the canvas. The Debugger window is an instance of the
Debug class, which is a subclass of LzView. Therefore, all attributes in the LzView class are also available in the Debug class.
The following are the methods defined in the Debug class:
backtrace (frameCount)— Copy the snapshot of the current call stack into aLzBacktraceobject, which can then be printed or inspected. This method is only available if the application is compiled with-option debugBacktrace=true. TheframeCountargument specifies the number of frames to omit from the backtrace. (The default is 1).error (control, args)— Displays an error on the console. Thecontrolargument specifies a format control and theargsargument represents any number of arguments.format (control, args)— Formats the output using theformatToStringmethod. Thecontrolargument specifies a format control and theargsargument represents any number of arguments.formatToString (control, args)— This method is similar to theprintffunction in the C language. Thecontrolargument specifies a format control and theargsargument represents any number of arguments.inspect (object, reserved)— Displays the properties of the specified object on the debug console. Thereservedargument is reserved for future use.-
log (message)— Sends the message to the log file. monitor (object, property)— Monitors the specified property of the specified object. Every time the value of the property changes, a message will be displayed in the Debugger window.trace (object, method)— Monitors the use of the specified method in the specified object. Every time the method is invoked, a message will be printed in the Debugger window.-
unmonitor (object, property)— Cancels the monitoring of the specified property on the specified object. -
untrace (object, method)— Cancels the monitoring of the specified monitor on the specified object.
The Debugger window can also be used for evaluating JavaScript global variables and expressions, and executing JavaScript statements. The evaluator is the text field and the EVAL button at the bottom of the Debugger window.
OpenLaszlo is an open source development platform for building rich Web applications written in LZX, an XML language that includes embedded JavaScript.
Unlike many Ajax solutions, however, OpenLaszlo applications are portable across browsers. This is possible due to the OpenLaszlo compiler technology, which takes care of runtime details, allowing the developer to concentrate more on the application's behavior/logic and appearance, truly making it a "write once, run everywhere" platform. OpenLaszlo supports a rich graphics model with many built-in and reusable components, as well as advanced WYSIWYG text and graphical editing tools.
| Description | Name | Size | Download method |
|---|---|---|---|
| Sample OpenLaszlo Code for this article | os-openlaszlo-ArticleCode.zip | 12KB | HTTP |
Information about download methods
Learn
-
Check out the OpenLaszlo
documentation.
-
Visit OpenLaszlo.org and see the
tutorials there to get a better understanding of how OpenLaszlo works.
-
This 40-minute
screencast demonstrates construction of a simple
client-server application.
-
To listen to interesting interviews and discussions for software developers, check out developerWorks podcasts.
-
Stay current with developerWorks' Technical events and webcasts.
-
Follow developerWorks on Twitter.
-
Check out upcoming conferences, trade shows, webcasts, and other Events around the world that are of interest to IBM open source developers.
-
Visit the developerWorks Open source zone for extensive how-to information, tools, and project updates to help you develop with open source technologies and use them with IBM's products, as well as our most popular articles and tutorials.
-
The My developerWorks community is an example of a successful general community that covers a wide variety of topics.
-
Watch and learn about IBM and open source technologies and product functions with the no-cost developerWorks On demand demos.
Get products and technologies
- Get OpenLaszlo.
- Get a
quick introduction to OpenLaszlo by looking at "Learn Laszlo in 10 Minutes."
-
Innovate your next open source development project with IBM trial software, available for download or on DVD.
- Download
IBM product evaluation versions
or explore
the online trials in the IBM SOA Sandbox and get your hands on application development tools and middleware products from
DB2®, Lotus®, Rational®, Tivoli®, and WebSphere®.
Discuss
-
Participate in developerWorks blogs and get involved in the developerWorks community.

Kumarsun Nadar currently works as a Senior Staff Software Engineer with IBM India Software Labs (ISL) in the WebSphere Business Service Fabric product team, based out of Mumbai, India. As part of this team, he was involved in the UI development of the Fabric Web Tools module, which was based on the Wicket framework. He has attained SUN Microsystems certifications in SCJP, SCWCD and SCBCD and has experience in various client- and server-side technologies such as Wicket, EJB, Hibernate, Struts and so on, based on the Java/J2EE platform. His hobbies include watching, as well as playing, sports such as Cricket, and TT.




