You are on page 1of 36

THE AGE OF RIAS, FLASH, FLEX, AND NOW APOLLO MX

DE
VE
FO
LO
RM
ER
PE
R’S LY

Web
JO

Developer’s &
UR
NA
L

WWW.WEBDDJ.COM

VOLUME 5 ISSUE 1 2007


Designer’s Journal
BUILDING ENGAGING APPLICATIONS AND CONTENT WITH ADOBE TECHNOLOGIES

Simplifying AJAX with


the Spry
Framework
Delivering great
experiences while
fitting the workflows
and skill sets of both
designers & developers

Plus:
• Binary Data, ColdFusion & Flex
• Flex 2 Metadata Tags
• Video Rock ’n Roll with Flex 2
Adobe Creative Suite 2.3
®
®
Say hello to the next generation.
It’s found in the world’s most inspirational places. It’s pushing the boundaries

of art direction and design. Introducing Adobe® Creative Suite® 2.3. Today’s

most talented designers and art directors are working smarter and faster

because of it. Just ask the masterminds behind INTERspectacular—they rely

on the Creative Suite to help bring their ideas into the world. See how they do

it at adobe.com/creativemind. It’s everything but the idea. Better by Adobe.™

Luis Blanco and Michael Uman,


INTERspectacular

adobe.com/creativemind
©2006 Adobe Systems Incorporated. All rights reserved. Adobe, the Adobe logo, Creative Suite and Better by Adobe are
either registered trademarks or trademarks of Adobe Systems Incorporated in the United States and/or other countries.
Web Developer’s &
Designer’s Journal
January/February 2007

We Have Entered the Age of

7 RIAs, Flash, Flex…and Now Apollo


by Jeremy Geelan

Binary Data,
ColdFusion & Flex

12 Sending BitmapData to a server and saving it as a JPG file


by Andrew Trice

Simplifying AJAX
with the Spry Framework

16 Delivering great experiences


by Paul Gubbay

Flex 2
Metadata Tags

26 Telling the compiler how to compile


by Rich Tretola

Video Rock ’n Roll


with Flex 2

32 Streaming videos
by Michael Givens

 January/February 2007
$PME'VTJPO)PTUJOH
JTPVS$PNQMFUF'PDVT
108&3'6-)045*/(1-"/4
'3&&42-TFSWFSBDDFTT]'3&&BDDPVOUTFUVQ]6OMJNJUFEFNBJMBDDPVOUT(FOFSPVTEJTLTQBDFEBUBUSBOTGFS
EBZNPOFZCBDLHVBSBOUFF](SFBUWBMVF

3&-*"#-&/&5803,
BWFSBHFVQUJNF]4UBUFPGUIFBSUEBUBDFOUFSXJUIDPNQMFUFSFEVOEBODZJOQPXFS )7"$ mSFTVQQSFTTJPO
CBOEXJEUIBOETFDVSJUZ]OFUXPSLNPOJUPSJOH

'"/5"45*$46110354&37*$&4
TVQQQPSUTFSWJDFT],OPXMFEHFBCMFQIPOFTVQQPSU]8FGPDVTPOZPVSJOEJWJEVBMOFFET

$'%:/".*$4$0.
'PSZFBSTXFIBWFCFFOJOWPMWFEJOUIF$PME'VTJPODPNNVOJUZBOEIBWFDPNFUPLOPXXIBUEFWFMPQFSTBOEQSPKFDUNBOBHFSTMPPLGPS
JOBXFCIPTU5IFDPNCJOBUJPOPGPVSQPXFSGVMIPTUJOHQMBOT SFMJBCMFOFUXPSL BOEGBOUBTUJDTVQQQPSUTFUTVTBQBSUGSPNPUIFSIPTUT
3FBMTFSWJDF3FBMTBUJTGBDUJPO3FBMWBMVF3FBMTVQQPSU3FBM'SFFEPN
from the publisher
Web Developer’s &
Designer’s Journal
Group Publisher Jeremy Geelan
We Have Entered the Age of
RIAs, Flash, Flex…and Now Apollo
Art Director Louis F. Cuffari

Editorial Board
Aral Balkan
Erik Bianchi
Craig Goodman
Andrew Powell
Jim Phelan
Andrew Phelps
Darron J. Schall by Jeremy Geelan

