OpenLaszlo -- A platform to rapidly build and deploy rich Internet applications

Understand what OpenLaszlo is and how it simplifies the way rich Internet applications can be developed and deployed

Meet OpenLaszlo, an open source platform, released under the Common Public License (CPL), for the development and delivery of rich Internet applications (RIAs). OpenLaszlo is based on LZX, which is an object-oriented language utilizing XML and JavaScript. Rich-client applications written with OpenLaszlo run across browsers and across platforms. In this article, we look at the architecture and APIs of OpenLaszlo with several examples. We also cover the basic debugging tools.

Share:

Kumarsun Nadar (kumarsun.nadar@in.ibm.com), Senior Staff Software Engineer, IBM

Photo of KumarsunKumarsun 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.



09 February 2010

Also available in Russian Japanese Spanish

Overview

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.


Architecture

The following figure shows the server side and the client-side architecture of OpenLaszlo.

Figure 1. OpenLaszlo server and client subsystems
Diagram showing architecture diagram of OpenLaszlo server and client subsystems

OpenLaszlo server

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 client

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.

Request cycle

A typical request flow takes the following path:

  1. User sends a request for a resource in the form of a URL via the browser.
  2. The OpenLaszlo server retrieves the resource based on the URL and sends it to the Interface Compiler for compilation.
  3. 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.
  4. 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.
  5. 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.
  6. The user enters some request data on the client side and submits the data.
  7. The OpenLaszlo server invokes the appropriate data connector, which, in turn, fetches the XML data.
  8. The OpenLaszlo server sends the data back to the client.
  9. 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
Diagram showing flow diagram of the request cycle just described

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>

Saving the source file

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
Screenshot of the 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
Screenshot of sample Hello World OpenLaszlo application shows the display without the development toolbar

Basic components

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.

Canvas

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
Screenshot of the Canvas showing the text 'OpenLaszlo World!

View

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
Screenshot shows an empty blue rectangle, representing the 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
Screenshot grey rectangle, prepresenting a view, contained within the blue rectangle, representing the parent view

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
Screenshot of a Resource View, showing the blue rectangle with an IBM logo in the top left corner

Window

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
Screenshot shows the blue canvas with a floating Window containing the text 'OpenLaszlo World!'

Alert

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
Screenshot shows 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.

Button

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
Screenshot shows the blue rectangle of the canvas with a clickable button labeled 'Hello World!!' in the center

Working with layouts

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

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
Screenshot shows three colored squares laid out side by side on the blue canvas

ResizeLayout

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
Screenshot shows a blue canvas with three colored rectangles laid out side by side

SimpleBoundsLayout

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
Screenshot shows a blue canvas with three colored squares representing views layed out side by side

ReverseLayout

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
Screenshot shows a blue canvas with three colored rectangles side by side represing the three views

ConstantLayout

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
Screenshot shows rectangles of various colors and shapes nested within one another

WrappingLayout

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
Screenshot shows the colored rectangles sized too large to lay side by side

Event handling

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
Image shows two screenshots show a canvas with a single button'

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

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.

Passing an object's reference

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.


Adding animation

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
Screenshot shows a button labeled 'Animated Stuff' with an arrow indicating motion to the right side of the screen

Multiple animation pieces

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
Screenshot shows the IBM logo in mid-motion, rotated slightly as it tumbles to the right of the screen

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.

Repeating animation

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
Screenshot shows a small square tumbling within a rectangluar view

Using animatorgroup

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>

Using timer

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
Screenshot shows a dialog box reading '10 minuts left for Completion!' with an OK button

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
Screenshotshows a time reading of '15:47:40'

Building rich components

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
Diagram shows the component tree of OpenLaszlo elements

Slider

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
Screenshot shows a slider centered on a scale of 0 to 100

datepicker

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
Screenshot shows a date picker calendar with the date November 1, 2009, selected

Scrollbar

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
Screenshot shows text in a view with both horizontal and vertical scrollbars

Tabs and Tabpane

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
Schreenshot shows a tabbed view with two tabs, Name and Address

Tree

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
Screenshot shows a graphical tree of folders, subfolders and objects

Working with XML data

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
Diagram shows a tree with the LzNode at the top. A fork comes off the left containing lzDataNode, LzDataElement and LzDataset

Data in the dataset can be manipulated using <datapath> and <datapointer>.

DataPath

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
Screenshot shows a spreadsheet-style view of the data

DataPointer

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
Screenshot shows a title 'Manufacturing' with a button labeled 'Next Record'

Debugging

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=true at 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
Screenshot shows the debugger window in action with a listing of different parameters associated with the running applications

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 a LzBacktrace object, which can then be printed or inspected. This method is only available if the application is compiled with -option debugBacktrace=true. The frameCount argument specifies the number of frames to omit from the backtrace. (The default is 1).
  • error (control, args)— Displays an error on the console. The control argument specifies a format control and the args argument represents any number of arguments.
  • format (control, args)— Formats the output using the formatToString method. The control argument specifies a format control and the args argument represents any number of arguments.
  • formatToString (control, args)— This method is similar to the printf function in the C language. The control argument specifies a format control and the args argument represents any number of arguments.
  • inspect (object, reserved)— Displays the properties of the specified object on the debug console. The reserved argument 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.


Conclusion

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.


Download

DescriptionNameSize
Sample OpenLaszlo Code for this articleos-openlaszlo-ArticleCode.zip12KB

Resources

Learn

Get products and technologies

Discuss

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into Open source on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Open source, WebSphere
ArticleID=466564
ArticleTitle=OpenLaszlo -- A platform to rapidly build and deploy rich Internet applications
publish-date=02092010