Chapter 15. Program Structure

Table of Contents

1. The canvas tag
1.1. Files included at compile time
1.2. Files imported at run time
1.3. Summary comparison of <include> and <import>
2. The <include> tag for compiled-in libraries
2.1. Including a Library
2.2. Including an instance
2.3. Including Text
3. The <library> tag
3.1. Library directories
4. The <import> tag for runtime includes
4.1. Positioning of imported library views
5. Deleting Imported Libraries
6. Conditional Compilation of Runtime-Dependent code
7. Debugging
8. Resources, Fonts, and Datasources
9. Accessibility
9.1. Overview of implementation

1. The canvas tag

An LZX application has exactly one canvas. The canvas is the container for all views and elements of the application.

An LZX application file is an XML file whose document root is a canvas element. The canvas contains attributes and elements that configure and define the application. For example,

Example 15.1. Hello World

<canvas height="15">
  <text>Hello, World</text>
</canvas>

is a simple LZX application. The canvas has a height and width measured in pixels; if you do not specify values for these attributes the default width and height are "100%".

In addition to the LZX code contained in the <canvas> block, OpenLaszlo applications may use code contained in separate library files. These libraries can be either compiled into the main program (using the <include> tag) or separately compiled and downloaded at run time (the <import> tag). These are described below.

1.1. Files included at compile time

An LZX application file may include other LZX files using the <include> element. When you use the <include> tag, the libraries you reference will be compiled into the program.

For example,

Example 15.2. Simple include

<canvas>
  <include href="hello-incl.lzx"/>
</canvas>

<library>
  <text>Hello World!</text>
</library>

1.2. Files imported at run time

A dynamic library is a portion of a program that can be loaded after the main application execution file has loaded. The goal for dynamic libraries is to reduce the initial download size of an OpenLaszlo application. This is required because initial download size (including all requests that precede initial user interaction) is used to evaluate web applications. Reducing the initial download size has the additional benefits of reducing the time to first interaction (although there are other ways of doing this), and of reducing bandwidth costs in the case where an optional feature of the application is not used.

Imported libraries can contain classes, instances, datasets, and <script> blocks. But any media resources in them are moved to the main (calling) application. For example, if this tag is included in the library file to be imported,

<view resource="foo.png"/>

the image resource is baked into the canvas application itself as a Flash resource. This means that the image is downloaded with the calling file, not the called file, as one might otherwise expect.

Resources that are loaded over http, as for example,

<view resource="http:foo.png"/> 

are still compiled into a runtime request.

1.3. Summary comparison of <include> and <import>

<include> and <import> both break an application into source files: they let you distribute an application's sources among multiple source files. They address developer workflow, code ownership, and source control issues.

However they are incorporated into an application, all library files share the same namespace.

<import> additional breaks an application into multiple delivery components: they let an application defer download of some components. It addresses the initial download size of an application; nothing more. It is intended for the scenario where all the source files are available when an application is created; it's synonymous with <include> except that the bits it creates are distributed across multiple files, instead of all placed in one file. These bits can't be mixed and matched any more than the bits in a single-object-file application created with <include> can.

OpenLaszlo does not support separate compilation: the library files will only work with the specific application file that they were compiled against, and vice versa.

The rest of this chapter explores these concepts in greater detail.

2. The <include> tag for compiled-in libraries

The <include> tag implements the XInclude standard for XML inclusions. The <include> tag can be used in three ways:

  • To include a <library> file.

  • To include an element hierarchy.

  • To include text from a text file.

The source code for an OpenLaszlo application can be contained in a single source file which specifies all aspects of the application. Alternatively, the <include> and <library> tags can be used to separate the source for an application into multiple files.

By dividing your application into a number of files, you can limit the size of your source files to a maintainable size. You can even break deep view hierarchies into multiple files to improve modularity, clarity and source code organization.

The value of the href attribute is the name of a file whose content is included at the point of the <include> element. This is the target of the include.

2.1. Including a Library

When the target is a library file (an XML file whose root element is <library> ), the contents of the library file are included in the application. Any views, scripts, fonts, resource, audio, datasource, dataset, and class definitions in the library file are included in the application. A library file can include other libraries, but a library is included in an application only once, no matter how many include statements reference it. For example:

Example 15.3. Including a library file