a
Stephanie Sullivan
Jeff Tapper
Jesse Randall Warden
lready, even in pre-release, or so during which the user experiences
Editorial
Adobe’s Spry seemed to catch the that drove applications on the web were
Editor
Nancy Valentine, 201 802-3044 imagination of many Web profes- primitive at best; when, as Trice expresses
nancy@sys-con.com sionals wrestling with how to integrate new it, “forms and grids trapped in the browser’s
To submit a proposal for an article, go to AJAX frameworks into existing workflows. content-centric chrome ruled the earth.”
http://grids.sys-con.com/proposal. Created with designers in mind, Spry uses The thing is, as Trice notes, grids are not
Subscriptions
regular HTML tags, CSS, and JavaScript, and how users think; grids are how program-
E-mail: subscribe@sys-con.com is easy to use – boiling down to a couple mers think. And the problem is... most of
U.S. Toll Free: 888 303-5282
of JavaScript libraries that you include in the users aren’t programmers.
International: 201 802-3012
Fax: 201 782-9600 your Web page in order to be in a position ”In the past,” Trice says, “it was easy to
Cover Price U.S. $5.99 to add dynamic interactive content to your claim that the platform was simply too
U.S. $29.99 (12 issues/1 year)
Canada/Mexico: $49.99/year
site. primitive to work any other way. That how-
International: $59.99/year What spurs me to mention Spry is the ever doesn’t fly anymore. Today with RIAs
Credit Card, U.S. Banks or Money Orders
approach of AJAXWorld Conference & Expo, you now not have only a vast array of rich
Back Issues: $12/each
of which Adobe is a Platinum sponsor. controls but access to a complete robust
Editorial and Advertising Offices There is no doubt that it will be the most vector graphics drawing API. Thanks to
Postmaster: Send all address changes to:
SYS-CON Media intense three-day conference anywhere all of this, if you can imagine an interface
577 Chestnut Ridge Rd. on the East coast this year, devoted to or a way to present data and information
Woodcliff Lake, NJ 07677
the issues most preoccupying those who to the user, you can make it come alive.
Worldwide Newsstand Distribution design, build, and deploy Web sites and More importantly, these RIAs are no longer
Curtis Circulation Company, New Milford, NJ Web-based applications. trapped inside the browser’s chrome and
List Rental Information There are several Flex sessions at the the vision of the web driving the applica-
Kevin Collopy: 845 731-2684, Conference, including one by Kevin Hoyt tions that run the business of the world is
kevin.collopy@edithroman.com,
Frank Cipolla: 845 731-3832,
– known to many readers of WebDDJ from coming alive.”
frank.cipolla@epostdirect.com his regular appearances at various user Many other sessions at AJAXWorld Jeremy Geelan is Sr. Vice-
group forums and conferences throughout are devoted to demonstrating how to President, Editorial & Events
Promotional Reprints
Megan Mussa, 201 802-3024 the United States. Kevin will be talking turn designs into reality and how to build of SYS-CON Media. He is
megan@sys-con.com about using Flex and AJAX “to bring the out incredible user experiences for the Conference Chair of the
Copyright © 2006
‘sexy’ back to the enterprise,” as he puts it. Web. Enterprise application developers AJAXWorld Conference
by SYS-CON Publications, Inc. All rights reserved. No part of this His session will provide an interactive deep are embracing AJAX – and increasingly, & Expo series and of the
publication may be reproduced or transmitted in any form or by
dive on how to integrate Flex, AJAX and Flex – to bring the same next-generation “Real-World Flex” One-Day
any means, electronic or mechanical, including photocopy or any in-
formation storage and retrieval system, without written permission. Apollo to bring the ‘sexy’ elements of Web- functionality to the enterprise. They are Seminar series. He is execu-
based RIAs to the enterprise. designing enterprise applications that tive producer and presenter
Web Developer’s & Designer’s Journal (ISSN#1546-2242)
is published monthly (12 times a year) by As for Apollo, that will naturally be perform like desktop software but have of “Power Panels with Jeremy
SYS-CON Publications, Inc., 577 Chestnut Ridge Road, making an appearance at AJAXWorld 2007 the connectivity of the Web and integrate Geelan” on SYS-CON.TV,
Woodcliff Lake, NJ 07677.
East, too. In a session called “Denting the with enterprise systems. Adobe’s prod- and is actively helping build
SYS-CON Media and SYS-CON Publications, Inc., reserve the right to re- Browser’s Chrome: Intense Experiences, uct road map is guiding developers and out the AJAXWorld brand
vise, republish, and authorize its readers to use the articles submitted for Advanced RIA Development and Apollo,” designers into exactly the right part of as well as developing entirely
publication. Adobe and Adobe products are either registered trademark
or trademarks of Adobe Systems Incorporated in the United States and/or Cynergy’s Andrew Trice, an Enterprise the technology landscape at exactly the new Conferences and One-
other countries. SYS-CON Publications, Inc., is independent of Adobe. All Applications Consultant for Cynergy right time. Day Seminars for SYS-CON
brand and product names used on these pages are trade names, service
marks or trademarks of their respective companies.
Systems, will remind us of the dark decade Drive safely, and enjoy! Media & Events.

January/February 2007 
Scary Question.
Exactly who is developing your next app?

Contact Us

Address:
555 Not My Home St.
Big City, CO 12345
Your App Starts Here.
We are the leaders in RIA development services.

INCREDIBLE APPLICATIONS

PASSIONATE USERS

PROVEN SUCCESS

Unlock your potential


with the help of industry leaders in
Rich Internet Application development.
10 Years. 1400+ Customers.
Your app starts here.

CYNERGYSYSTEMS.COM
webddj editorial board

Aral Balkan Andrew Phelps


Aral Balkan is founder and managing director of Andrew M. Phelps is in the Information Technology
Ariaware, a London-based company offering products Department at the Rochester Institute of Technology in
like Ariaware Optimizer and the open-source Ariaware Rochester, NY (http://andysgi.rit.edu/).
RIA Platform (ARP 2.0) for Flash developers. Ariaware
also offers RIA development process and usability Darron J. Schall
consulting and development services. Aral holds an Darron J. Schall has been programming long before
MA in Film and Electronic Media, is a Macromedia he could drive. In school he studied programming
Certified Instructor and is celebrating his 20th year as languages, ranging from Basic to Pascal to C++ and
a programmer (he’s only 27!). His passions include soft- eventually moving into Java and C# throughout college.
ware architecture and Human-Computer Interaction Somewhere in the middle he got hooked on Flash 5 and
- in other words, building solid, usable applications. it’s been a crazy love affair ever since. Darron is an inde-
He’s co-author of “Flash MX Most Wanted Components” pendent consultant specializing in RIA development.
and “Flash 3D Cheats Most Wanted,” as well as author He maintains a Flash Platform related weblog (www.
and editor of numerous articles for Adobe Developer darronschall.com) and is an active voice in the Flash and
Center and Ultrashock.com. Flex communities.

Erik Bianchi Stephanie Sullivan


Erik Bianchi is a software engineer with more than Stephanie Sullivan is a Web developer, partner at
five years of experience developing Flash-based RIAs CommunityMX (www.communitymx.com), owner of
and enterprise-wide applications for Fortune 50 and VioletSky Design (www.violetsky.net), and contributing
500 companies. In his spare time he enjoys building author of Dreamweaver MX 2004 Magic.
Flash-based games, writing or tech editing Flash-related
books, and when burned out on code, playing video Jeff Tapper
games on his PC/console systems. You can get more Jeff Tapper, co-founder of Tapper, Nimer and
info about Erik and his latest projects on his blog at Associates, has been developing Internet-based appli-
www.erikbianchi.com. cations since 1995, for a myriad of clients including
Toys R Us, IBM, Allaire, Dow Jones, American Express,
Craig Goodman M&T Bank, Verizon, Allied Office Supplies, and many
Craig Goodman is the executive editor of Adobe’s others. As an Instructor, he is certified to teach all
Developer Center. He and his team publish the tutori- of Adobe’s courses on Flex, ColdFusion and Flash
als and articles in the area. Craig joined Macromedia development. He has worked as author and technical
in 1995 and his past roles include managing web sup- editor for several books on technologies including
port and supervising product technical support for Flex, Flash and ColdFusion, such as “Object Oriented
Macromedia Flash. Programming with ActionScript 2.0”, and “Flex 2
Training from the Source.”
Jim Phelan
Jim Phelan is vice president of development for Jesse Randall Warden
Stream57, a New York City based firm specializing in Jesse R. Warden is a senior Flash developer at
communication solution development for the enter- Surgical Information Systems, an operating room
prise. Jim’s expertise in creating solutions for consolida- software company, where he currently uses Flash
tion and collateralization of business communications MX, Flash Remoting, .NET, and Oracle to create
has allowed his team to create applications for the man- next-generation rich Internet applications for the
agement and delivery of live and on demand rich media OR. He contributed four chapters to the Flash
content. Jim is a strong proponent of the Adobe Flash Communication Server MX Bible and has written
Platform and is a member of the editorial board of MX articles for various publications, including one for
Developer’s Journal. Macromedia for a DRK.

10 January/February 2007
bitmap data

Binary Data,
ColdFusion & Flex
Sending BitmapData to a server
and saving it as a JPG file
by Andrew Trice

s everal months ago I posted


some articles on my blog about
Flex 2 components and access-
ing/modifying their BitmapData.
In one example, I sent the BitmapData
to the server and saved it as a JPG file,
to convert binary image data into a com-
pressed JPG ByteArray that can be sent to
the server. This is a good practice for two
reasons:
• The data is compressed, which helps
decrease latency when communicating
remember that your Flex application will
have a slight pause while the encoding is
being processed:

var bd : BitmapData = getUIComponent-

BitmapData( paintCanvas );

and I’ve been asked numerous times with the server. var encoder : JPEGEncoder = new

since… “How did you do that?” It’s sur- • The data is encoded into the format JPEGEncoder(75);

prisingly easy to do once you understand that you want to save, so no additional var data : ByteArray = encoder.encode(

the concepts involved. There are four processing/conversion is required on bd );

ways to get binary data from the Flex the server. You simply need to save the
application back to your server: AMF3 data either in your file system or in a Once you have the data converted
(RemoteObject), Web Services, HTTP binary object in your database. to a JPG ByteArray, you’re ready to push
Services, or through a Socket connection. it to the server and save it. The fastest
In this article I’ll cover the first three top- Here’s how you get data from a Flex and easiest way to do that is to use a
ics as they pertain to Flex 2; Socket con- component into a JPG ByteArray: First, RemoteObject method and serialize
nectivity could take an article all by itself. you’ll have to retrieve the BitmapData the data using AMF3. This example
Binary data can’t be pushed to the from your Flex component. You can pass shows you a method in a ColdFusion
server in its native format using a Web any Flex component into the following Component (CFC) that will let you send
Service or a standard HTTP POST method. function to retrieve its BitmapData: the data and save it to the local file sys-
To save the data using Web Services or tem:
HTTP POST, you must first convert the private function getUIComponentBit-

binary data to a text string using Base64- mapData( target : UIComponent ) : <cfcomponent name=”ImageSave”

encoding. On the other hand, AMF3 BitmapData displayname=”ImageSave”

(RemoteObject method) lets you send { output=”false”>

the binary data to the server in its native var bd : BitmapData = new BitmapData( <cffunction name=”ROsave”

binary form. One thing to keep in mind target.width, target.height ); access=”remote” output=”false”

with Base64-encoding is that the encod- var m : Matrix = new Matrix(); returntype=”void”>

ing process will actually increase the size bd.draw( target, m ); <cfargument name=”data”

of the data that’s being sent across the return bd; type=”binary” required=”true” />

wire. } <cffile action=”write” file=”c:\

Regardless of how you’re sending the temp\ro_data.jpg”

data to the server, it’s a good practice to Once you have the BitmapData, output=”#arguments.data#” />

compress the data client side whenever you’ll have to create an instance of </cffunction>

possible. I’ve used the JPGEncoder class the JPGEncoder class and encode the </cfcomponent>

at http://code.google.com/p/as3corelib BitmapData. (This example uses the


with great success. You can use this class JPG quality of 75.) It’s also important to You can see that the code is actually

12 January/February 2007
SYS-CON Media
very simple. The CFC’s ROsave (remote object save) required=”true” />
CEO
method is expecting binary data as a parameter. When <cffile action=”write” file=”c:\temp\ws_data.jpg” Fuat Kircaali, 201 802-3001
fuat@sys-con.com
executed, the data is written to the file system using output=”#ToBinary(arguments.data)#” />

the <CFFILE /> “write” method. </cffunction> President & COO


Carmen Gonzalez, 201 802-3021
On the Flex side, we’ll have to instantiate a mx: </cfcomponent> carmen@sys-con.com
RemoteObject:
Sr. Vice-President, Editorial & Events
You can see that the code for the Web Service Jeremy Geelan, 201 802-3051
jeremy@sys-con.com
<mx:RemoteObject method is very similar to the previous example. The
id=”ro” only difference is that the toBinary method is being Advertising
Vice President, Sales & Marketing
showBusyCursor=”true” used to convert the data from a Base64-encoded string Miles Silverman , 201 802-3029
destination=”ColdFusion” into binary data. The CFC’s WSsave (Web Service save) miles@sys-con.com

source=”BinaryData.cf.ImageSave”> method is expecting a Base64-encoded string as a Advertising Sales Director


Megan Mussa, 201 802-3023
parameter. When executed, the data is also written to megan@sys-con.com
<mx:method name=”ROsave” the file system using the <CFFILE /> “write” method.
Associate Sales Managers
result=”onResult(‘Data Saved via mx:RemoteObject’)” In Flex, we need an instance of a mx:WebService to Corinna Melcon, 201 802-3026
fault=”onFault(event)” /> save the data: corinna@sys-con.com

</mx:RemoteObject> Events Manager


Lauren Orsi, 201 802-3022
<mx:WebService
lauren@sys-con.com
To save the data, we’ll invoke the ROsave method id=”ws”
Production
and pass the JPG-encoded ByteArray as a parameter: showBusyCursor=”true” Lead Designer
wsdl=”/BinaryData/cf/ImageSave.cfc?wsdl”> Louis F. Cuffari, 201 802-3035
louis@sys-con.com
var bd : BitmapData = getUIComponentBitmapData(
Art Director
paintCanvas ); <mx:operation name=”WSsave”
Alex Botero, 201 802-3031
var encoder : JPEGEncoder = new JPEGEncoder(75); result=”onResult(‘Data Saved via mx:WebService’)” alex@sys-con.com

var data : ByteArray = encoder.encode( bd ); fault=”onFault(event)” /> Associate Art Directors


</mx:WebService> Abraham Addo, 201 802-3037
abraham@sys-con.com
ro.ROsave( data ); Tami Beatty, 201 802-3038
tami@sys-con.com
To save the data, we first need to Base64-encode it.
If you aren’t using remoting, you can save the data The following function will take care of that for us: SYS-CON.COM
Consultant, Information Systems
using Web Services or HTTP services. Most seasoned Robert Diamond, 201 802-3051
ColdFusion developers might stop me here and say… private function base64Encode( data : ByteArray ) robert@sys-con.com

“If you’re using CFCs as Web Services, why wouldn’t you : String Web Designers
Stephen Kilmurray, 201 802-3053
just use them as RemoteObject methods since they are {
stephen@sys-con.com
faster?” My response is this: This is just an example. You var encoder : Base64Encoder = new Base64Encoder(); Richard Walter, 201 802-3042
richard@sys-con.com
may be able to take this method and apply it to other encoder.encodeBytes( data );

technologies where it may be applicable (.NET, Java, return encoder.flush(); Accounting


Financial Analyst
PHP, etc.). } Joan LaRose, 201 802-3081
joan@sys-con.com

<cfcomponent name=”ImageSave” We’ll then invoke the WSsave method and pass the Accounts Payable
Betty White, 201 802-3002
displayname=”ImageSave” output=”false”> Base64-encoded ByteArray as a parameter: betty@sys-con.com
<cffunction name=”WSsave” access=”remote”
Customer Relations
output=”false” returntype=”void”> var bd : BitmapData = getUIComponentBitmapData( Circulation Service Coordinator
Edna Earle Russell, 201 802 -3081
<cfargument name=”data” type=”string” paintCanvas );
edna@sys-con.com

January/February 2007 13
var encoder : JPEGEncoder = new of the HTTPService.send method (note
JPEGEncoder(75); “hs” is the id of the HTTPService instance):
var data : ByteArray = encoder.encode(

bd ); var bd : BitmapData = getUIComponent-

ws.WSsave( base64Encode( data ) ); BitmapData( paintCanvas );

If you want to save the binary var encoder : JPEGEncoder = new

data without using RemoteObjects or JPEGEncoder(75);

Web Services, you can always use a var data : ByteArray = encoder.encode(

standard HTTP post method. In Flex, bd );

you’ll have to create an instance of an var params : Object = { data : bas-

HTTPService object, with the method e64Encode( data ) };

set to “POST”: hs.send( params );

<mx:HTTPService …and that is how you save binary


id=”hs” image data using RemoteObjects, Web
showBusyCursor=”true” Services, or HTTPServices. This doesn’t
useProxy=”false” just apply to images. This applies to any
method=”POST” kind of binary data; the only difference
resultFormat=”text” is that the image data first gets encoded
url=”/BinaryData/cf/HTTPImageSave. to a JPG ByteArray. The AS3 corelib
cfm” project on Adobe Labs/Google Code
result=”onResult(‘Data Saved via mx: also includes class libraries that enable
HTTPService’)” you to save data as PNG images instead
fault=”onFault(event)” /> of JPG images, so JPG isn’t your only

“Regardless The file HTTPImageSave.cfm is actu-


option.
A few things to keep in mind for

of how you’re
ally very simple. The save occurs with real-world applications... It’s best prac-
only two lines of code: tice to use <CFFILE /> in a <CFTRY/>
statement to catch any file system
sending the data <cfparam name=”data” type=”string” errors that may occur (not enough
space, permissions, etc.). It’s also
to the server,
default=””>

<cffile action=”write” file=”c:\temp\ best practice to use <CFLOCK /> with


http_data.jpg” output=”#ToBinary( data <CFFILE /> to prevent any errors due to
it’s a good practice )#” /> data synchronization, threading access,
or deadlock scenarios.

