Browser Inteqration
出自OpenFace
Chapter 32. Browser Integration
Part IV. In Depth
(这里面的功能是否被支持)
Though OpenLaszlo applications are not dependent on the browser or operating system for their look or behavior, there are some important limitations that the browser container places on the application. There are also a number of features that your application can use.
目录 |
Scaling OpenLaszlo Applications to Browser Dimensions
You can make the canvas of the OpenLaszlo application either a fixed size, or you can make it expand or contract as the browser window expands or contracts. To make the canvas an absolute size, set its height and width with integer values, for example, width="40" height="40". To have the canvas scale, simply express the height and width as percentages.
Note As of OpenLaszlo release 3.0, the Flash 5 target is no longer supported. Applications can be compiled for the Flash 6 or Flash 7 player. The default target is Flash 6.
The LzBrowser service
The LzBrowser service provides access to the browser and player environment. It includes methods to load URLs in the browser and check the version of the player. Furthermore, by using the LzBrowser service together with other OpenLaszlo functions described below, you can build applications that pass information and control between the OpenLaszlo application and the JavaScript of the browser.
As you explore examples in this chapter you should take the opportunity to explore the facilities provided by this service. The Lzbrowser is always running.
Embedding OpenLaszlo Applications
OpenLaszlo applications are .swf files sent from the OpenLaszlo Server to be rendered in the Flash Player. They can be from the OpenLaszlo Server to client:
as "naked" swf
as swf embedded in an html "wrapper" page
as xml source.
See the Request Types chapter of the Deployer's Guide for discussion of the various ways to request applications.
In this section we'll look at ways to include OpenLaszlo applications in HTML pages. This means, in effect, that the HTML page invokes the Flash player, and the player runs the OpenLaszlo application.
Embedding OpenLaszlo Applications in HTML pages
When you place a OpenLaszlo application inside an HTML page, that page has to have some way to know where to place the application, and how to handle it. That is, you must inform the browser that the embedded OpenLaszlo application is actually a swf file, and so forth. Necessary information is included in a file called embed.js, so you need to place a reference to that file within a <script> tag in the head of the HTML file. In particular, this filed defines the function LzEmbed.
You can, of course, put this information into an HTML file "by hand", but the easier way is to use the OpenLaszlo Server to generate a "wrapper" page that contains all the necessary information. You can edit this wrapper or paste its contents into an existing HTML page The steps below show how to do this.
The easiest way cause the OpenLaszlo Server to generate the appropriate wrapper pages, for both SOLO and proxied applications, is to use the Developer's Console. Simply press the appropriate button, "Server" or "SOLO", and follow the instructions that are then displayed.
Alternatively, you can generate wrappers by using the various request types on the url you use to browse to your application:
Invoke the lzx application with request type "?lzt=html". This generates the "wrapper."
Using your browser's "View source" function, copy the contents of the wrapper and place in a new file with a .html extension.
In the head of the HTML file, you will see the script tag that includes embed.js Adjust the path if necessary for deployment.
take lzEmbed method call including surrounding script tags copy that
paste to wherever you want the OpenLaszlo application to appear in HTML page
verify by running HTML file in your browser.
Consider the following simple OpenLaszlo application. (For now, pay no attention to the onreset method; we'll see it used later.):
Example 32.1. Hello Grace!
<canvas height="200" efcdebug="true" proxied="false">
<attribute name="reset"/>
<handler name="onreset">
canvas.redview.unfade.dostart()
Debug.write('Reset Button clicked')
</handler>
<view name="redview" bgcolor="red" height="30" width="150" clip="true">
<animator name="fade" attribute="opacity" to=".10" duration="2000"/>
<animator name="unfade" attribute="opacity" to="1" duration="2000" start="false"/>
<text x="15"> Hello Grace!
<animator name="wrapper" attribute="x" to="150" duration="2000"/>
</text>
</view>
</canvas>
The wrapper page returned with by invoking it with the ?lzt=html type returns the following wrapper:
Example 32.2. Simple wrapper page
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <link rel="SHORTCUT ICON" href="http://www.openlaszlo.org/favicon.ico"> <title>OpenLaszlo Application</title><style type="text/css"> html, body { margin: 0; padding: 0; height: 100%; } body { background-color: #ffffff; } </style><script src="/lps-dev/lps/includes/embed.js" type="text/javascript"></script></head> <body><script type="text/javascript"> lzEmbed({url: 'graceie.lzx?lzt=swf', bgcolor: '#ffffff', width: '500', height: '200'}); </script></body> </html>
Later on in this chapter we'll show how to modify this wrapper to enable more sophisticated applications.
The <embed> tag
To embed OpenLaszlo applications in HTML pages, you use <embed> tag. The mechanics of this can be handled automatically as we have seen above. For your reference, here's a sample embed object:
Example 32.3. The embed tag
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,79,0"
width="705"
height="80">
<param name="movie" value="OpenLaszloapplication.lzx?lzt=swf">
<param name="quality" value="high">
<param name="scale" value="noscale">
<param name="salign" value="LT">
<param name="menu" value="false">
<param name="bgcolor" value="#394660">
<embed src="OpenLaszloapplication.lzx?lzt=swf"
scale="noscale"
salign="lt"
width="705"
height="80"
bgcolor="#394660"
type="application/x-shockwave-flash"
pluginspage="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash">
</embed>
</object>
How to specify the target
The query parameterlzr identifies which version is to be issued. Use lzr=swf6, lzr=swf7, or lzr=swf8 accordingly.
Alternatively you can compile your applications using the lzc command. Use the --runtime= argument to specify the target, for example,
lzc myfile.lzx --runtime=swf7
Using LzEmbed()
LZX provides a number of helpful javascript routines to simplify the process of embedding LZX applications into your web pages. The most common of these is lzEmbed, which easily specifies the application to include and any request parameters that your application relies on. LzEmbed is in /3.3.3/lps/includes/embed.js.
Example 32.5. Using LzEmbed
<script type="text/javascript">
lzEmbed({url: 'header.lzx?lzt=swf', bgcolor: '#394660', width: '705', height: '80'});
</script>
Page design and layout
<script type="text/javascript">
lzEmbed({url: 'header.lzx?lzt=swf', bgcolor: '#394660', width: '705', height: '80'});
</script>
Integrating with Frames
Frames are a very handy way to use OpenLaszlo applications within a page. If you are using a OpenLaszlo application for your navigation or as a widget in your page you might consider using frames to format your layout.
Frame Sets
When laying out a page that will use OpenLaszlo applications in different places, you can use a frameset like this:
Example 32.7. example frameset
<html>
<frameset cols="128,*">
<frame name="navBar" src="myOpenLaszloNav.lzx?lzt=html" /> <frame name="contentArea" src="myOpenLaszloContent.lzx?lzt=html" />
</frameset>
</html>
Inside your application use the target parameter of LzBrowser.LoadURL() to load pages in the target frame.
Example 32.8. target in loadURL
LzBrowser.loadURL('http://www.laszlosystems.com','contentArea');
Inline Frames
Like framesets, OpenLaszlo applications can be embedded within an "inline frame" or <iframe> which can be more flexible for your layout and easier to use. Like regular frames, inline frames can be named for later reference by the OpenLaszlo application.
Example 32.9. iframes and applications
<html> <body>
Here is a header
<iframe src="myOpenLaszloApplication.lzx?lzt=html" width="200" height="200"
frameborder="0" name="inlineApplication" scrolling="no"/>
</body> </html>
Bear in mind that the iframe will contain a canvas, and unless you want the browser to provide scrollbars, you should set the width and height equal to that of your canvas plus any margin you may have included.
Popping and reusing browser windows
The same way you would target content to a frame, you can target the loadUrl to new window.
Example 32.10. new Blank window
<canvas height="27" >
<button onclick="LzBrowser.loadURL('http://www.laszlosystems.com','_blank');" text="Click Me!"/>
</canvas>
This mechanism can also be used to name the window allowing subsequent loads to occur in the same window
Example 32.11. new Blank window
<canvas height="56" >
<simplelayout/>
<button onclick="LzBrowser.loadURL('http://www.openlaszlo.org','newOpenLaszloWindow');" text="OpenLaszlo Homepage"/>
<button onclick="LzBrowser.loadURL('http://www.mylaszlo.com','newOpenLaszloWindow');" text="myLaszlo.com"/>
</canvas>
Passing startup Data to Embedded Applications
Any query parameters that you add to the end of your url to load the application get passed into the application as globals.
Example 32.12. Passing query parameters to LZX application
<script type="text/javascript">
lzEmbed({url: 'header.lzx?lzt=swf&globalVar=foo', bgcolor: '#394660', width: '705', height: '80'});
</script>
Query Parameters and Global Variables
Once the data has been passed in you can simply access it as a global variable from within the OpenLaszlo application.
Example 32.13. Accessing parameters
<canvas efcdebug="true" oninit="Debug.write(globalVar)"/>
In many cases you will have full control of the HTML content that is embedding your application. In many other cases you won't be able to depend on the existence of those query parameters so it is wise to provide sane defaults for those values:
Example 32.14. Setting defaults
<canvas efcdebug="true" width="200" height="200"> <script> var innerVar = typeof(global.globalVar) != 'undefined' ? global.globalVar : 'bar'; Debug.write(global.innerVar); </script> </canvas>
The above application is requested without a globalVar query parameter. The debugger therefore displays the default value bar. If this application is requested with the globalVar=foo query parameter, it will display the default value 'bar'. Click here to see the application in a popup window with the query parameter applied.
Application state
Using query parameters, you can craft your application to start up in a specific state. The default behavior of a tabslider is to have none of the tabelements opened at startup. The following application changes that default to open to the tab specified on the query parameter, and if one isn't provided, open to the first element.
Example 32.15. Restoring state
<canvas width="300" height="250">
<script>
var opened = typeof(global.tab) != 'undefined' ? global.tab : 'one';
</script>
<tabslider width="150" x="10" y="10"
height="200"
spacing="2" slideduration="300" oninit="this[global.opened].setAttribute('selected',true)">
<tabelement name="one" text="Tabelement One"/>
<tabelement name="two" text="Tabelement Two"/>
<tabelement name="three" text="Tabelement Three"/>
</tabslider>
</canvas>
Click here to see this application in a popup with a different initial state applied. This is useful when creating links from outside the application, or for creating a bookmark for an application. Another thing to do is read browser cookies from javascript and pass in the parameters when calling LzEmbed().
Supporting Multiple Resolutions
Most web surfers have discovered the merits of high resolution displays. Some, though, still view the web using very low resolutions. OpenLaszlo applications can be written in a way that allows for multiple resolution versions of the same application to coexist using the same codebase.
Begin by creating your application in a library file instead of a canvas, but use $once{} constraints to size the visual elements relative to the canvas.
Example 32.16. Multi-canvas application library
mainApplication.lzx:
<library>
<tabslider width="$once{canvas.width - 20}" x="10" y="10"
height="$once{canvas.height - 20}" spacing="2" slideduration="300">
<tabelement name="one" text="Tabelement One"/>
<tabelement name="two" text="Tabelement Two"/>
<tabelement name="three" text="Tabelement Three"/>
</tabslider>
</library>
Then create multiple files, one for each canvas area you wish to support.
Example 32.17. Multi-canvas application files
mainApplication640.lzx:
<canvas width="640" height="480"> <include href="mainApplication.lzx"/> </canvas>
mainApplication800.lzx:
<canvas width="800" height="600"> <include href="mainApplication.lzx"/> </canvas>
mainApplication1024.lzx:
<canvas width="1024" height="768"> <include href="mainApplication.lzx"/> </canvas>
mainApplication1280.lzx:
<canvas width="1280" height="1024"> <include href="mainApplication.lzx"/> </canvas>
For real world deployments, you will want to set the size of your canvas to account for screen area occupied by browser controls. Selecting the correct application size requires some javascript to pick the right application when the visitor comes to the page. This example keys off the screen width which will help you determine with high accuracy the height of the client as well.
Example 32.18. Using LzEmbed() to Selecting the Correct Canvas
<script type="text/javascript">
var screenW = screen.width; var screenH =0; switch (true) {
case (screenW >= 1280): screenW = 1280; screenH = 1024; break; case (screenW >= 1024): screenW = 1024; screenH = 768; break; case (screenW >= 800): screenW = 800; screenH = 600; break; default: screenW = 640; screenH = 480; break;
} lzEmbed({url: 'mainApplication'+screenW+'.lzx?lzt=swf', bgcolor: '#394660', width: screenW, height: screenH});
</script>
Communicating with Javascript
It is possible to pass initialization arguments in by adding arguments to the lzEmbed() call in the wrapper HTML or by adding them to the query string when you request your app from the server.
If you define attributes on the canvas with a corresponding name and no value, these attributes will be set when your application starts up.
For example, adding this in the canvas of your app:
<attribute name="foo" />
Allows the value of foo to be passed in via lzEmbed in the HTML, e.g.:
lzEmbed({url: 'grad_test.lzx?lzt=swf&foo=bar', bgcolor: '#ffffff', width: '800', height: '600'});
would cause the foo attribute to contain 'bar' when the application starts up.
Using the browser's "back" button
The LzHistory service allows you to preserve the state of your application, and then use the "back" button of the browser to move among such states.
The default wrapper page enables the back button and browser-to-LZX communication. Once you've got this, you can call the browser javascript method
javascript:lzSetCanvasAttribute(attributeName, value)
to set a canvas attribute and send an event. The following example shows the way the LzHistory service works to move among states. To see the program in action, copy this code to your applications directory.
Example 32.21. Communicating with Back button
<canvas width="1400" height="600" efcdebug="true">
<debug width="500" height="500" fontsize="12" x="450"/>
<class name="blob" extends="drawview" width="100" height="100">
<attribute name="title" type="text"/>
<attribute name="selected" type="boolean" />
<text y="20" x="4" fontsize="16" text="${parent.title}"/>
<handler name="onclick">
this.setAttribute('selected', true);
main.selectBlob(this);
</handler>
<method name="select" args="val">
if (val) {
// draw a border to select
this.lineStyle = 0x000000;
this.lineWidth = 4;
moveTo(0,0);
lineTo(0,100);
lineTo(100,100);
lineTo(100,0);
lineTo(0,0);
stroke();
} else {
clear();
}
</method>
</class>
<view id="main" x="10" y="10" layout="axis: x; spacing: 10">
<attribute name="mystate" type="string" value="START"/>
<blob bgcolor="#ffcccc" id="s1" title="START"/>
<blob bgcolor="#ccccff" id="s2" title="STATE_2"/>
<blob bgcolor="#ccffcc" id="s3" title="STATE_3"/>
<blob bgcolor="#cccccc" id="s4" title="END"/>
<method name="unselectAll">
s1.select(false);
s2.select(false);
s3.select(false);
s4.select(false);
</method>
<method name="selectBlob" args="blob">
// save the old state
LzHistory.next();
setAttribute('mystate', blob.title);
unselectAll();
blob.select(true);
recordState(blob.title);
</method>
<handler name="oninit">
unselectAll();
recordState("START");
selectBlob(s1);
</handler>
<handler name="onmystate">
Debug.write("got onmystate event: ", this.mystate);
gotoState(this.mystate);
</handler>
<method name="recordState" args="newstate">
this.mystate = newstate;
LzHistory.save(this,'mystate', this.mystate);
Debug.write("recordState", newstate)
</method>
<method name="gotoState" args="ns">
unselectAll();
if (ns == "START") {
s1.select(true);
} else if (ns == "STATE_2") {
s2.select(true);
} else if (ns == "STATE_3") {
s3.select(true);
} else if (ns == "END") {
s4.select(true);
}
</method>
</view>
</canvas>
Prev Next