<canvas height="100" width="400">
  <include href="library.lzx"/>
  <mywindow/>
</canvas>

<library>
  <class name="mywindow" extends="window"
   title="MyTitle">
    <button>Click me!</button>
  </class>
</library>

2.2. Including an instance

When the target is an XML file that is not a library file, its root element is included at the point of the include element. This can be used to break a view hierarchy into multiple files. Unlike including a library file, a non-library file is inserted once each time it is included.

The following example shows a view with two buttons, both labeled "Click me!":

Example 15.4. Including a node

<canvas height="100">
  <window layout="axis: y">
    <include href="inner.lzx"/>
    <include href="inner.lzx"/>
  </window>
</canvas>

Example 15.5. inner.lzx

<button>Click me!</button>

2.3. Including Text

If the type attribute has the value text, the included file is included as characters, rather than XML. This can be used to include literal text from another file.

Example 15.6. Including text

<canvas height="100">
  <window>
    <button>
      <include href="mytext.txt" type="text"/>
    </button>
  </window>
</canvas>

Example 15.7. mytext.txt

Click me!

3. The <library> tag

A library file is a file contained in a <library> tag. A library file cannot be compiled to an application, but an application can include library files through use of the <include> tag. Library files are used to break an application's source into multiple files, or to share code among multiple applications.

For example, instead of defining a view as in <canvas><window title="mywindow"/></canvas>, an application can include a library that defines the view. In this case, the application's canvas source file would read <canvas><include href="mylib.lzx"/></canvas>, and mylib.lzx would contain the definition <library><window title="mywindow"/></library>.

A library file can contain any element that a canvas source file can contain, except for the <splash> , <connection> , and <debug> elements. Including a library includes the elements — code, views, and definitions — in the library.

An application only contains one copy of each library, no matter how many includes for that library its source files contain. For example, <canvas><include href="mylib.lzx"/><include href="mylib.lzx"/></canvas> is equivalent to the previous example: only one window is defined.

3.1. Library directories

If a directory contains a file named library.lzx, you can include that file by referencing the name of the directory. For example, the utils components directory contains a file named library.lzx. Therefore, the following two fragments have the same effect:

Example 15.8. Include library.lzx file

<include href="utils/library.lzx"/>

Example 15.9. Include directory with library file

<include href="utils"/>

Similarly, you can write <include href="utils/states"/> to include the files that the file utils/states/library.lzx includes, and <include href="lz"/> to include the OpenLaszlo component set.

3.1.1. Auto-includes

Some of the distributed components are automatically included, if the application references them. If the application uses a tag that it has not defined, but that is defined in the base, lz, charts or utils directory, the file that contains this class is included. The following pairs of programs are therefore equivalent:

Example 15.10. Use button with explicit include

<canvas height="50">
  <include href="lz/button.lzx"/>
  <button>Click me!</button>
</canvas>

Example 15.11. Use button with implicit include

<canvas height="50">
  <button>Click me!</button>
</canvas>

Example 15.12. Subclass button with explicit include

<canvas height="50">
  <include href="lz/button.lzx"/>
  <class name="mybutton" extends="button" fgcolor="red"/>
  <mybutton>Click me!</mybutton>
</canvas>

Example 15.13. Subclass button with implicit include

<canvas height="50">
  <class name="mybutton" extends="button" fgcolor="red"/>
  <mybutton>Click me!</mybutton>
</canvas>

A file is only included if the application references a class that it does not define in its own sources. The following two programs define their own <button> tag, and therefore do not implicitly include the file that defines the OpenLaszlo <button> tag.

Example 15.14. Define button

<canvas height="50">
  <class name="button">
    <text>Click me!</text>
  </class>
  <button/>
</canvas>

Example 15.15. Define and subclass button

<canvas height="50">
  <class name="button">
    <text>Click me!</text>
  </class>
  <class name="mybutton" extends="button" fgcolor="red"/>
  <mybutton/>
</canvas>

3.1.2. More on base components

An application can include the entire set of Base components by including the line <include href="base"/>. An application can include individual Base components by including just the files that define those components. The Base components are included automatically if an application refers to them but does not define or include them.

4. The <import> tag for runtime includes

The tag <import> , is used to include dynamic libraries.