to compress the You’ll notice in this case that the


data is also being written to the file
A working example and the source
code from this article can be viewed

data client side system using the toBinary method (to


convert the Base64-encoded string back
online at http://www.cynergysystems.
com/blogs/blogs/andrew.trice/bina-

whenever into binary data). When invoking the


HTTPService, you’ll have to create an
ry_data_example/ or downloaded from
http://www.cynergysystems.com/blogs/

possible.” object containing the parameters for the


HTTPService and send it as the parameter
blogs/andrew.trice/binary_data_exam-
ple/BinaryData.zip.

14 January/February 2007
Simplifying AJAX
with the Spry Framework
Delivering great experiences while fitting
the workflows and skill sets of both

o
designers & developers
by Paul Gubbay

ver the past year the


Dreamweaver product design
and development team have
been out on the road talk-
ing to Web designers and
developers (Web pros)
about the prospect of
using AJAX to build
more engaging and
interactive Web pages
and applications. While
many Web pros were
excited by what could be
built, we also heard big
concerns both about how
to get started and how to
integrate new AJAX frame-
works into existing workflows.

16 January/February 2007
January/February 2007 17
• Takeaway: The technology is a means to an end. What resonates with Web pros Next-Generation Web UI OK
is the ability to offer their customers richer and more engaging experiences. Top So what do we mean by more engaging and interactive Web pages? To
of mind is the ability to incorporate new technology into existing workflows. get a first-hand experience you can check out some of the sample pages
We took this to heart and set out to create a framework that leverages that have been built using Spry at Adobe Labs http://labs.adobe.com/tech-
AJAX to deliver great experiences while fitting the workflows and skill nologies/spry/demos/index.html.
sets of both designers and developers. The Spry framework for AJAX was In the course of this article we’re going to look at one page in detail and
developed with the following objectives: explore the code that was used to generate it.
• Keep it open: Spry works with all HTML editors, including Dreamweaver. Some of the characteristics of Spry-enabled Web pages include:
Anyone can download it off Adobe Labs to start building high-performing • Single page experience.
interactive Web pages and applications. No proprietary tags or server-side • Seamless interactivity/more responsive.
code needed. • Use of transitions and effects.
• Make it easy to use: Spry uses the same technologies that you already • More sophisticated UI elements.
know to build Web pages (HTML, CSS, and JavaScript). Include a couple
of JavaScript libraries with your page and you are ready to go. Create and The Spry Framework
style dynamic regions and interactive widgets using the same techniques Spry is a client-side framework in the form of JavaScript libraries that you can
as any other HTML elements on your page. easily add to your new and existing Web pages. Spry is server- and tool-agnostic.
• Enable innovation: At the end of the day Spry is about delivering richer You can use it with Dreamweaver or your HTML editor of choice. Just a few lines of
experiences for your customers. Spry provides a lightweight yet powerful code can produce powerful results. More importantly, it should all look familiar. You
model for adding data, interactivity, and rich UI widgets into your Web should be able to jump in and be productive right away. Spry does the heavy lifting.
pages while putting you in complete control of the design. The Spry JavaScript libraries host three modules (see Figure 2).

Who Is It For? Spry Data


Spry was built for both Web designers and developers. Before we built Data is accessed and displayed using Spry Data Sets and Regions. The Spry
the framework we created a profile of the typical user for Spry. This profile Data Set is a JavaScript object that is responsible for loading and managing
helped us define our guiding principles. (e.g., sort, filter) data. The Data Set base class is architected so that multiple
• Works in Web production. Focused on the Web UI and x(HTML) production. flavors can be built to access data from different sources (see Figure 3).
• Expert with x(HTML) and CSS.
• Familiar with JavaScript and the DOM. Spry Regions
• Cares about the quality of the code. A Spry dynamic Region is an area on a Web page that’s bound to a Data
• Wants to create next-generation Web pages. Set. When a Data Set is modified (e.g., loading data off the server, filtering,
sorting), the Spry Region is updated to reflect the new data. A Spry Region
Guiding Principles can be created for any HTML block element such as a <div> or a <p> tag.
• Keep the framework familiar, lightweight and transparent.
• Keep the “framework” to a minimum (page-centric).
• Don’t obscure the code.
• Make it feel like a natural extension to HTML.
• Integrate well with other technologies.

