Although it is possible to build Flex applications to deploy on the desktop (see Chapter 22), the vast majority of Flex applications today are deployed on the Web. To deploy a Flex application on the Web you should embed it in an HTML page. Although this may seem like a fantastically simple task (and it can be), it has larger implications. In this chapter, we’ll look at these implications and the options available to you for embedding a Flex application in HTML and how a Flex application can interact with the web browser environment.
By now, you should be aware that Flex applications get compiled to .swf files. When you deploy a Flex application to the Web, you must place the .swf file for the Flex application on the web server. At a minimum, this one file is always required. However, in almost all cases you will need to provide at least one additional file: an HTML file that embeds the .swf. Although it is possible for users to access an .swf file directly in a web browser, such an approach is inadvisable. Keep in mind that when users access a Flex application in a browser, you will still want the browser to display basic information such as a title, information that only an HTML page can provide. Furthermore, by using an HTML page, it is possible to do much more with a Flex application than if the user was accessing the application’s .swf file directly in the browser. For example, using an HTML page you can utilize JavaScript. And by embedding a Flex application in HTML, you can place the application alongside other non-Flex content. Not only that, but by using JavaScript and HTML, you can detect whether the user even has Flash Player installed. Therefore, embedding Flex applications in HTML is a fundamental skill for creating Flex applications. In the next few sections, we will look at various ways in which you can embed Flex content in HTML pages.
Any technology that writes HTML to a browser can be used interchangeably with HTML files, as we describe in this chapter. For example, you can use the same principles described in this chapter with PHP, .NET, and Ruby to embed a Flex application.
Flex applications are .swf files that must be run by an ActiveX control or a browser plug-in. Therefore, you embed Flex applications in HTML pages in much the same way that you can embed other types of applications or media that requires an ActiveX control or a browser plug-in.
Flash Player runs as an ActiveX control in Internet Explorer and as a plug-in for Firefox and other browsers.
Two tags allow you to embed content in an HTML page: object
and embed
. There is much debate among developers
as to which is better and how they should and shouldn’t be used. For
instance, the embed
tag is supported
in all modern browsers, and that might sound like a good enough reason
to use it exclusively. However, there are drawbacks to using the
embed
tag. For one, the embed
tag
is not standards-compliant; it is not the W3C-recommended way in which
to embed content. This is because the embed
tag is proprietary and is covered by
patents. Furthermore, there is the issue of alternative content.
Although some popular search engines (notably Google) are capable to
some degree of indexing Flash and Flex content, it is still customary
(and recommended) that you provide alternative content whenever you have
a Flex application. This allows you to create content that will be
visible not only to users who do not have Flash Player, but also to
search engines, allowing you greater control over how search engines
index the site. The embed
tag simply
doesn’t allow this to happen. Although the embed
tag does allow alternative content using
a noembed
tag, only users using a
browser that doesn’t support the embed
tag can view the alternative content,
and this doesn’t include search engines. For these reasons, we recommend
that you use only the object
tag,
which is the W3C recommendation. Also, the object
tag allows you to specify alternative
content that is indexable.
Although there is one W3C recommendation for how to embed such
content using an object
tag, as we’ll
see not all browsers are designed to work according to the same
specification. One of the strengths of Flex is that it shields
application developers from the majority of browser inconsistencies.
However, the only time you’ll have to deal with these issues is when you
embed the Flex application in an HTML page.
All browsers are consistent in that when you use the object
tag, you must specify width
and height
attributes, indicating the dimensions
(in pixels) of the content to embed in the page. However, beyond that
they differ on two important points:
How the object
tag
determines which control or plug-in to use
How the object
tag
determines which .swf to load
into the control or plug-in
Microsoft Internet Explorer determines the control to use by way
of an attribute called classid
.
The classid
value for
Flash Player is a long value that you are unlikely to memorize. Instead,
you’ll simply want to copy and paste it from one document to another.
Therefore, an object
tag that will
embed a Flash Player control in a page for Internet Explorer (at 400 by
400 pixels) looks like the following:
<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="400" height="400"> </object>
The classid
value is
case-insensitive.
Internet Explorer relies on a nested param
tag with a name of movie
to specify the .swf that should be loaded into the control.
The following example will load an .swf file called example.swf:
<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="400" height="400"> <param name="movie" value="example.swf"> </object>
You can also specify a codebase
attribute for Internet
Explorer to tell the browser where it can go to download the
control if it’s not already installed. This is generally not advised
because it interferes with alternative content and there are better
ways to allow users to install Flash Player. The HTML templates that
ship with the Flex SDK (and Flex Builder) use the codebase
attribute. However, as you’ll read
later in this chapter, we advise against using the Flex HTML templates
for this and other reasons.
Internet Explorer is alone in its answers to these questions. All
other major browsers take a different approach and have standardized on
specifying the plug-in to use via the MIME type as indicated by the
value of a type attribute. They also have standardized on specifying the
content to load into the plug-in via an attribute called data
.
The following is an example of an object
tag that accomplishes the same thing as
the preceding example, except that it works for all browsers excluding
Internet Explorer:
<object type="application/x-shockwave-flash" data="example.swf" width="400" height="400" />
The obvious question is how can you support all browsers at the
same time if different browsers require different implementations? One
of the preferred answers to this question is to nest the object
tags with the Internet Explorer version
on the outside. Browsers that don’t use the classid
attribute will ignore the outer
object
tag, using only the inner tag.
Internet Explorer has a bug with nested object
tags, but to resolve this you can use
Internet Explorer conditional statements to effectively hide the inner
tag. The result looks like the following:
<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="400" height="400"> <param name="movie" value="example.swf"> <!--[if !IE]>--> <object type="application/x-shockwave-flash" data="example.swf" width="400" height="400" /> <!--<![endif]--> </object>
You can improve this further by adding alternative content, as in the following example:
<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="400" height="400"> <param name="movie" value="example.swf"> <!--[if !IE]>--> <object type="application/x-shockwave-flash" data="example.swf" width="400" height="400"> <!--<![endif]--> <p>Alternative Content</p> <!--[if !IE]>--> </object> <!--<![endif]--> </object>
Any additional parameters that you’d like to pass to the object
tag you should place inside the nested
object
tag but outside the
conditional statements, right next to the alternative content. When
using the object
tag to embed Flex
content, you can specify a lot of different parameters, all of which are
listed at the Adobe web site (http://livedocs.adobe.com/flex/3/html/help.html?content=wrapper_13.html).
You’ll see an example of how to use one such parameter in the next
section.
The Flex HTML templates use an object
tag for Internet Explorer and a
nested embed
tag for all other
browsers. Although that approach does work, it is not ideal because
the embed
tag is a proprietary tag
that is not part of the W3C recommendation for standards.
In earlier chapters, you learned the various ways in which a
Flex application loads data. For example, you learned how to use the
WebService
component to load data
from web services. However, a Flex application can acquire data at
runtime in yet another way: you can pass values to the Flex application
from HTML. Just as web services have their uses and purposes, this
technique of passing values from HTML to Flex has its uses and purposes,
which are generally different from those of web services (or any other
remote procedure call [RPC] techniques). Typically, you will want to
pass only small amounts of data to a Flex application from HTML, and the
data is typically environment-specific. For
example, you may pass values to a Flex application telling it where the
web services can be found on a specific environment (i.e., testing
versus production).
One major advantage to passing data to the Flex application from HTML over other techniques is that the data is available immediately when the application starts.
This technique of passing values to a Flex application from HTML
is sometimes referred to as using flashvars
because the object
tag
parameter used to pass the values to the Flex application is called
flashvars
. Values passed to a Flex
application using the flashvars
parameter must be in URL-encoded name-value pairs delimited by equals
signs and ampersands exactly as they would be in a URL query string. For
example, the following code embeds a Flex .swf file and uses flashvars
to pass in two variables called
variable1
and variable2
:
<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"
width="400" height="400">
<param name="movie" value="example.swf">
<!--[if !IE]>-->
<object type="application/x-shockwave-flash" data="example.swf"
width="400" height="400">
<!--<![endif]-->
<param name="flashvars" value="variable1=a&variable2=b" />
<p>Alternative Content</p>
<!--[if !IE]>-->
</object>
<!--<![endif]-->
</object>
When values are passed to a Flex application via flashvars
, they are available via ActionScript using the parameters
property of the Application
instance. You can access this property from anywhere in a Flex
application using Application.application.parameters
.
The parameters
property is an
associative array where the keys correspond to the names of the
variables passed in through flashvars
.
For example, you could use the following code to output the values passed in via the preceding HTML example:
trace(Application.application.parameters.variable1); trace(Application.application.parameters.variable2);
Flex applications require that the user has Flash Player installed if he is to use the application. Not only do Flex applications require that the user has Flash Player in general, but they specifically require that the user has Flash Player 9 or later. Therefore, it is important that you account for users who might not have Flash Player installed (according to Adobe’s studies, this accounts for just around 1% of users) as well as users who might have Flash Player installed, but don’t have the necessary version (i.e., they need to update their Flash Player to Version 9 or later). Additionally, for users connecting via devices that don’t support Flash Player (e.g., some mobile devices), you can display alternative content.
You can detect Flash Player and/or the Flash Player version in a variety of ways, ranging from client-side JavaScript to server-side scripting to ActionScript. Adobe has a Flash Player Detection Kit (http://www.adobe.com/products/flashplayer/download/detection_kit) that is available as a free download (all the necessary files are also included in the Flex SDK with the HTML templates, as you’ll read in Using the Standard Templates” later in this chapter). The Flash Player Detection Kit is Adobe’s current official solution to Flash Player detection, and it is worth downloading the kit just to read the documentation that is included because it provides a helpful context and a fair amount of useful information. However, plenty of criticisms have been leveled at the Flash Player Detection Kit, most of which are warranted. The key criticisms are as follows:
The kit relies on non-standards-compliant markup code because
it uses both the object
and the
embed
tags.
It requires that you define alternative content twice instead of once, and in two different ways.
It is difficult to customize the code.
There is nothing necessarily wrong with using the Flash Player Detection Kit. However, for the reasons just mentioned, we do not recommend it as the best solution. Instead, we recommend using SWFObject, which we describe in Using SWFObject” later in this chapter.
Although we don’t recommend its use outright, the Flash Player Detection Kit is not without value. It contains one component that highlights an important feature of Flash Player, called Express Install. Express Install is available in Flash Player 6.0.65 and later, and it allows Flash Player to download and install the latest version of itself. That means that if a user has Flash Player 6.0.65 or later installed but she doesn’t have the latest version required by your Flex application, it is possible to allow the user to download and install the latest version from within your site. The user will never have to leave the site, and once the installation is complete, the browser will restart and open to the same page the user was just on (the page with the Flex application).
Technically, Express Install is a feature of Flash Player, and it doesn’t require the Flash Player Detection Kit. However, practically speaking, the detection kit provides an Express Install .swf file that you can use to trigger Express Install if necessary. You’d need the Flash IDE to create a custom Express Install .swf file, and for most purposes the version that is included in the detection kit is all you need.
The general process for using Express Install is as follows:
Use a detection method (client-side, server-side, or Flash-based) to detect whether the user has Flash Player installed. If the user has no version of Flash Player or a version prior to 6.0.65, direct the user to alternative content.
If the user has the version of Flash Player required by your Flex application, simply display the application. However, if the user has a version that is earlier than what your application requires, load the Express Install .swf file into Flash Player. This will automatically prompt the user to download and install the latest version of Flash Player right from within the browser.
Once the installation is complete, the browser will restart and will open to the page that was open prior to installation. This time the detection method will detect that the user has the necessary version of Flash Player.
In the templates directory of the Flex 3 SDK or in the Flash Player Detection Kit, the Express Install .swf is called playerProductInstall.swf.
Flex ships with a variety of standard templates that you can use. The templates are located in the templates directory of the SDK. These templates include the following:
No player detection
Client-side detection
Express Installation
No player detection with history
Client-side detection with history
Express Installation with history
All of these templates use the same JavaScript file and the same markup as the Flash Player Detection Kit, which puts the templates in the same boat with the detection kit as far as the previously mentioned criticisms are concerned. Therefore, we do not recommend using the templates, except perhaps in the early stages of application development, while testing applications locally using Flex Builder.
By default, when you run or debug an application in Flex Builder, you are using the templates.
SWFObject is a method for embedding Flash and Flex content in an HTML page. It uses JavaScript for Flash Player detection and for a variety of other features. SWFObject is the unofficial standard for embedding Flash and Flex content, and it is the method we recommend in this book. SWFObject is easy to use, and it uses standards-compliant markup and unobtrusive JavaScript. You can download SWFObject from http://code.google.com/p/swfobject.
The SWFObject documentation is excellent at explaining both how and why to use SWFObject, and we won’t attempt to repeat too much of that here in this book. However, we’ll give you a brief introduction that will provide you with enough information to get started, and you can consult the documentation for further details.
SWFObject 2.0 (the current version as of this writing) provides two ways for you to embed content: static publishing and dynamic publishing. Static publishing uses markup directly in the HTML, and it uses JavaScript to resolve issues that cannot be dealt with by markup (such as player detection). The biggest advantage of static publishing is that because it doesn’t rely on JavaScript to embed the content, your Flex application will be available to browsers that don’t support JavaScript or that have JavaScript disabled; devices that have poor JavaScript support; and automated tools. Dynamic publishing, on the other hand, uses JavaScript to write the Flex application to the page. The advantage to this is that it sidesteps click-to-activate issues related to the Eolas patent (note that this primarily affected Internet Explorer, and Microsoft has since reversed this change) and it allows for easier integration with scripted applications. Dynamic publishing works only if enough JavaScript support is available. Otherwise, the user will see only alternative content.
The Eolas patent is a patent awarded in 1998 to Eolas Technologies, a U.S. company. The patent ostensibly covers embedding content (such as Flash Player content) in HTML pages. Eolas sued Microsoft for infringement on the patent because Microsoft didn’t license its embedding technology from Eolas.
Clearly, sometimes dynamic publishing is advantageous, and we encourage you to learn more about it by reading the SWFObject documentation. However, for most purposes static publishing is a better option, and it is the option we will look at in more detail in this chapter.
To use static publishing follow these steps:
Place the swfobject.js file in the same directory as your HTML page and .swf file.
Use the nested object
tag
markup discussed earlier in this chapter to embed the Flex
application.
Your HTML page might look like the following:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> <head> <title>Flex Example</title> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> </head> <body> <div> <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="400" height="400"> <param name="movie" value="Example.swf" /> <!--[if !IE]>--> <object type="application/x-shockwave-flash" data="Example.swf" width="400" height="400"> <!--<![endif]--> <p>This site is best viewed as a Flex application, which requires Flash Player 9. For users who prefer not to use Flash Player we have provided a <a href='textVersion.html'>text-only version of the site</a/>.</p> <!--[if !IE]>--> </object> <!--<![endif]--> </object> </div> </body> </html>
Next, you must set an id
attribute for the outer object
tag:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<title>Flex Example</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
</head>
<body>
<div>
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
width="400" height="400" id="flexApplication"
>
<param name="movie" value="Example.swf" />
<!--[if !IE]>-->
<object type="application/x-shockwave-flash" data="Example.swf"
width="400" height="400">
<!--<![endif]-->
<p>This site is best viewed as a Flex application, which requires
Flash Player 9. For users who prefer not to use Flash Player
we have provided a <a href='textVersion.html'>text-only
version of the site</a/>.</p>
<!--[if !IE]>-->
</object>
<!--<![endif]-->
</object>
</div>
</body>
</html>
Add a script
tag to the
head of the document. The script
tag should include the SWFObject JavaScript file, as in the
following code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<title>Flex Example</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<script type="text/javascript" src="swfobject.js"></script>
</head>
<body>
<div>
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
width="400" height="400" id="flexApplication">
<param name="movie" value="Example.swf" />
<!--[if !IE]>-->
<object type="application/x-shockwave-flash" data="Example.swf"
width="400" height="400">
<!--<![endif]-->
<p>This site is best viewed as a Flex application, which requires
Flash Player 9. For users who prefer not to use Flash Player
we have provided a <a href='textVersion.html'>text-only
version of the site</a/>.</p>
<!--[if !IE]>-->
</object>
<!--<![endif]-->
</object>
</div>
</body>
</html>
Add a second script
tag
following the first, and inside this script
tag add a line of code that calls
swfobject.registerObject()
. This
method requires that you specify at least two parameters: the ID of
the outer object
tag and the
minimum required Flash Player version in the form of
major.minor.release.
For example, if your application requires Flash Player 9 and it does
not require any later releases, you can use the string 9.0.0
:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> <head> <title>Flex Example</title> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> <script type="text/javascript" src="swfobject.js"></script> <script type="text/javascript"> swfobject.registerObject("flexApplication", "9.0.0"); </script> </head> <body> <div> <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="400" height="400" id="flexApplication"> <param name="movie" value="Example.swf" /> <!--[if !IE]>--> <object type="application/x-shockwave-flash" data="Example.swf" width="400" height="400"> <!--<![endif]--> <p>This site is best viewed as a Flex application, which requires Flash Player 9. For users who prefer not to use Flash Player we have provided a <a href='textVersion.html'>text-only version of the site</a/>.</p> <!--[if !IE]>--> </object> <!--<![endif]--> </object> </div> </body> </html>
You can also optionally use Express Install with SWFObject. If
you want to use Express Install, you will need to specify a third
parameter for registerObject()
,
indicating the location of the .swf to use. You can use playerProductIinstall.swf from the Flex
SDK, or you can use the expressinstall.swf file that is included
with SWFObject.
It is important to remember that when you embed Flex applications in HTML pages, web browsers will likely cache the .swf files. That is both advantageous and disadvantageous. The upside is that because a Flex application gets cached, users will not have to download the .swf file upon subsequent visits to a site. However, the downside is that when you deploy updates to the Flex application, it is possible that users will still see cached versions instead of the new version.
One of the simplest and most effective ways to deal with this
caching issue is to append a variable to the name of the .swf file that you are embedding and
increment that variable value with each new build. This simple strategy
will ensure that users can use cached versions of the application until
you deploy a new version, and at that point they will be forced to
download the new version when they next visit the site. To add a
variable to the .swf file reference
you should add a question mark (?
)
and a name-value pair following the name of the .swf file. For example, if you normally
reference a file as example.swf
, you
could instead reference the same file as example.swf?build=1
. When you deploy a new
build, you need only update the build variable such that the reference
is now example.swf?build=2
. This way,
you don’t have to change the name of the .swf file (simplifying build scripts and
versioning), but you still can address the caching issue.