The <import> tag must occur at the top level of an application (as the immediate child of the <canvas> or <library> document root element of a file).

The syntax of the import tag is as follows:

 <import href="mylib.lzx" prefix="ns" stage="late"/>

All attributes except href are optional. The "href" attribute of an import statement is the pathname of a library file. The pathname is resolved relative to the pathname of the file that contains the import statement.

The <import> tag has these attributes:

Table 15.1. Attributes for <import>

name type default description
href URI required The URI of a file that defines the library. In the case where stage is "late", this has the same meaning as it does in an <include> tag. If stage="deferred", the URI is resolved relative to the location of the location of the file that contains the <import> element, and a request for this URI is sent to the server to request a library file that is downloaded into the running application.
stage "late" | "defer" compile If stage is "late", the library is imported once the main application file has finished loading. If it is "defer", the library is imported during the execution of the application by an API call, as described below.
name JavaScript Identifier global If this is not empty, it is the name of an ECMAScript object whose properties are the global ECMAScript names (classes, functions, objects) that the library defines. If it is not empty and is the name of a namespace prefix that the including file defines with a xmlns or xmlns:prefix attribute, tag names such as myclass that the library defines are accessible outside the library as prefix myclass.
prefix XML namespace prefix "" If this is not empty, it must be an XML namespace prefix that is in scope on the <import> element. In this case, class definitions in the target library are bound to XML tags in the specified namespace.
onerror script "" Code to be executed if the import call generates an error. For example, it is an error for a program to contain an XML reference to a class that is defined in a late or defer library.
onload script "" Code to be executed after the library has successfully completed loading.
ontimeout script "" Code to be executed if the operation times out.

A "defer" library is loaded programmatically via a JavaScript method on the object bound to the variable named by the value of its "name" attribute; in this example, "mylib".

 <import name="mylib" href="lib/foo.lzx" stage="defer" onload="doSomething()"/>

4.1. Positioning of imported library views

Say you had a view, call it "blueview" in a library to be imported. If you merely used the load()to import the code for "blueview", you would see the view show up at the bottom of the application, not at the place where the method was invoked. This is because the load() method only tells <import> what to load, not where to load it. To get the effect we want, we could define a class in a library and instantiate it dynamically. (The following discussion assumes an understanding of delegates and timers, explained in Chapter 30, Delegates.)

To do position code where we want it in the importing application, we would make a delegate that directly listens for the onload event from the <import> and instantiates the class (or calls a method to do so). Something like:

   <handler name="onload" reference="blueview">
      this.makeChild({name: 'blueview', ...});
   </handler>

We could define an onload() on <import> to call a method to set a global variable "loaded" to true.

Then, at the place where we want blueview to appear, we could load the library and then set up a delegate and timer which calls a method to see if the variable "loaded" is true, and if not reset the timer. If it is true--that is, if the class has been loaded-- the view is created.

5. Deleting Imported Libraries

To 'unload' an imported library, three things have to be done:

  1. Destroy all the instances that were created by the library. This is done by calling iii.destroy(); for each instance iii. Note that if you have created references to the instance outside of the library, you must delete those references.

  2. Destroy all classes that were created by the snippet. This is done by calling ccc.destroy(); for each class ccc. Note that if you have created references to the class outside of the library, you must delete those references.

  3. Unload the library. This is done by calling sss.unload()` where sss is the name of the library (in the import tag).

At this point, you can re-load the library by calling sss.load()` If you know you will never use the library again, you can call sss.destroy(); to remove the library from your application altogether.

6. Conditional Compilation of Runtime-Dependent code

You can enclose blocks of code within <switch> elements that are associated with a specific runtime. The <switch> is a compiler directive that instructs the compiler to compile or omit blocks according to the target runtime to which the application is being compiled.

Example 15.16. switch tag for condtional compilation

<canvas>
  <switch>
    <when runtime="dhtml">
       <text>This program has been compiled for DHTML</text>
    </when>
    <otherwise>
      <text>This program has been compiled for SWF</text> 
    </otherwise>
  </switch>
</canvas>

See Chapter 48, Understanding Compilation for a more in-depth discussion of these compiler directives.

7. Debugging

An LZX application can be debugged by requesting that the application be compiled in debug mode by setting the canvas's debug attribute to true:

Example 15.17. Compiling with the debugger

<canvas height="140" debug="true">
  <!-- ... -->
</canvas>

This has the same effect as pressing the Debug button in the developer console. It is also possible to invoke the debugger by loading the application using the ?debug=true query parameter.

See Chapter 50, Debugging for more information on using the debugger.

8. Resources, Fonts, and Datasources

In addition to including classes and instances, a library file can use the <font> , <resource> , and <datasource> tags to include fonts, media resources, and XML datasources defined in external files as well.

Elements within an application, such as <script> , <class> , and extensions of <view> , are evaluated in the order that they appear in the source file. In particular, code in a <script> element cannot refer to <view> elements that follow it.

9. Accessibility

OpenLaszlo provides partial support for the Microsoft Active Accessibility specification, which states, "[b]y using Active Accessibility and following accessible design practices, developers can make applications running on Windows more accessible to many people with vision, hearing, or motion disabilities." Accessibility support is a common requirement for application development in order to conform to the U.S. Federal requirement for accessible information systems (also known as Section 508). This support requires installation of third party software on the client machine, and is only available in the OpenLaszlo targets that run the Flash Player under Internet Explorer. See below for a list of currently available third party software.

9.1. Overview of implementation

Accessibility is implemented using five attributes on <view> and two methods on LzBrowser.

In LZX, the most basic visible object is a view. Since almost every visible object inherits from view, almost all visible objects will inherit accessibility support including image, text, button, checkbox, and radio button. (The one exception, images embedded within editable text views, is covered at the end of this section.) The following methods and attributes will be added to view:

These are the attributes on view. They are described briefly below.

aaactive="boolean"

activate/deactivate children for accessibility

aaname="string"

accessibility name

aadescription="string"

accessibility description

aatabindex="number"

accessibility tab ordering

aasilent="boolean"

accessibility silencing/unsilencing

These are the methods on LzBrowser.

LzBrowser.isAAActive()

returns true if a screen reader is active and the Flash player is focused.

LzBrowser.setClipboard(string)

sets system clipboard

By default, all text contained in an OpenLaszlo application will be read by supported screen readers. Therefore, the activation feature allows you to specify which views should be read by the screen reader. Activation applies to the current view and all of its children. Accessibility name and description provide the overview and detailed text for the screen reader. Accessibility tab ordering, specifies the reading order for accessible objects. Silencing/unsilencing specifies whether an individual item is accessible or not. Finally, LzBrowser provides the isAAActive() method to determine if a screen reader is active and the Flash player is currently focused.

aadescription is treated separately from the contents. If it's specified, aadescription will be read in addition to the aaname. By default, aaname is equal to the contents of the text field. aaname can also be specified or overridden.

For non-MSAA compliant screen readers such as R&W Gold, OpenLaszlo supports the ability to place text on the clipboard from within an OpenLaszlo application using the LzBrowser.setClipboard().

In this example, there are two views that provide accessibility information. When the first view is clicked, it uses the scripting API to unsilence the button.

Example 15.18. Specifiying accessibility parameters

<view aaactive="true" aaname="Activation Button" aadescription="This button allows you to access more information by activating important views." aatabindex="1" onclick="important.setAASilent(false)">

<button id="important" aaactive="true" aaname="Important Information" aadescription="Here is some important information." aatabindex="2" aasilent="true"/>

9.1.1. Compatibility Notes

The Flash Player has basic support for screen readers with Flash Player versions 6 and above. For best results, we recommend upgrading to Flash 8. OpenLaszlo's built-in version detection feature can facilitate automatic upgrades.

Here are some notes from the Macromedia Flash 8 accessibility FAQ:

Microsoft Active Accessibility (MSAA) makes it easier for all assistive technologies to incorporate support for Macromedia Flash Player. Once the contents of a Macromedia Flash movie are placed under MSAA, it is up to the individual assistive technology to render that content for the user. Macromedia is committed to expanding the number of tools that take advantage of the new features of Macromedia Flash Player. Macromedia is working with leading vendors of assistive technology to ensure the broadest possible support for Macromedia Flash Player. To date, the following assistive technologies support the Flash player: Window Eyes from GW Micro, JAWS from Freedom Scientific, Home Page Reader from IBM and ZoomText from Ai Squared.