Enable a better designer-developer workflow


• Promote separation of design from data/content.
• Support “design-time XML.”
• A framework easily leveraged within design-time tools If we take a look at our example we can see that the Products table and
Product image are contained within Spry Regions that are bound to a Spry
XML Data Set. When the data changes within the Data Set, both regions
Figure 1

automatically update themselves to reflect the new data.

Loading Data
The Spry Data Set is responsible for loading and processing data behind
the scenes (see Figure 4). XML is frequently used to transfer data from the
server to the client. The XML Data Set in Spry can be used to retrieve this
data through the browser via the XMLHTTPRequest object. The XML can
be contained in a file or returned from a server-side function call (e.g., PHP,
ColdFusion, ASP).
Once the XML data is retrieved it’s flattened into a standard record/field
format to make it easier for users to bind the data to Spry Regions in the
Web page. Spry uses XPath, a W3C standard for describing a set of nodes in
XML, to identify the nodes(s) that represent a record of data.

18 January/February 2007
In Figure 5 you can see a sample XML file (products.xml) that represents • Spry Region Declaration: Defines an HTML element as a Spry region.
the products in our table. Using XPath (products/product) we identify the • Data Set Binding: Binds a Spry Region to a Data Set.
node(s) in the XML file that represent the records of data for our Data Set. • Spry Attributes: Specialized attributes that provide additional functional-
Finally, we can see the records and fields in the Spry Data Set once the con- ity such as sorting.
version is complete. • Spry Data Bindings: Bindings to fields located in the Data Set.
• Repeat Region Declaration: Repeats a Spry Region once for each record
Data Set Declaration in the Data Set.
Spry Data Sets are added to your page in two steps. First, you must
include the appropriate JavaScript libraries: Assuming that we’re using the XML sample from our previous example
this code snippet creates the following HTML:

Second, create an instance of the Data Set by passing in the location to


the XML data and defining the repeating node that represents a record of
the data. This code is added to the head of the document.

• Variable reference: Name of the Data Set. Referenced through data bind-
ings or JavaScript.
• Object Instance: Creates an instance of the Data Set object using the
“new” keyword.
• XML Data: Pointer to the XML file or server-side function that returns
XML.
• XPath: Pointer to the node in the XML file that represents a record of the data. Master/Detail Data Sets
The Spry framework supports the concept of Master/Detail Data Sets.
Displaying Data This implies that the selected record in a Master Data Set drives the contents
Data is displayed on the Web page using Spry Regions that are loaded of the Detail Data Set. There are many ways to create this relationship using
with live data when the Web page is displayed in the browser. Creating the Spry. In our example the Master Data Set and the Detail Data Set retrieves
bindings from the Data Set to the Spry Regions is easily accomplished by data from different sections of the same XML file. Each time a new record is
attaching Spry attributes to your standard HTML tags. selected in the Master Data Set, the Detail Data Set retrieves a subset of the
In the following example we can see how the Spry Region for the data.
Products table is built: The Master Data Set is used to retrieve the products for the Products
table. The Detail Data Set is used to retrieve the product features once a spe-
cific product is selected in the Product table.

Detail Data Set Declaration


The Detail Data Set and its relationship to the Master Data Set can be set
up easily using one additional line of JavaScript:

Note that the main difference in the Detail Data Set declaration is the
XPath. This XPath includes a filter expression and uses a Spry Token. The filter
expression limits the nodes that will be returned for the dsProductFeatures
Detail Data Set. The Spry token represents the “name” field for the current
record in the dsProducts Master Data Set.
In effect the declaration states that the dsProductFeatures Detail Data
Set will fetch its data based on the value of the “name” field in the current

January/February 2007 19
Spry Widgets
Figure 2

Spry widgets are UI elements that make it easier for your users to interact
with the content on the page. The current set of widgets (so far) includes:
• Accordion
• Menu Bar
• Collapsible Panel
• Tabbed Panels
• Text Field
• Text Area
• Checkbox & Checkbox Group
• Select list
Figure 3

The Widget philosophy follows the Spry guiding principles:


• Widgets must be easy to modify (re-style).
• Code must be easy to understand.
• HTML-centric markup.
• No custom tags.
• No programmatic injection of markup.
• Self-contained (limit dependencies on additional libraries).

Anatomy of a Widget
Each widget is broken down into three modules as in Figure 8.
record of the dsProducts Master Data Set (see Figure 6). Every time the user
selects a new record in the Master Data Set, this Detail Data Set will auto- Widget Structure
matically update. In our example we use an Accordion widget to display additional infor-
mation about the selected product in the Products table. The structure of
Master/Detail Regions the widget is defined by the HTML code.
In Figure 7 the dsProductFeatures Detail Data Set is used to display
the features of a selected product in the Accordion widget. When the user
chooses a new product in the Product table, the features will change in the
Accordion without needing a page refresh.
Figure 4

As you can see, the composition of the widget is quite easy to under-
stand for anybody familiar with HTML. If you want to add or delete a panel,
you can simply add or delete the appropriate HTML container in your code.

Widget Behavior
The functionality for the Accordion widget is built into a JavaScript file
that understands the HTML structure for the widget. This approach makes it
easy for users to modify the look-and-feel of the widget without having to
worry about its functionality. As long as the HTML structure is correct, the
widget will function as expected. The JavaScript is included using two lines
of code.
The first line simply links in the JavaScript file that contains the
Accordion functionality.

20 January/February 2007
The second line creates an instance of the Accordion JavaScript object
and links it to the HTML by passing in the user-defined ID (Acc1).

Note that the JavaScript to create an instance of a Spry widget must be


included under your markup at the bottom of the Web page.

Widget Styling
The Accordion widget is styled just as you would any other HTML ele-
ment on your page using CSS. The CSS file (SpryAccordion.css) is included
using the following line of code:

In the HTML example in Figure 8 you will notice that there are CSS
classes applied to each of the relevant block-level elements (Accordion,
AccordionPanel, AccordionPanelTab, and AccordionPanelContent). The CSS
rules for these classes are defined in the SpryAccordion.css file. They can be Paul Gubbay is a director of engineering at Macrome-
changed at will by the Web developer or designer. dia. Previously, Paul held the role of CEO at CyberSage
Software, where he spent several years building the vision
Spry Effects and infrastructure of the company. Under Paul’s guid-
Spry effects are visual enhancements that you can apply to almost any element ance, CyberSage focused on emerging technologies such as
on an HTML page. For example, an effect might highlight information, create ani- XML, Java, and Macromedia Flash to deliver leading edge
mated transitions, or visually alter a page element for a certain period of time. Effects product offerings.
are a simple but elegant way of enhancing the look-and-feel of your Web site. pgubbay@adobe.com
Figure 5

January/February 2007 21
The current set of effects (so far) includes:
• Appear/Fade
• Highlight
• Blind Up/Blind Down
• Slide Up/Slide Down
• Grow/Shrink
• Shake
• Squish

The Effect philosophy follows the Spry guiding principles:


• Simple JS Syntax.
• Single JS include.
• Compatible with other effect libs/frameworks.
• Focus on key interaction/UE behaviors.

Implementing an Effect
Spry Effects are added to your page in two steps. First, you must include

“Our goal in putting the appropriate JavaScript library:

Spry on Adobe Labs


was to make it an Second, add an event handler to a supported element (e.g., <a> tag).

open technology that Note: Supported elements differ by effect – please refer to the Spry API docs.

could be driven by
customer feedback”
Figure 6

22 January/February 2007
For each effect, you must set the target element to create your own variations. This is done by using the Cluster
which you want to apply the effect. The element parameter effect that acts like a container for multiple core effects.
can be either a string containing the id of the element or a Like a regular effect, the Cluster effect has a start() function.
JavaScript DOM element object. In the example above the But unlike regular effects, Cluster provides the methods
AppearFade effect will run on the “target” element when the addNextEffect() and addParallelEffect(). These functions let
user clicks on the <a> link. If the target element is a <div you chain effects together to create new variations.
id=”products”> tag, you would pass in “products” as the tar- Clustered effects are a flexible mechanism for creating
get parameter. new effect variations (see Figure 9). However, they require
some JavaScript programming knowledge. Please refer to
Effect Composition the Spry API docs for more information.
Spry effects are created by combining core effects. The
core effects include: What’s Next for Spry?
• Move Our goal in putting Spry on Adobe Labs was to make it
• MoveSlide an open technology that could be driven by customer feed-
• Size back. This method has produced great results for our engi-
• Opacity neering team and our customers. We continue to use your
• Color feedback on the forums to help guide Spry’s future direc-
tion. Spry is currently in beta with official release scheduled
The combined effects of the Spry framework include: for early spring, 2007. This new release will include support
• Highlight for JSON and nested Data Sets.
• Grow/Shrink Besides the official release of Spry on Adobe Labs, we’ll
• Shake be shipping a new version of Dreamweaver with support for
• Squish Spry Data Sets, Widgets, and Effects.
Spry is a free download and can be accessed on Adobe
Spry supports the ability to cluster effects together to Labs using http://labs.adobe.com/technologies/spry/.
Figure 7

Figure 9
Figure 8

January/February 2007 23
.FFU3PCFSU
"CVTJOFTTFYFDVUJWFBUBQPQVMBSTPDJBMNFEJBTJUF

$IBMMFOHFT
t &ODPVOUFSJOHQPPSWJEFPRVBMJUZEVFUPFYQPOFOUJBMHSPXUIJOUSBöD

t *ODSFBTJOHCBOEXJEUIDPTUTEVFUPHSPXJOHBVEJFODFTJ[F

t &YQFSJFODJOHDPNQBUJCJMJUZJTTVFTEVFUPVTFSHFOFSBUFEWJEFP
BSSJWJOHJONVMUJQMFGPSNBUT

4PMVUJPOT
t 7JUBM4USFBN4USFBNJOH4FSWJDFTo*NQSPWFERVBMJUZPGFOEVTFSWJEFP
FYQFSJFODFVTJOHBTDBMBCMFBOEHMPCBMDPOUFOUEFMJWFSZOFUXPSL
t 7JUBM4USFBN"EWFSUJTJOH4FSWJDFTo5SBOTGPSNFEUIFEFMJWFSZPG
EJHJUBMNFEJBGSPNBDPTUDFOUFSJOUPBQSPmUDFOUFS
t 7JUBM4USFBN5SBOTDPEJOH4FSWJDFTo"VUPNBUJDBMMZDPOWFSUFEBMM
VTFSHFOFSBUFEDPOUFOUJOUPUIFMFBEJOHTUSFBNJOHNFEJBGPSNBU

1SPWJEJOH&OEUP&OE4PMVUJPOTGPS:PVS#VTJOFTT
7JUBM4USFBNJTNPSFUIBOBSJDINFEJBEFMJWFSZDPNQBOZ8FBSFZPVS
QSPGFTTJPOBMQBSUOFSQSPWJEJOHTPMVUJPOTUIBUNFFUZPVSVOJRVFCVTJOFTT
DIBMMFOHFT5PMFBSONPSFBCPVU7JUBM4USFBNTPMVUJPOT DBMM
PSWJTJUXXXWJUBMTUSFBNDPNHPTPMVUJPOT
ª7JUBM4USFBN *OD"MMSJHIUTSFTFSWFE
book excerpt

Flex 2
Metadata Tags
Telling the compiler how to compile
by Rich Tretola

m ost Flex developers


have seen and used the
[Bindable] tag but not
many know what this
tag does or even what it is. [Bindable]
is what is known as a metadata tag.
UIComponent”)]

public var arrayOfUIComponents:

Array;

[Bindable]
The Bindable metadata tag is one of
[DefaultProperty]
The DefaultProperty metadata tag is
used to set a single property as a default
property of a class. This allows the prop-
erty to be set within a container tag with-
out needing to define the property name.
Metadata tags are special tags that the most used metadata tags because A simple example of this would be a cus-
are inserted in your source code that it allows for easy data synchronization tom Button class. Listing 3 shows a simple
give the compiler information on how within the components of your appli- Button class that has the label property
to compile the application. These tags cation. Bindable can be used to bind set as the DefaultProperty. Listing 4
aren’t actually compiled into the gener- simple data, classes, complex data, and shows how the label is defined as a string
ated SWF file but provide instructions functions. To bind a simple piece of data, within the custom Button container tags.
on how the compiler should create the you must simply define the data with
SWF. There are 12 documented metadata the metadata tag included, as shown in [Embed]
tags. This article will offer definitions of Listing 1. Figure 1 shows the results of The Embed metadata tag is used
Rich Tretola is a senior these metadata tags and give examples Listing 1 to import images into your application.
software developer at Herff of their use. By the end of this article you Bindable also allows binding to events. There are two ways to use Embed. You can
Jones, Inc., specializing in will understand when and where to use Listing 2 shows how to bind a property either embed the image in ActionScript
Rich Internet Applica- metadata tags in your Flex 2 applica- using getters and setters, along with an and assign it to a variable (as in the first
tions. He is an award- tions. event binding. This example has a private example in the following code), or you can
winning Flex developer variable named phoneNumber, as well assign it directly to the component prop-
and self-proclaimed Flex [ArrayElementType] as a public getter and setter. The getter erty (using the syntax shown in the second
evangelist. Rich is highly Defining an array is usually very method uses the Bindable tag to bind to example of the following code).
regarded in the Flex com- generic in nature because the elements an event named phoneNumberChanged.
munity as an expert in of the array can be any type. However, This setter method dispatches the phone- [Embed(source=”myIcon.gif”)]

RIA and is an Adobe using the ArrayElementType metadata NumberChanged even whenever its data [Bindable]

Community Expert. He tag lets you define the data types of the changes. By using a setter method, the public var myIcon:Class;

runs a popular Flex blog at array elements. Here is the sample syntax data can be manipulated before it’s set to
HYPERLINK “http:// of [ArrayElementType]: the private variable. In this example, the <mx:Button label=”Icon Button 1”

www.everythingFlex.com” data is formatted only when the length of icon=”{myIcon}”/>

http://www.everything- [ArrayElementType(“String”)] the value coming into the method is 10.


Flex.com, contributes to public var arrayOfStrings:Array; When the phoneNumberChanged event is <mx:Button label=”Icon Button 2”

the Indianapolis Flex user dispatched, the second TextInput compo- icon=”{myIcon}”/>

group, and is the lead [ArrayElementType(“Number”)] nent updates because its text property is
author of the Wiley/Wrox public var arrayOfNumbers:Array; bound to the phoneNumber variable. The output from the following is
Publication Professional Figures 2 and 3 show the results of identical to the previous code block. The
Flex 2. [ArrayElementType(“mx.core. Listing 2. benefits of creating the myIcon class are

26 January/February 2007
that it can be defined one time in a single

Figure 1
class and bound to multiple components
in your application.

<mx:Button label=”Icon Button 1”

icon=”@Embed(source=myIcon.gif’)”/>

<mx:Button label=”Icon Button 2”

icon=”@Embed(source=myIcon.gif’)”/>

[Event]
The Event metadata tag is used to

Figure 2
declare events that will be dispatched
by your custom class. Adding this meta-
data tag to your class definition allows
you to add an event handler function to
the MXML tag used to instantiate your
custom class. Listing 5 creates a custom
Button class that will dispatch an event
whenever its label property changes. The
main application file shown in Listing 6
instantiates the custom Button and cre-
ates the event handler function, which

Figure 3
dumps the new label property to a
TextArea component to show the occur-
ring changes.
Figure 4 shows the results of Listing 5
and Listing 6.

[Effect]
The Effect metadata tag is used to
define a custom effect that will be dis-
patched when an event occurs. This can
be easily demonstrated by building on

Figure 4
the earlier Event examples. By simply
changing a single line to the ButtonLabel
class (Listing 7), an effect is defined that
can be assigned to an Effect instance
(Listing 8).

[IconFile]
IconFile is used to identify the file-
name of a jpg, gif, or png file that will be
used as the icon for your custom class.
While the [Embed] meta tag can be used
to embed images files, SWF files, music
files, video files, etc, IconFile is only used
to embed a file that will be used as the
icon for the custom class. Here is the
example of the IconFile syntax:

[IconFile(“icon.png”)] [Inspectable] shown in Listing 9 defines a variable


public class CustomButton extends The Inspectable metadata tag is named ccType that is inspectable. It
Button used to define the attributes of your defines a defaultValue of Visa, a cat-
{ custom component that you would like egory of Credit Card and enumeration
to display in the code hints and property values of Visa, Mastercard, Discover, and
} inspector of Flex Builder 2. The example American Express.

January/February 2007 27
Figure 5 shows the example of the Figure 6 shows the same example, but the category of properties is Credit Card
code hints being displayed as the compo- this time in design view, which exposes with the property showing as ccType and
nent is added to an application. the property inspector. You can see that the available values in the drop-down.

[InstanceType]
Figure 6 The InstanceType metadata tag is
used to declare the type of object that
will be allowed when declaring a variable
as IDeferredInstance in a template object.
The syntax of InstanceType looks like this:

[InstanceType(“package.className”)]

[NonCommittingChangeEvent]
The NonCommittingChangeEvent is a
metadata tag that will prevent a change
from occurring when a specified event
occurs. Listing 10 demonstrates how this
works. A private variable named s of type
String is created and bound to the ti2
TextInput component. The other TextInput
component with the id of ti1 sets the value
of s equal to the value of its text property
whenever the text changes. Additionally,
the Binding metadata tag attached to
the s variable is set to bind when the trig-
gerBinding event is dispatched. The trig-
Figure 5

28 January/February 2007
"USINESSESTHATIGNORETHEPOTENTIALOF3/!WILLlNDTHEMSELVES
OUTPACEDBYRIVALSWHOIMPROVETHEIRAGILITYANDTRANSFORM
THEMSELVESINTONEWKINDSOFENTERPRISES
ˆ9AlM.ATIS 'ARTNER!NALYST

4/0)#3).#,5$%

 $!9%6%.4 40"8FC4FSWJDFT 0QFO4PVSDF

3/!7ORLD
"+"9BOE40" 0QFO4PVSDF

8FC   #VTJOFTT.PEFMT
 0QFO4PVSDF&4#
6OJWFSTBM40" 
 0QFO"KBY"MMJBODF
1SPUFDUJOH 
  8FC4FSWJDFT 4BB4BOE0QFO4PVSDF

5SPVCMFTIPPUJOH 4QSJOH )JCFSOBUF


  BOE&DMJQTF
0LUS
 40"
(PWFSOBODF 4FBN
 
0QFO4PVSDF 0QFO4PVSDF1FOFUSBUJPO

%NTERPRISE
 
 40" .POFUJ[JOH0QFO4PVSDF


/PEN3OURCE
9#3- 0QFO4PVSDF%BUBCBTFT
 
4FSWJDF ".21
 
 7JSUVBMJ[BUJPO 0QFO4PVSDF.JEEMFXBSF


#ONFERENCE%XPO *UNEn 


2OOSEVELT(OTEL.EW9ORK#ITY

2EGISTER/NLINEWWW3/!7ORLDCOM 3/!%/3#/.&%2%.#%393 #/.#/-

2%')34%2/.,).%4/$!9

3!6%
(5229&/2%!2,9 ")2$$)3#/5.4

"2/5'(44/9/5"9
4(%7/2,$3,%!$).'-!'!:).%$%$)#!4%$4/7%"3%26)#%34%#(./,/')%3

40"8PSME.BHB[JOF
&/2!,,4(%,!4%34.%73
!.$).&/2-!4)/.
6)3)4

WWW3/!393 #/.COM

GPDVTFTPOUIFCVTJOFTTBOE
JTUPNBOZJOEVTUSZJOTJEFSTTIBQJOHVQUPCFBNBKPSJOnFDUJPOQPJOUJOTPGUXBSFEFWFMPQNFOU
*!.5!296/,5-%)335%

!RE9OU"EING
BOEEFQMPZNFOU XJUI40" 8FC4FSWJDFT 0QFO4PVSDF BOE"+"9BMMDPOWFSHJOHBTDSPTTQMBUGPSN



 &ROMTHE%DITOR

3%!.2(/$9

 )NTELLIGENT3/.
*%&&"2/7.).'
3ERVED UFDIOPMPHZPG4FSWJDF0SJFOUFE
 !*!8 3/!  #USTOMER

"SDIJUFDUVSFTBOE8FC4FSWJDFT

BOEDSPTTCSPXTFSBQQTCFDPNFUIFSVMFSBUIFSUIBOUIFFYDFQUJPO
4HE.EXT+ILLER!PP

*/(.#250) #ENTRIC3/!
0!5,,)04/.


 !RCHITECTURAL&RAMEWORK
FOR""-ARKETPLACES
*!)'!.%3(!.$32).)6!30!$-!.!"(5.)

 #(2)3&!22%,,
3/!!PPLICATION3UCCESS

*UUBSHFUTFOUFSQSJTFBQQMJDBUJPO


 !RCHITECTURE&RAMEWORK
4HE/PEN'ROUP


&!4-!$!.$!3() 4%2%.#%",%6).3
2/,&3)%'%23 !.$*5$)4(*/.%3

"DDPSEJOHMZUIFUI*OUFSOBUJPOBM40"8FC4FSWJDFT&EHFBHBJOTFFLTUPPGGFSDPNQSFIFOTJWF  !.$2%7"/2,%9 3)-/.,!73 !.$(!,%(-!("/$




!N/VERVIEWOF3#!AND3$/

 )S9OUR%NTERPRISE
!RCHITECTURE(EALTHY
$!6)$3,).4()#5-
EFWFMPQNFOUBOENBOBHFNFOU 
DPWFSBHFBOEBDUJPOBCMFJOTJHIUTUPUIFEFWFMPQFST BSDIJUFDUT *5NBOBHFST $90T BOBMZTUT 7$T  0,%!3%$)30,!95.4),-!2#( 

8FC 3*"
.BS 
JOBMMJUTBTQFDUT
BOEKPVSOBMJTUTXIPMMCFBTTFNCMJOHBTEFMFHBUFTBOE7*1HVFTUTJO5IF3PPTFWFMU)PUFMJOEPXOUPXO
$PNJOHUP/FX:PSL$JUZ
XXXBKBYXPSMEFYQPDPN

.BOIBUUBO +VOF 

$PMPDBUFEXJUIUIFOE"OOVBM&OUFSQSJTF0QFO4PVSDF$POGFSFODF&YQP UIFFWFOUXJMMEFMJWFSUIF &OUFSQSJTF0QFO4PVSDF.BHB[JOF


JUFDIOPMPHZFEVDBUJPOBMBOEOFUXPSLJOHPQQPSUVOJUZPGUIFZFBS5IFTFUXPDPOGFSFODFQSPHSBNT &04JTUIFXPSMETMFBEJOH
CFUXFFOUIFNXJMMQSFTFOUBDPNQSFIFOTJWFWJFXPGBMMUIFEFWFMPQNFOUBOENBOBHFNFOUBTQFDUTPG
QVCMJDBUJPOTIPXDBTJOHFWFSZ
JOUFHSBUJOHB40"TUSBUFHZBOEBO0QFO4PVSDFQIJMPTPQIZJOUPZPVSFOUFSQSJTF0VSPSHBOJ[JOHQSJODJQMF
JTUIBUEFMFHBUFTXJMMHPBXBZGSPNUIFJOUFOTFUXPEBZQSPHSBNSFQMFUFXJUIXIZUPBOEIPXUP BTQFDUPGQSPmUBCMF0QFO4PVSDF
LOPXMFEHFEFMJWFSFEmSTUIBOECZJOEVTUSZFYQFSUT TPMVUJPOTJOCVTJOFTTBOE
DPOTVNFSDPOUFYUT
7JTJUTPBFPTDPOGFSFODFTZTDPODPNGPSUIFNPTUVQUPUIFNJOVUFJOGPSNBUJPOJODMVEJOH
,FZOPUFT 4FTTJPOT 4QFBLFST 4QPOTPST &YIJCJUPST 4DIFEVMF FUD

'PSNPSFHSFBUFWFOUTWJTJUXXX&7&/544:4$0/DPN &YIJCJUBOE4QPOTPSTIJQ*OGP
$BMMPSFNBJMFWFOUT!TZTDPODPN
COPYRIGHT ©2007 SYS-CON MEDIA ALL RIGHTS RESERVED
gerBinding event is dispatched only when the Enter key is Listing 1 A simple use of [Bindable]
<?xml version=”1.0” encoding=”utf-8”?>
pressed while typing in the ti1 TextInput component. <mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml”
backgroundColor=”#FFFFFF”>
<mx:Script>
[RemoteClass] <![CDATA[
RemoteClass can be used to bind an ActionScript [Bindable]
private var me:String=”Rich Tretola”;
class to a Java class or a ColdFusion CFC. This will allow
]]>
for automatic data type conversions. Below is a sample </mx:Script>
of an ActionScript class named MyClass in the package <mx:Panel title=”Simple Binding” width=”500” height=”90”
paddingTop=”10” paddingLeft=”10” paddingRight=”10” pad-
com.mydomain being bound to a Java class named dingBottom=”10”
MyClass in the package com.mydomain: layout=”horizontal”>
<mx:Label text=”{me}”/>
</mx:Panel>
package com.mydomain { </mx:Application>
[Bindable]

[RemoteClass(alias=”com.mydomain.MyClass”)]
Listing 2 Using [Bindable] with getters and setters
<?xml version=”1.0” encoding=”utf-8”?>
public class MyClass { <mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml”>
public var id:int;
<mx:Script>
<![CDATA[
public var myText:String; private var _phoneNumber:String = “”;
// Bind getter function to phoneNumberChanged event
[Bindable(event=”phoneNumberChanged”)]
} public function get phoneNumber():String {
} return _phoneNumber;
}
// Setter method.
[Style] public function set phoneNumber(value:String):void {
if (value.length<10) {
The Style metadata tag is used to define custom style
_phoneNumber = value;
properties for your components. Simply add the Style } else {
metadata tag or tags to your class definition and then _phoneNumber = phoneFormatter.format(value);
}
use the getStyle method to retrieve its value. // Create and dispatch event
Listings 11 and 12 give examples of how to define var eventObj:Event = new Event(“phoneNumberChanged”);
dispatchEvent(eventObj);
two styles named borderColor and fillColor, both of
}
which are defined as a uint data type. The styles are set ]]>
in the component tag when the class is instantiated. The </mx:Script>
<mx:PhoneFormatter id=”phoneFormatter”
updateDisplayList function is overridden and the custom formatString=”(###) ###-####” validPatternChars=”#-()
styles are used to draw the circle border and fill. “/>
<mx:Panel title=”Bind with Getters and Setters”
Figure 7 shows the results of Listing 12 and Listing 13.
width=”500” height=”90”
By now you should have had a few “Wow, I know paddingTop=”10” paddingLeft=”10” paddingRight=”10” pad-
where I could have used that” or “Hmm, I think I will dingBottom=”10”
layout=”horizontal”>
try this metadata tag in a new project.” If you haven’t, <mx:TextInput id=”ti1” change=”phoneNumber=ti1.text”
then you need to go back and read the article again. maxChars=”10” restrict=”0-9”/>
<mx:TextInput id=”ti2” text=”{phoneNumber}”/>
OK, so what I’m trying to say is that the metadata tags
</mx:Panel>
provided for us by the Adobe Flex team are not only </mx:Application>
extremely powerful, allowing us to extend and custom-
ize what we do with Flex, but are also very easy to use. Listing 3 Custom Button class named MyButton
package
They are a very quick way to accomplish a great deal
{
with only a few lines of code. If you’re not using these import mx.controls.Button;
tags, you’re working too hard to accomplish things that
[DefaultProperty(“label”)]
are built into Flex 2.
public class MyButton extends Button
• • • {

}
The content of this article is excerpted from }

the upcoming book titled Professional Flex 2 (ISBN


0470102675) by Rich Tretola, Simon Barber, and Renaun Listing 4 Using the MyButton class wih [DefaultProperty]
<?xml version=”1.0” encoding=”utf-8”?>
Erickson from Wiley Publishing, Inc./Wrox Press. To
<mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml”
pre-order please visit http://www.everythingflex.com xmlns:comps=”*”>
or http://www.amazon.com/Professional-Flex-2-Rich-
<comps:MyButton>
Tretola/dp/0470102675. <mx:String>Test</mx:String>

30 January/February 2007
</comps:MyButton> <![CDATA[
[Inspectable(defaultValue=”Visa”,
</mx:Application> enumeration=”Visa,Mastercard,Discover,American Express”
category=”Credit Card” type=”String”)]
public var ccType:String;
Listing 5 Custom ButtonLabel class using [Event] ]]>
package </mx:Script>
{
import mx.controls.Button; </mx:HBox>
import flash.events.Event;
// Define the custom event
[Event(name=”labelChanged”, type=”flash.events.Event”)]
Listing 10 Using [NonCommittingChangeEvent]
<?xml version=”1.0” encoding=”utf-8”?>
public class ButtonLabel extends Button {
<mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml”
// property to hold label value
backgroundColor=”#FFFFFF”>
private var _myLabel:String;
// public setter method
<mx:Script>
public function set myLabel(s:String):void {
<![CDATA[
_myLabel = s;
import flash.events.Event;
this.label = s;
private var eventObj:Event;
// Create and dispatch custom event
var eventObj:Event = new Event(“labelChanged”);
[Bindable(event=”triggerBinding”)]
dispatchEvent(eventObj);
[NonCommittingChangeEvent(“change”)]
}
private var s:String;
}
}
private function triggerBinding():void{
eventObj = new Event(“triggerBinding”);
dispatchEvent(eventObj);
Listing 6 Using the ButtonLabel class with the labelChanged [Event] }
<?xml version=”1.0” encoding=”utf-8”?> ]]>
<mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml” </mx:Script>
xmlns:comps=”*” <mx:Panel title=”NonCommittingChangeEvent Sample” width=”500”
backgroundColor=”#FFFFFF”> height=”90”
<mx:Script> paddingTop=”10” paddingLeft=”10” paddingRight=”10” paddingBot-
<![CDATA[ tom=”10”
import mx.controls.Alert; layout=”horizontal”>
import flash.events.Event; <mx:TextInput id=”ti1” change=”s=ti1.text” enter=”triggerBinding()”
/>
// method to handle custom event <mx:TextInput id=”ti2” text=”{s}” />
public function labelChanged(eventObj:Event):void { </mx:Panel>
myTA.text= myTA.text + “\n”+ eventObj.target.label; </mx:Application>
myTA.verticalScrollPosition = myTA.verticalScrollPosition +
20;
} Listing 11 Custom Class CustomCircle using [Style] tags
]]> package
</mx:Script> {
<mx:Panel title=”Event Sample” width=”500” height=”275” import mx.core.UIComponent;
paddingTop=”10” paddingLeft=”10” paddingRight=”10” paddingBot-
tom=”10” [Style(name=”borderColor”,type=”uint”,format=”Color”,inherit=”no”)]
layout=”absolute”> [Style(name=”fillColor”,type=”uint”,format=”Color”,inherit=”no”)]
<mx:TextInput id=”buttonLabelTI” public class CustomCircle extends UIComponent {
change=”myButton.myLabel=buttonLabelTI.text” x=”10” y=”9”/>
<!--Instantiate custom class and define method to handle label- public function CustomCircle(){
Changed event--> super();
<comps:ButtonLabel id=”myButton” labelChanged=”labelChanged(event) }
;”
x=”10” y=”39”/> override protected function updateDisplayList(unscaledWidth:Number,
<mx:TextArea id=”myTA” width=”200” height=”200” x=”249” y=”10”/> unscaledHeight:Number):void {
</mx:Panel> super.updateDisplayList(unscaledWidth, unscaledHeight);
</mx:Application> graphics.lineStyle(1, getStyle(“borderColor”), 1.0);
graphics.beginFill(getStyle(“fillColor”),1.0);
Listing 7 Add the Effect metadata tag graphics.drawEllipse(0,0,100,100);
... }
// Define the custom event }
[Event(name=”labelChanged”, type=”flash.events.Event”)] }
[Effect(name=”labelChangedEffect”, event=”labelChanged”)]
public class ButtonLabel extends Button {
...
Listing 12 Using CustomCircle and assigning custom style properties
<?xml version=”1.0” encoding=”utf-8”?>
<mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml”
Listing 8 Add labelChangedEffect to the Component xmlns:comps=”*”
Instantiation MXML Tag backgroundColor=”#FFFFFF”>
<comps:ButtonLabel id=”myButton” labelChanged=”labelChanged(event);” <mx:Panel title=”Style Sample” width=”200” height=”200”
labelChangedEffect=”myEffect” x=”10” y=”39”/> paddingTop=”10” paddingLeft=”10” paddingRight=”10” paddingBot-
tom=”10”
Listing 9 Custom component with [Inspectable] defined layout=”horizontal”>
<comps:CustomCircle borderColor=”#000000” fillColor=”#FF0000” />
<?xml version=”1.0” encoding=”utf-8”?>
</mx:Panel>
<mx:HBox xmlns:mx=”http://www.adobe.com/2006/mxml”>
</mx:Application>
<mx:Script>

January/February 2007 31
flexination

Video Rock ’n Roll


with Flex 2
Streaming videos
by Michael Givens

f
lex 2 and the Flash Media Server html. The full source code is available at Utilizing an EventListener, vidDisplay.
are a match made in heaven. By http://www.insideflex.com/fmsvideo/bin/ addEventListener(Event.COMPLETE,
combining the two technolo- srcview/index.html. onComplete)5 , the buttons are enabled
gies, streaming Flash videos at Stepwise, first create a new Flex 2 or disabled in a logical fashion depending
my office has become a nice part project in the Flex 2 Builder IDE (for this on the video’s playback state.
of my daily routine and a good excuse project there’s one named fmsvideo_flex). This article would not be complete
to add another monitor to my desktop. The code and the explanation for the without discussing the placement of
Whether your musical genre taste is clas- main MXML file are discussed below (see the Flash video flvs. You should create a
sical or rock ’n roll, it’s relatively easy to Listing 1). new Flash Media Server application – by
quickly create a desktop library of Flash The application is initialized with adding new folders (for this demo, vid-
videos. In this article, I’ll describe one the initApp()1 function where the eos\streams\_definst_) in the applications
approach that will have you streaming in VideoDisplay control is displayed and the folder (for a default installation, you would
no time. HttpService is called. This accomplishes end up with this folder: “C:\Program Files\
You will need the Flex 2 Builder (with two main things. First, Flex creates a Macromedia\Flash Media Server 2\applica-
Flex 2 SDK), the Flash Media Server (the VideoDisplay control (http://livedocs. tions\videos\streams\_definst_”). Copy the
Macromedia Communication Server macromedia.com/flex/201/langref/mx/ flvs and paste them here. If you need some
works as well), and at least one or two controls/VideoDisplay.html) with no vis- flvs for your VideoPlayer, you can grab the
Flash videos (flv). I will omit the instal- ible user interface; by setting the source URLs from YouTube.com and use a tool
lation details in this discussion and get attribute to an flv and the autoPlay attri- you’ll find at TechCrunch – http://www.
to the good stuff right away. For a quick bute to false, the control gets displayed in techcrunch.com/get-youtube-movie/. This
demo, try this example: http://www. the UI. Second, the data (see Listing 2) for effectively allows you to download the flvs
insideflex.com/fmsvideo/bin/fmsvideo. the ComboBox video list is requested. of your choice.
The creationComplete attribute I hope you found this article useful.
includes a call to the PageLoaded()2 If you have any follow-up questions, feel
Figure 1

function that kicks off, at one-second free to ping me at the e-mail address
intervals, a function that determines if the listed with this article. Rock on!
HttpService is complete; the readytoCon-
tinue()3 function loads the videos’ names Mike Givens is the CTO of U Saw It
and labels into an array, dp, that is the Enterprises, a Web technology consulting
dataProvider of the ComboBox control, firm based in Marietta, GA. He is an Adobe
cbxVideos. Community Expert (Flex) as well as an
Selecting a video triggers the com- Adobe Corporate Champion known to share
boBox’s change event and the function, his experience and evangelism of all things
playVideo(cbxVideo.selectedItem.name)4, Adobe. Certified in both ColdFusion 5 and
and the video begins streaming its content. as an Advanced CFMX Developer, he has
The standard Play, Mute, Pause been using ColdFusion since the days of
and Stop buttons are included, pro- Allaire Spectra. Mike blogs at http://www.
viding complete playback control. flexination.info/. info@webmxml.com

32 January/February 2007
//mx.controls.Alert.show(“number of videos: “ + videoSer-
Listing 1: fmsvideo.mxml
vice.lastResult.videos.video.length);
<?xml version=”1.0” encoding=”utf-8”?>
var aryTemp:Array = new Array();
<mx:Application pageTitle=”My FMS Video Player” xmlns:
for (var i:Number=0; i<videoService.lastResult.videos.
mx=”http://www.adobe.com/2006/mxml” initialize=” HYPERLINK
video.length; i++) {
\l “initAppfx” initApp()1” creationComplete=” HYPERLINK \l
aryTemp.push({name: videoService.lastResult.videos.video[i].
“PageLoadedfx” PageLoaded()2” layout=”vertical”>
name, label: videoService.lastResult.videos.video[i].label});
<!—this http service is used to supply the dataProvider for
}
the ComboBox list of videos
dp = aryTemp;
<mx:HTTPService id=”videoService” url=”theVideos.xml”
cbxVideo.dataProvider = dp;
showBusyCursor=”true” />
}

blnLoadDelayRunOnce = true;
<mx:Script>
}
<![CDATA[

import mx.events.VideoEvent;
private function playVideo(stream:String)4:void {
import mx.controls.Alert;
if (stream!=null) {

//Alert.show(stream);
[Bindable] private var dp:Array;
vidDisplay.autoBandWidthDetection = false;
[Bindable] private var bgimage:String = “”;
vidDisplay.source = “rtmp:// your_domain /videos/” + stream
private var blnLoadDelayRunOnce:Boolean = false;
+ “.flv”;

vidDisplay.addEventListener(Event.COMPLETE, onComplete)5;
private function initApp()1:void {
vidDisplay.play();
vidDisplay.autoBandWidthDetection = false;
btnPlay.enabled = false;
vidDisplay.source = “rtmp://your_domain/videos/
btnMute.enabled = true;
defleppard_photograph.flv”;
btnPause.enabled = true;
videoService.send();
btnStop.enabled = true;
}
swfLoad.source = “delirio.swf”;

}
private function PageLoaded()2:void {
}
var myTimer:Timer = new Timer(1000, 0);

myTimer.addEventListener(“timer”, onTimer);
private function onComplete(event:Event):void {
myTimer.start();
swfLoad.source = null;
}
btnPlay.enabled = true;

btnMute.enabled = false;
private function onTimer(event:TimerEvent):void {
btnPause.enabled = false;
if (!blnLoadDelayRunOnce) {
btnStop.enabled = false;
readytoContinue();
}
}

}
private function pauseVideo(stream:String):void {

if (stream!=null) {
private function readytoContinue()3:void {
vidDisplay.pause();
if (videoService.lastResult.videos.video!=undefined) {
btnPlay.enabled = true;

January/February 2007 33
swfLoad.source = null; }

} ]]>

} </mx:Script>

<mx:Panel title=”Rock it to me” color=”#E21C51”

private function stopVideo(stream:String):void { height=”{vidDisplay.height + 80}” width=”{vidDisplay.width +

if (stream!=null) { 40}” horizontalAlign=”center” verticalAlign=”middle”>

vidDisplay.stop(); <mx:VideoDisplay id=”vidDisplay” source=”{null}”

vidDisplay.close(); autoPlay=”false” maintainAspectRatio=”true”/>

btnStop.enabled = false; <mx:HBox>

btnPause.enabled = false; <mx:Button id=”btnPlay” label=”Play” click=”playVid

btnMute.enabled = false; eo(cbxVideo.selectedItem.name)” enabled=”false”/>

btnPlay.enabled = true; <mx:Button id=”btnPause” label=”Pause” click=”pause

swfLoad.source = null; Video(cbxVideo.selectedItem.name)” enabled=”false”/>

} <mx:Button id=”btnStop” label=”Stop” click=”stopVid

} eo(cbxVideo.selectedItem.name)” enabled=”false”/>

<mx:Button id=”btnMute” label=”Mute” click=”muteVid

private function muteVideo(stream:String):void { eo(cbxVideo.selectedItem.name)” enabled=”false”/>

if (stream!=null && btnMute.label==’Mute’) { </mx:HBox>

vidDisplay.volume = 0; </mx:Panel>

btnMute.label = “Sound On”; <mx:ComboBox id=”cbxVideo” dataProvider=”{dp}”

swfLoad.source = null; labelField=”label” change=” HYPERLINK \l “playVideo”

} else if (stream!=null && btnMute.label==’Sound On’) { playVideo(cbxVideo.selectedItem.name)4” toolTip=”Select the

vidDisplay.volume = 1; video you want to play...”/>

btnMute.label = “Mute”; <mx:Spacer height=”10”/>

swfLoad.source = “delirio.swf”; <mx:SWFLoader id=”swfLoad” source=”{null}” width=”50”

} height=”50” click=”viewSource()” toolTip=”Click to view the

} source...”/>

private function viewSource():void { </mx:Application>

var u:URLRequest = new URLRequest(“srcview/index.html”);

navigateToURL(u,”_blank”); Listing 2: theVideos.xml


<?xml version=”1.0” encoding=”iso-8859-1”?>

<videos>

Advertising Index <video>

<label>Select a video...</label>
Advertiser URL Phone Page
<name>null</name>
Adobe www.adobe.com 2

CFDynamics www.cfdynamics.com 866-233-9626 6 </video>

CFUnited www.cfunderground.com 19 <video>

Community MX www.communitymx.com 15 <label>Def Leppard - Hysteria</label>

Cynergy 8 <name>defleppard_hysteria</name>
Hot Banana 35
</video>
Host My Site 12
<video>
JavaOne 11
<label>Def Leppard - Love Bites</label>
Intergral www.fusiondebug.com 5
<name>defleppard_love_bites</name>
Omniture 11
</video>
PaperThin www.paperthin.com 37

Stream57 www.stream57.com 212-909-2550x1012 15 </videos>

Vitalstream www.vitalstream.com 800-254-7554 24

34 January/February 2007
/THERCOMPANIESINTHISMAGAZINESPENTALOTOFTIMEONPRETTYADS!S
YOUCANSEE WEDIDNOT7ESPENTOURTIMEHIRINGTHEBESTPEOPLEAND
TRAINING THEM TO DELIVER OUTSTANDING SUPPORT FOR YOUR WEBSITE 7E
SPENTOURTIMEBUILDINGASTATEOFTHEARTDATACENTERANDSTAFFINGITWITH
PEOPLEWHOCAREABOUTYOURWEBSITELIKEITSTHEIROWN#OMPASSION
RESPECT CREDIBILITY OWNERSHIP RELIABILITY hNEVERSAYNO vANDEXCEED
EXPECTATIONSAREWORDSTHATDESCRIBEOURSERVICEPHILOSOPHY&ROMTHE
FIRST TIME YOU INTERACT WITH US YOUgLL SEE WHAT A DIFFERENCE IT REALLY
MAKES!NDYOUgLLALSOFORGIVEUSFORNOTHAVINGAPRETTYAD

7%"(/34).'s-!.!'%$$%$)#!4%$3%26%23s#/,/#!4)/.s603s%#/--%2#%s",/'').'s%-!),

You might also like