Web Designer`sJournal Developer`s - SYS

Web Designer`sJournal Developer`s - SYS
THE AGE OF RIAS, FLASH, FLEX, AND NOW APOLLO
Web
VOLUME 5 ISSUE 1 2007
MX
DE
FO
VE
LO
RM
PE
ER
R’S
LY
JO
Developer’s &
Designer’s Journal
UR
NA
L
WWW.WEBDDJ.COM
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
7
12
16
26
32
We Have Entered the Age of
RIAs, Flash, Flex…and Now Apollo
by Jeremy Geelan
Binary Data,
ColdFusion & Flex
Sending BitmapData to a server and saving it as a JPG file
by Andrew Trice
Simplifying AJAX
with the Spry Framework
Delivering great experiences
by Paul Gubbay
Flex 2
Metadata Tags
Telling the compiler how to compile
by Rich Tretola
Video Rock ’n Roll
with Flex 2
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
JOBXFCIPTU5IFDPNCJOBUJPOPGPVSQPXFSGVMIPTUJOHQMBOTSFMJBCMFOFUXPSLBOEGBOUBTUJDTVQQQPSUTFUTVTBQBSUGSPNPUIFSIPTUT
3FBMTFSWJDF3FBMTBUJTGBDUJPO3FBMWBMVF3FBMTVQQPSU3FBM'SFFEPN
from the publisher
Web Developer’s &
Designer’s Journal
Group Publisher Jeremy Geelan
Art Director Louis F. Cuffari
Editorial Board
Aral Balkan
Erik Bianchi
Craig Goodman
Andrew Powell
Jim Phelan
Andrew Phelps
Darron J. Schall
Stephanie Sullivan
Jeff Tapper
Jesse Randall Warden
Editorial
Editor
Nancy Valentine, 201 802-3044
nancy@sys-con.com
To submit a proposal for an article, go to
http://grids.sys-con.com/proposal.
Subscriptions
E-mail: subscribe@sys-con.com
U.S. Toll Free: 888 303-5282
International: 201 802-3012
Fax: 201 782-9600
Cover Price U.S. $5.99
U.S. $29.99 (12 issues/1 year)
Canada/Mexico: $49.99/year
International: $59.99/year
Credit Card, U.S. Banks or Money Orders
Back Issues: $12/each
Editorial and Advertising Offices
Postmaster: Send all address changes to:
SYS-CON Media
577 Chestnut Ridge Rd.
Woodcliff Lake, NJ 07677
Worldwide Newsstand Distribution
Curtis Circulation Company, New Milford, NJ
List Rental Information
Kevin Collopy: 845 731-2684,
kevin.collopy@edithroman.com,
Frank Cipolla: 845 731-3832,
frank.cipolla@epostdirect.com
Promotional Reprints
Megan Mussa, 201 802-3024
megan@sys-con.com
Copyright © 2006
by SYS-CON Publications, Inc. All rights reserved. No part of this
publication may be reproduced or transmitted in any form or by
any means, electronic or mechanical, including photocopy or any information storage and retrieval system, without written permission.
Web Developer’s & Designer’s Journal (ISSN#1546-2242)
is published monthly (12 times a year) by
SYS-CON Publications, Inc., 577 Chestnut Ridge Road,
Woodcliff Lake, NJ 07677.
SYS-CON Media and SYS-CON Publications, Inc., reserve the right to revise, republish, and authorize its readers to use the articles submitted for
publication. Adobe and Adobe products are either registered trademark
or trademarks of Adobe Systems Incorporated in the United States and/or
other countries. SYS-CON Publications, Inc., is independent of Adobe. All
brand and product names used on these pages are trade names, service
marks or trademarks of their respective companies.
January/February 2007
We Have Entered the Age of
RIAs, Flash, Flex…and Now Apollo
a
lready, even in pre-release,
Adobe’s Spry seemed to catch the
imagination of many Web professionals wrestling with how to integrate new
AJAX frameworks into existing workflows.
Created with designers in mind, Spry uses
regular HTML tags, CSS, and JavaScript, and
is easy to use – boiling down to a couple
of JavaScript libraries that you include in
your Web page in order to be in a position
to add dynamic interactive content to your
site.
What spurs me to mention Spry is the
approach of AJAXWorld Conference & Expo,
of which Adobe is a Platinum sponsor.
There is no doubt that it will be the most
intense three-day conference anywhere
on the East coast this year, devoted to
the issues most preoccupying those who
design, build, and deploy Web sites and
Web-based applications.
There are several Flex sessions at the
Conference, including one by Kevin Hoyt
– known to many readers of WebDDJ from
his regular appearances at various user
group forums and conferences throughout
the United States. Kevin will be talking
about using Flex and AJAX “to bring the
‘sexy’ back to the enterprise,” as he puts it.
His session will provide an interactive deep
dive on how to integrate Flex, AJAX and
Apollo to bring the ‘sexy’ elements of Webbased RIAs to the enterprise.
As for Apollo, that will naturally be
making an appearance at AJAXWorld 2007
East, too. In a session called “Denting the
Browser’s Chrome: Intense Experiences,
Advanced RIA Development and Apollo,”
Cynergy’s Andrew Trice, an Enterprise
Applications Consultant for Cynergy
Systems, will remind us of the dark decade
by Jeremy Geelan
or so during which the user experiences
that drove applications on the web were
primitive at best; when, as Trice expresses
it, “forms and grids trapped in the browser’s
content-centric chrome ruled the earth.”
The thing is, as Trice notes, grids are not
how users think; grids are how programmers think. And the problem is... most of
the users aren’t programmers.
”In the past,” Trice says, “it was easy to
claim that the platform was simply too
primitive to work any other way. That however doesn’t fly anymore. Today with RIAs
you now not have only a vast array of rich
controls but access to a complete robust
vector graphics drawing API. Thanks to
all of this, if you can imagine an interface
or a way to present data and information
to the user, you can make it come alive.
More importantly, these RIAs are no longer
trapped inside the browser’s chrome and
the vision of the web driving the applications that run the business of the world is
coming alive.”
Many other sessions at AJAXWorld
are devoted to demonstrating how to
turn designs into reality and how to build
out incredible user experiences for the
Web. Enterprise application developers
are embracing AJAX – and increasingly,
Flex – to bring the same next-generation
functionality to the enterprise. They are
designing enterprise applications that
perform like desktop software but have
the connectivity of the Web and integrate
with enterprise systems. Adobe’s product road map is guiding developers and
designers into exactly the right part of
the technology landscape at exactly the
right time.
Drive safely, and enjoy!
Jeremy Geelan is Sr. VicePresident, Editorial & Events
of SYS-CON Media. He is
Conference Chair of the
AJAXWorld Conference
& Expo series and of the
“Real-World Flex” One-Day
Seminar series. He is executive producer and presenter
of “Power Panels with Jeremy
Geelan” on SYS-CON.TV,
and is actively helping build
out the AJAXWorld brand
as well as developing entirely
new Conferences and OneDay Seminars for SYS-CON
Media & Events.
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
Ariaware, a London-based company offering products
like Ariaware Optimizer and the open-source Ariaware
RIA Platform (ARP 2.0) for Flash developers. Ariaware
also offers RIA development process and usability
consulting and development services. Aral holds an
MA in Film and Electronic Media, is a Macromedia
Certified Instructor and is celebrating his 20th year as
a programmer (he’s only 27!). His passions include software architecture and Human-Computer Interaction
- in other words, building solid, usable applications.
He’s co-author of “Flash MX Most Wanted Components”
and “Flash 3D Cheats Most Wanted,” as well as author
and editor of numerous articles for Adobe Developer
Center and Ultrashock.com.
Andrew M. Phelps is in the Information Technology
Department at the Rochester Institute of Technology in
Rochester, NY (http://andysgi.rit.edu/).
Erik Bianchi
Stephanie Sullivan
Erik Bianchi is a software engineer with more than
five years of experience developing Flash-based RIAs
and enterprise-wide applications for Fortune 50 and
500 companies. In his spare time he enjoys building
Flash-based games, writing or tech editing Flash-related
books, and when burned out on code, playing video
games on his PC/console systems. You can get more
info about Erik and his latest projects on his blog at
www.erikbianchi.com.
Stephanie Sullivan is a Web developer, partner at
CommunityMX (www.communitymx.com), owner of
VioletSky Design (www.violetsky.net), and contributing
author of Dreamweaver MX 2004 Magic.
Craig Goodman
Craig Goodman is the executive editor of Adobe’s
Developer Center. He and his team publish the tutorials and articles in the area. Craig joined Macromedia
in 1995 and his past roles include managing web support and supervising product technical support for
Macromedia Flash.
Darron J. Schall
Darron J. Schall has been programming long before
he could drive. In school he studied programming
languages, ranging from Basic to Pascal to C++ and
eventually moving into Java and C# throughout college.
Somewhere in the middle he got hooked on Flash 5 and
it’s been a crazy love affair ever since. Darron is an independent consultant specializing in RIA development.
He maintains a Flash Platform related weblog (www.
darronschall.com) and is an active voice in the Flash and
Flex communities.
Jeff Tapper
Jeff Tapper, co-founder of Tapper, Nimer and
Associates, has been developing Internet-based applications since 1995, for a myriad of clients including
Toys R Us, IBM, Allaire, Dow Jones, American Express,
M&T Bank, Verizon, Allied Office Supplies, and many
others. As an Instructor, he is certified to teach all
of Adobe’s courses on Flex, ColdFusion and Flash
development. He has worked as author and technical
editor for several books on technologies including
Flex, Flash and ColdFusion, such as “Object Oriented
Programming with ActionScript 2.0”, and “Flex 2
Training from the Source.”
Jim Phelan
Jim Phelan is vice president of development for
Stream57, a New York City based firm specializing in
communication solution development for the enterprise. Jim’s expertise in creating solutions for consolidation and collateralization of business communications
has allowed his team to create applications for the management and delivery of live and on demand rich media
content. Jim is a strong proponent of the Adobe Flash
Platform and is a member of the editorial board of MX
Developer’s Journal.
10
Jesse Randall Warden
Jesse R. Warden is a senior Flash developer at
Surgical Information Systems, an operating room
software company, where he currently uses Flash
MX, Flash Remoting, .NET, and Oracle to create
next-generation rich Internet applications for the
OR. He contributed four chapters to the Flash
Communication Server MX Bible and has written
articles for various publications, including one for
Macromedia for a DRK.
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 accessing/modifying their BitmapData.
In one example, I sent the BitmapData
to the server and saved it as a JPG file,
and I’ve been asked numerous times
since… “How did you do that?” It’s surprisingly easy to do once you understand
the concepts involved. There are four
ways to get binary data from the Flex
application back to your server: AMF3
(RemoteObject), Web Services, HTTP
Services, or through a Socket connection.
In this article I’ll cover the first three topics as they pertain to Flex 2; Socket connectivity could take an article all by itself.
Binary data can’t be pushed to the
server in its native format using a Web
Service or a standard HTTP POST method.
To save the data using Web Services or
HTTP POST, you must first convert the
binary data to a text string using Base64encoding. On the other hand, AMF3
(RemoteObject method) lets you send
the binary data to the server in its native
binary form. One thing to keep in mind
with Base64-encoding is that the encoding process will actually increase the size
of the data that’s being sent across the
wire.
Regardless of how you’re sending the
data to the server, it’s a good practice to
compress the data client side whenever
possible. I’ve used the JPGEncoder class
at http://code.google.com/p/as3corelib
with great success. You can use this class
12
to convert binary image data into a compressed 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
with the server.
• The data is encoded into the format
that you want to save, so no additional
processing/conversion is required on
the server. You simply need to save the
data either in your file system or in a
binary object in your database.
Here’s how you get data from a Flex
component into a JPG ByteArray: First,
you’ll have to retrieve the BitmapData
from your Flex component. You can pass
any Flex component into the following
function to retrieve its BitmapData:
remember that your Flex application will
have a slight pause while the encoding is
being processed:
var bd : BitmapData = getUIComponentBitmapData( paintCanvas );
var encoder : JPEGEncoder = new
JPEGEncoder(75);
var data : ByteArray = encoder.encode(
bd );
Once you have the data converted
to a JPG ByteArray, you’re ready to push
it to the server and save it. The fastest
and easiest way to do that is to use a
RemoteObject method and serialize
the data using AMF3. This example
shows you a method in a ColdFusion
Component (CFC) that will let you send
the data and save it to the local file system:
private function getUIComponentBitmapData( target : UIComponent ) :
<cfcomponent name=”ImageSave”
BitmapData
displayname=”ImageSave”
{
output=”false”>
var bd : BitmapData = new BitmapData(
<cffunction name=”ROsave”
target.width, target.height );
access=”remote” output=”false”
var m : Matrix = new Matrix();
returntype=”void”>
bd.draw( target, m );
<cfargument name=”data”
return bd;
type=”binary” required=”true” />
}
<cffile action=”write” file=”c:\
temp\ro_data.jpg” Once you have the BitmapData,
you’ll have to create an instance of
the JPGEncoder class and encode the
BitmapData. (This example uses the
JPG quality of 75.) It’s also important to
output=”#arguments.data#” />
</cffunction>
</cfcomponent>
You can see that the code is actually
January/February 2007
very simple. The CFC’s ROsave (remote object save)
method is expecting binary data as a parameter. When
executed, the data is written to the file system using
the <CFFILE /> “write” method.
On the Flex side, we’ll have to instantiate a mx:
RemoteObject:
<mx:RemoteObject
id=”ro”
showBusyCursor=”true”
destination=”ColdFusion”
source=”BinaryData.cf.ImageSave”>
<mx:method name=”ROsave”
result=”onResult(‘Data Saved via mx:RemoteObject’)”
fault=”onFault(event)” />
SYS-CON Media
required=”true” />
<cffile action=”write” file=”c:\temp\ws_data.jpg”
output=”#ToBinary(arguments.data)#” />
</cffunction>
</cfcomponent>
You can see that the code for the Web Service
method is very similar to the previous example. The
only difference is that the toBinary method is being
used to convert the data from a Base64-encoded string
into binary data. The CFC’s WSsave (Web Service save)
method is expecting a Base64-encoded string as a
parameter. When executed, the data is also written to
the file system using the <CFFILE /> “write” method.
In Flex, we need an instance of a mx:WebService to
save the data:
</mx:RemoteObject>
<mx:WebService
To save the data, we’ll invoke the ROsave method
and pass the JPG-encoded ByteArray as a parameter:
id=”ws”
showBusyCursor=”true”
wsdl=”/BinaryData/cf/ImageSave.cfc?wsdl”>
var bd : BitmapData = getUIComponentBitmapData(
paintCanvas );
<mx:operation name=”WSsave”
var encoder : JPEGEncoder = new JPEGEncoder(75);
result=”onResult(‘Data Saved via mx:WebService’)”
var data : ByteArray = encoder.encode( bd );
fault=”onFault(event)” />
</mx:WebService>
ro.ROsave( data );
If you aren’t using remoting, you can save the data
using Web Services or HTTP services. Most seasoned
ColdFusion developers might stop me here and say…
“If you’re using CFCs as Web Services, why wouldn’t you
just use them as RemoteObject methods since they are
faster?” My response is this: This is just an example. You
may be able to take this method and apply it to other
technologies where it may be applicable (.NET, Java,
PHP, etc.).
<cfcomponent name=”ImageSave”
displayname=”ImageSave” output=”false”>
To save the data, we first need to Base64-encode it.
The following function will take care of that for us:
private function base64Encode( data : ByteArray )
: String
{
var encoder : Base64Encoder = new Base64Encoder();
encoder.encodeBytes( data );
President & COO
Carmen Gonzalez, 201 802-3021
carmen@sys-con.com
Sr. Vice-President, Editorial & Events
Jeremy Geelan, 201 802-3051
jeremy@sys-con.com
Advertising
Vice President, Sales & Marketing
Miles Silverman , 201 802-3029
miles@sys-con.com
Advertising Sales Director
Megan Mussa, 201 802-3023
megan@sys-con.com
Associate Sales Managers
Corinna Melcon, 201 802-3026
corinna@sys-con.com
Events Manager
Lauren Orsi, 201 802-3022
lauren@sys-con.com
Production
Lead Designer
Louis F. Cuffari, 201 802-3035
louis@sys-con.com
Art Director
Alex Botero, 201 802-3031
alex@sys-con.com
Associate Art Directors
Abraham Addo, 201 802-3037
abraham@sys-con.com
Tami Beatty, 201 802-3038
tami@sys-con.com
SYS-CON.COM
Consultant, Information Systems
Robert Diamond, 201 802-3051
robert@sys-con.com
Web Designers
Stephen Kilmurray, 201 802-3053
stephen@sys-con.com
Richard Walter, 201 802-3042
richard@sys-con.com
}
Accounting
Financial Analyst
Joan LaRose, 201 802-3081
joan@sys-con.com
We’ll then invoke the WSsave method and pass the
Base64-encoded ByteArray as a parameter:
Accounts Payable
Betty White, 201 802-3002
betty@sys-con.com
return encoder.flush();
<cffunction name=”WSsave” access=”remote”
output=”false” returntype=”void”>
var bd : BitmapData = getUIComponentBitmapData(
<cfargument name=”data” type=”string”
paintCanvas );
January/February 2007
CEO
Fuat Kircaali, 201 802-3001
fuat@sys-con.com
Customer Relations
Circulation Service Coordinator
Edna Earle Russell, 201 802 -3081
edna@sys-con.com
13
var encoder : JPEGEncoder = new
JPEGEncoder(75);
of the HTTPService.send method (note
“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
data without using RemoteObjects or
Web Services, you can always use a
standard HTTP post method. In Flex,
you’ll have to create an instance of an
HTTPService object, with the method
set to “POST”:
var encoder : JPEGEncoder = new
<mx:HTTPService
…and that is how you save binary
image data using RemoteObjects, Web
Services, or HTTPServices. This doesn’t
just apply to images. This applies to any
kind of binary data; the only difference
is that the image data first gets encoded
to a JPG ByteArray. The AS3 corelib
project on Adobe Labs/Google Code
also includes class libraries that enable
you to save data as PNG images instead
of JPG images, so JPG isn’t your only
option.
A few things to keep in mind for
real-world applications... It’s best practice to use <CFFILE /> in a <CFTRY/>
statement to catch any file system
errors that may occur (not enough
space, permissions, etc.). It’s also
best practice to use <CFLOCK /> with
<CFFILE /> to prevent any errors due to
data synchronization, threading access,
or deadlock scenarios.
A working example and the source
code from this article can be viewed
online at http://www.cynergysystems.
com/blogs/blogs/andrew.trice/binary_data_example/ or downloaded from
http://www.cynergysystems.com/blogs/
blogs/andrew.trice/binary_data_example/BinaryData.zip.
id=”hs”
showBusyCursor=”true”
useProxy=”false”
method=”POST”
resultFormat=”text”
url=”/BinaryData/cf/HTTPImageSave.
cfm”
result=”onResult(‘Data Saved via mx:
HTTPService’)”
fault=”onFault(event)” />
“Regardless
of how you’re
sending the data
to the server,
it’s a good practice
to compress the
data client side
whenever
possible.”
14
The file HTTPImageSave.cfm is actually very simple. The save occurs with
only two lines of code:
<cfparam name=”data” type=”string”
default=””>
<cffile action=”write” file=”c:\temp\
http_data.jpg” output=”#ToBinary( data
)#” />
You’ll notice in this case that the
data is also being written to the file
system using the toBinary method (to
convert the Base64-encoded string back
into binary data). When invoking the
HTTPService, you’ll have to create an
object containing the parameters for the
HTTPService and send it as the parameter
JPEGEncoder(75);
var data : ByteArray = encoder.encode(
bd );
var params : Object = { data : base64Encode( data ) };
hs.send( params );
January/February 2007
Simplifying AJAX
with the Spry Framework
Delivering great experiences while fitting
the workflows and skill sets of both
designers & developers
o
by Paul Gubbay
ver the past year the
Dreamweaver product design
and development team have
been out on the road talking 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 frameworks 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
is the ability to offer their customers richer and more engaging experiences. Top
of mind is the ability to incorporate new technology into existing workflows.
We took this to heart and set out to create a framework that leverages
AJAX to deliver great experiences while fitting the workflows and skill
sets of both designers and developers. The Spry framework for AJAX was
developed with the following objectives:
• Keep it open: Spry works with all HTML editors, including Dreamweaver.
Anyone can download it off Adobe Labs to start building high-performing
interactive Web pages and applications. No proprietary tags or server-side
code needed.
• Make it easy to use: Spry uses the same technologies that you already
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
style dynamic regions and interactive widgets using the same techniques
as any other HTML elements on your page.
• Enable innovation: At the end of the day Spry is about delivering richer
experiences for your customers. Spry provides a lightweight yet powerful
model for adding data, interactivity, and rich UI widgets into your Web
pages while putting you in complete control of the design.
Next-Generation Web UI OK
Who Is It For?
Spry Data
Spry was built for both Web designers and developers. Before we built
the framework we created a profile of the typical user for Spry. This profile
helped us define our guiding principles.
• Works in Web production. Focused on the Web UI and x(HTML) production.
• Expert with x(HTML) and CSS.
• Familiar with JavaScript and the DOM.
• Cares about the quality of the code.
• Wants to create next-generation Web pages.
Data is accessed and displayed using Spry Data Sets and Regions. The Spry
Data Set is a JavaScript object that is responsible for loading and managing
(e.g., sort, filter) data. The Data Set base class is architected so that multiple
flavors can be built to access data from different sources (see Figure 3).
Guiding Principles
•
•
•
•
•
The Spry Framework
Spry is a client-side framework in the form of JavaScript libraries that you can
easily add to your new and existing Web pages. Spry is server- and tool-agnostic.
You can use it with Dreamweaver or your HTML editor of choice. Just a few lines of
code can produce powerful results. More importantly, it should all look familiar. You
should be able to jump in and be productive right away. Spry does the heavy lifting.
The Spry JavaScript libraries host three modules (see Figure 2).
Spry Regions
A Spry dynamic Region is an area on a Web page that’s bound to a Data
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
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
Figure 1
So what do we mean by more engaging and interactive Web pages? To
get a first-hand experience you can check out some of the sample pages
that have been built using Spry at Adobe Labs http://labs.adobe.com/technologies/spry/demos/index.html.
In the course of this article we’re going to look at one page in detail and
explore the code that was used to generate it.
Some of the characteristics of Spry-enabled Web pages include:
• Single page experience.
• Seamless interactivity/more responsive.
• Use of transitions and effects.
• More sophisticated UI elements.
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
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
the products in our table. Using XPath (products/product) we identify the
node(s) in the XML file that represent the records of data for our Data Set.
Finally, we can see the records and fields in the Spry Data Set once the conversion is complete.
Data Set Declaration
Spry Data Sets are added to your page in two steps. First, you must
include the appropriate JavaScript libraries:
• Spry Region Declaration: Defines an HTML element as a Spry region.
• Data Set Binding: Binds a Spry Region to a Data Set.
• Spry Attributes: Specialized attributes that provide additional functionality such as sorting.
• Spry Data Bindings: Bindings to fields located in the Data Set.
• Repeat Region Declaration: Repeats a Spry Region once for each record
in the Data Set.
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 bindings 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.
Displaying Data
Data is displayed on the Web page using Spry Regions that are loaded
with live data when the Web page is displayed in the browser. Creating the
bindings from the Data Set to the Spry Regions is easily accomplished by
attaching Spry attributes to your standard HTML tags.
In the following example we can see how the Spry Region for the
Products table is built:
Master/Detail Data Sets
The Spry framework supports the concept of Master/Detail Data Sets.
This implies that the selected record in a Master Data Set drives the contents
of the Detail Data Set. There are many ways to create this relationship using
Spry. In our example the Master Data Set and the Detail Data Set retrieves
data from different sections of the same XML file. Each time a new record is
selected in the Master Data Set, the Detail Data Set retrieves a subset of the
data.
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 specific 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
Figure 2
Spry Widgets
Figure 3
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
•
•
•
•
•
•
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 automatically update.
Master/Detail Regions
Widget Structure
In our example we use an Accordion widget to display additional information about the selected product in the Products table. The structure of
the widget is defined by the HTML code.
Figure 4
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.
As you can see, the composition of the widget is quite easy to understand 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 element 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
changed at will by the Web developer or designer.
Spry Effects
Figure 5
Spry effects are visual enhancements that you can apply to almost any element
on an HTML page. For example, an effect might highlight information, create animated transitions, or visually alter a page element for a certain period of time. Effects
are a simple but elegant way of enhancing the look-and-feel of your Web site.
Paul Gubbay is a director of engineering at Macromedia. Previously, Paul held the role of CEO at CyberSage
Software, where he spent several years building the vision
and infrastructure of the company. Under Paul’s guidance, CyberSage focused on emerging technologies such as
XML, Java, and Macromedia Flash to deliver leading edge
product offerings.
pgubbay@adobe.com
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
Second, add an event handler to a supported element (e.g., <a> tag).
Note: Supported elements differ by effect – please refer to the Spry API docs.
Figure 6
“Our goal in putting
Spry on Adobe Labs
was to make it an
open technology that
could be driven by
customer feedback”
Spry Effects are added to your page in two steps. First, you must include
the appropriate JavaScript library:
22
January/February 2007
Effect Composition
Spry effects are created by combining core effects. The
core effects include:
• Move
• MoveSlide
• Size
• Opacity
• Color
The combined effects of the Spry framework include:
Highlight
Grow/Shrink
Shake
Squish
Spry supports the ability to cluster effects together to
What’s Next for Spry?
Our goal in putting Spry on Adobe Labs was to make it
an open technology that could be driven by customer feedback. This method has produced great results for our engineering team and our customers. We continue to use your
feedback on the forums to help guide Spry’s future direction. Spry is currently in beta with official release scheduled
for early spring, 2007. This new release will include support
for JSON and nested Data Sets.
Besides the official release of Spry on Adobe Labs, we’ll
be shipping a new version of Dreamweaver with support for
Spry Data Sets, Widgets, and Effects.
Spry is a free download and can be accessed on Adobe
Labs using http://labs.adobe.com/technologies/spry/.
Figure 8
Figure 7
•
•
•
•
create your own variations. This is done by using the Cluster
effect that acts like a container for multiple core effects.
Like a regular effect, the Cluster effect has a start() function.
But unlike regular effects, Cluster provides the methods
addNextEffect() and addParallelEffect(). These functions let
you chain effects together to create new variations.
Clustered effects are a flexible mechanism for creating
new effect variations (see Figure 9). However, they require
some JavaScript programming knowledge. Please refer to
the Spry API docs for more information.
Figure 9
For each effect, you must set the target element to
which you want to apply the effect. The element parameter
can be either a string containing the id of the element or a
JavaScript DOM element object. In the example above the
AppearFade effect will run on the “target” element when the
user clicks on the <a> link. If the target element is a <div
id=”products”> tag, you would pass in “products” as the target parameter.
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
DIBMMFOHFT5PMFBSONPSFBCPVU7JUBM4USFBNTPMVUJPOTDBMM
PSWJTJUXXXWJUBMTUSFBNDPNHPTPMVUJPOT
ª7JUBM4USFBN*OD"MMSJHIUTSFTFSWFE
book excerpt
Flex 2
Metadata Tags
Telling the compiler how to compile
by Rich Tretola
m
Rich Tretola is a senior
software developer at Herff
Jones, Inc., specializing in
Rich Internet Applications. He is an awardwinning Flex developer
and self-proclaimed Flex
evangelist. Rich is highly
regarded in the Flex community as an expert in
RIA and is an Adobe
Community Expert. He
runs a popular Flex blog at
HYPERLINK “http://
www.everythingFlex.com”
http://www.everythingFlex.com, contributes to
the Indianapolis Flex user
group, and is the lead
author of the Wiley/Wrox
Publication Professional
Flex 2.
26
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.
Metadata tags are special tags that
are inserted in your source code that
give the compiler information on how
to compile the application. These tags
aren’t actually compiled into the generated SWF file but provide instructions
on how the compiler should create the
SWF. There are 12 documented metadata
tags. This article will offer definitions of
these metadata tags and give examples
of their use. By the end of this article you
will understand when and where to use
metadata tags in your Flex 2 applications.
[ArrayElementType]
Defining an array is usually very
generic in nature because the elements
of the array can be any type. However,
using the ArrayElementType metadata
tag lets you define the data types of the
array elements. Here is the sample syntax
of [ArrayElementType]:
[ArrayElementType(“String”)]
public var arrayOfStrings:Array;
[ArrayElementType(“Number”)]
public var arrayOfNumbers:Array;
[ArrayElementType(“mx.core.
UIComponent”)]
public var arrayOfUIComponents:
Array;
[Bindable]
The Bindable metadata tag is one of
the most used metadata tags because
it allows for easy data synchronization
within the components of your application. Bindable can be used to bind
simple data, classes, complex data, and
functions. To bind a simple piece of data,
you must simply define the data with
the metadata tag included, as shown in
Listing 1. Figure 1 shows the results of
Listing 1
Bindable also allows binding to events.
Listing 2 shows how to bind a property
using getters and setters, along with an
event binding. This example has a private
variable named phoneNumber, as well
as a public getter and setter. The getter
method uses the Bindable tag to bind to
an event named phoneNumberChanged.
This setter method dispatches the phoneNumberChanged even whenever its data
changes. By using a setter method, the
data can be manipulated before it’s set to
the private variable. In this example, the
data is formatted only when the length of
the value coming into the method is 10.
When the phoneNumberChanged event is
dispatched, the second TextInput component updates because its text property is
bound to the phoneNumber variable.
Figures 2 and 3 show the results of
Listing 2.
[DefaultProperty]
The DefaultProperty metadata tag is
used to set a single property as a default
property of a class. This allows the property to be set within a container tag without needing to define the property name.
A simple example of this would be a custom Button class. Listing 3 shows a simple
Button class that has the label property
set as the DefaultProperty. Listing 4
shows how the label is defined as a string
within the custom Button container tags.
[Embed]
The Embed metadata tag is used
to import images into your application.
There are two ways to use Embed. You can
either embed the image in ActionScript
and assign it to a variable (as in the first
example in the following code), or you can
assign it directly to the component property (using the syntax shown in the second
example of the following code).
[Embed(source=”myIcon.gif”)]
[Bindable]
public var myIcon:Class;
<mx:Button label=”Icon Button 1”
icon=”{myIcon}”/>
<mx:Button label=”Icon Button 2”
icon=”{myIcon}”/>
The output from the following is
identical to the previous code block. The
benefits of creating the myIcon class are
January/February 2007
Figure 1
that it can be defined one time in a single
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]
Figure 2
The Event metadata tag is used to
declare events that will be dispatched
by your custom class. Adding this metadata 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 creates the event handler function, which
dumps the new label property to a
TextArea component to show the occurring changes.
Figure 4 shows the results of Listing 5
and Listing 6.
Figure 3
[Effect]
Figure 4
The Effect metadata tag is used to
define a custom effect that will be dispatched when an event occurs. This can
be easily demonstrated by building on
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 filename 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”)]
public class CustomButton extends
Button
{
}
January/February 2007
[Inspectable]
The Inspectable metadata tag is
used to define the attributes of your
custom component that you would like
to display in the code hints and property
inspector of Flex Builder 2. The example
shown in Listing 9 defines a variable
named ccType that is inspectable. It
defines a defaultValue of Visa, a category of Credit Card and enumeration
values of Visa, Mastercard, Discover, and
American Express.
27
Figure 5 shows the example of the
code hints being displayed as the component is added to an application.
Figure 6 shows the same example, but
this time in design view, which exposes
the property inspector. You can see that
the category of properties is Credit Card
with the property showing as ccType and
the available values in the drop-down.
Figure 6
[InstanceType]
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]
Figure 5
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 triggerBinding event is dispatched. The trig-
28
January/February 2007
"USINESSESTHATIGNORETHEPOTENTIALOF3/!WILLlNDTHEMSELVES
OUTPACEDBYRIVALSWHOIMPROVETHEIRAGILITYANDTRANSFORM
THEMSELVESINTONEWKINDSOFENTERPRISES
ˆ9AlM.ATIS'ARTNER!NALYST
4/0)#3).#,5$%
$!9%6%.4
40"8FC4FSWJDFT
"+"9BOE40"
8FC
6OJWFSTBM40"
1SPUFDUJOH
8FC4FSWJDFT
5SPVCMFTIPPUJOH
40"
(PWFSOBODF
0QFO4PVSDF
40"
9#3
4FSWJDF
7JSUVBMJ[BUJPO
3/!7ORLD
0LUS
%NTERPRISE
/PEN3OURCE
#ONFERENCE%XPO
0QFO4PVSDF
0QFO4PVSDF
#VTJOFTT.PEFMT
0QFO4PVSDF&4#
0QFO"KBY"MMJBODF
4BB4BOE0QFO4PVSDF
4QSJOH)JCFSOBUF
BOE&DMJQTF
4FBN
0QFO4PVSDF1FOFUSBUJPO
.POFUJ[JOH0QFO4PVSDF
0QFO4PVSDF%BUBCBTFT
".21
0QFO4PVSDF.JEEMFXBSF
*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
&/2!,,4(%,!4%34.%73
!.$).&/2-!4)/.
6)3)4
WWW3/!393#/.COM
JTUPNBOZJOEVTUSZJOTJEFSTTIBQJOHVQUPCFBNBKPSJOnFDUJPOQPJOUJOTPGUXBSFEFWFMPQNFOU
BOEEFQMPZNFOUXJUI40"8FC4FSWJDFT0QFO4PVSDFBOE"+"9BMMDPOWFSHJOHBTDSPTTQMBUGPSN
BOEDSPTTCSPXTFSBQQTCFDPNFUIFSVMFSBUIFSUIBOUIFFYDFQUJPO
*!.5!296/,5-%)335%
&ROMTHE%DITOR
)NTELLIGENT3/.
!*!83/!
3%!.2(/$9
*%&&"2/7.).'
!RE9OU"EING
3ERVED
4HE.EXT+ILLER!PP
*/(.#250)
!RCHITECTURAL&RAMEWORK
FOR""-ARKETPLACES
#USTOMER #ENTRIC3/!
0!5,,)04/.
*!)'!.%3(!.$32).)6!30!$-!.!"(5.)
#(2)3&!22%,,
3/!!PPLICATION3UCCESS
4HE/PEN'ROUP
!RCHITECTURE&RAMEWORK
"DDPSEJOHMZUIFUI*OUFSOBUJPOBM40"8FC4FSWJDFT&EHFBHBJOTFFLTUPPGGFSDPNQSFIFOTJWF
DPWFSBHFBOEBDUJPOBCMFJOTJHIUTUPUIFEFWFMPQFSTBSDIJUFDUT*5NBOBHFST$90TBOBMZTUT7$T
BOEKPVSOBMJTUTXIPMMCFBTTFNCMJOHBTEFMFHBUFTBOE7*1HVFTUTJO5IF3PPTFWFMU)PUFMJOEPXOUPXO
.BOIBUUBO+VOF
$PMPDBUFEXJUIUIFOE"OOVBM&OUFSQSJTF0QFO4PVSDF$POGFSFODF&YQPUIFFWFOUXJMMEFMJWFSUIF
JUFDIOPMPHZFEVDBUJPOBMBOEOFUXPSLJOHPQQPSUVOJUZPGUIFZFBS5IFTFUXPDPOGFSFODFQSPHSBNT
CFUXFFOUIFNXJMMQSFTFOUBDPNQSFIFOTJWFWJFXPGBMMUIFEFWFMPQNFOUBOENBOBHFNFOUBTQFDUTPG
JOUFHSBUJOHB40"TUSBUFHZBOEBO0QFO4PVSDFQIJMPTPQIZJOUPZPVSFOUFSQSJTF0VSPSHBOJ[JOHQSJODJQMF
JTUIBUEFMFHBUFTXJMMHPBXBZGSPNUIFJOUFOTFUXPEBZQSPHSBNSFQMFUFXJUIXIZUPBOEIPXUP
LOPXMFEHFEFMJWFSFEmSTUIBOECZJOEVTUSZFYQFSUT
7JTJUTPBFPTDPOGFSFODFTZTDPODPNGPSUIFNPTUVQUPUIFNJOVUFJOGPSNBUJPOJODMVEJOH
,FZOPUFT4FTTJPOT4QFBLFST4QPOTPST&YIJCJUPST4DIFEVMFFUD
'PSNPSFHSFBUFWFOUTWJTJUXXX&7&/544:4$0/DPN
COPYRIGHT ©2007 SYS-CON MEDIA
ALL RIGHTS RESERVED
&!4-!$!.$!3()4%2%.#%",%6).3
2/,&3)%'%23!.$*5$)4(*/.%3
!N/VERVIEWOF3#!AND3$/
!.$2%7"/2,%93)-/.,!73!.$(!,%(-!("/$
)S9OUR%NTERPRISE
!RCHITECTURE(EALTHY
$!6)$3,).4()#5-
0,%!3%$)30,!95.4),-!2#(
8FC3*"
.BS
$PNJOHUP/FX:PSL$JUZ
XXXBKBYXPSMEFYQPDPN
40"8PSME.BHB[JOF
GPDVTFTPOUIFCVTJOFTTBOE
UFDIOPMPHZPG4FSWJDF0SJFOUFE
"SDIJUFDUVSFTBOE8FC4FSWJDFT
*UUBSHFUTFOUFSQSJTFBQQMJDBUJPO
EFWFMPQNFOUBOENBOBHFNFOU
JOBMMJUTBTQFDUT
&OUFSQSJTF0QFO4PVSDF.BHB[JOF
&04JTUIFXPSMETMFBEJOH
QVCMJDBUJPOTIPXDBTJOHFWFSZ
BTQFDUPGQSPmUBCMF0QFO4PVSDF
TPMVUJPOTJOCVTJOFTTBOE
DPOTVNFSDPOUFYUT
&YIJCJUBOE4QPOTPSTIJQ*OGP
$BMMPSFNBJMFWFOUT!TZTDPODPN
gerBinding event is dispatched only when the Enter key is
pressed while typing in the ti1 TextInput component.
[RemoteClass]
RemoteClass can be used to bind an ActionScript
class to a Java class or a ColdFusion CFC. This will allow
for automatic data type conversions. Below is a sample
of an ActionScript class named MyClass in the package
com.mydomain being bound to a Java class named
MyClass in the package com.mydomain:
package com.mydomain {
[Bindable]
[RemoteClass(alias=”com.mydomain.MyClass”)]
public class MyClass {
public var id:int;
public var myText:String;
}
}
[Style]
The Style metadata tag is used to define custom style
properties for your components. Simply add the Style
metadata tag or tags to your class definition and then
use the getStyle method to retrieve its value.
Listings 11 and 12 give examples of how to define
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
updateDisplayList function is overridden and the custom
styles are used to draw the circle border and fill.
Figure 7 shows the results of Listing 12 and Listing 13.
By now you should have had a few “Wow, I know
where I could have used that” or “Hmm, I think I will
try this metadata tag in a new project.” If you haven’t,
then you need to go back and read the article again.
OK, so what I’m trying to say is that the metadata tags
provided for us by the Adobe Flex team are not only
extremely powerful, allowing us to extend and customize what we do with Flex, but are also very easy to use.
They are a very quick way to accomplish a great deal
with only a few lines of code. If you’re not using these
tags, you’re working too hard to accomplish things that
are built into Flex 2.
•
•
Listing 1 A simple use of [Bindable]
<?xml version=”1.0” encoding=”utf-8”?>
<mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml”
backgroundColor=”#FFFFFF”>
<mx:Script>
<![CDATA[
[Bindable]
private var me:String=”Rich Tretola”;
]]>
</mx:Script>
<mx:Panel title=”Simple Binding” width=”500” height=”90”
paddingTop=”10” paddingLeft=”10” paddingRight=”10” paddingBottom=”10”
layout=”horizontal”>
<mx:Label text=”{me}”/>
</mx:Panel>
</mx:Application>
Listing 2 Using [Bindable] with getters and setters
<?xml version=”1.0” encoding=”utf-8”?>
<mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml”>
<mx:Script>
<![CDATA[
private var _phoneNumber:String = “”;
// Bind getter function to phoneNumberChanged event
[Bindable(event=”phoneNumberChanged”)]
public function get phoneNumber():String {
return _phoneNumber;
}
// Setter method.
public function set phoneNumber(value:String):void {
if (value.length<10) {
_phoneNumber = value;
} else {
_phoneNumber = phoneFormatter.format(value);
}
// Create and dispatch event
var eventObj:Event = new Event(“phoneNumberChanged”);
dispatchEvent(eventObj);
}
]]>
</mx:Script>
<mx:PhoneFormatter id=”phoneFormatter”
formatString=”(###) ###-####” validPatternChars=”#-()
“/>
<mx:Panel title=”Bind with Getters and Setters”
width=”500” height=”90”
paddingTop=”10” paddingLeft=”10” paddingRight=”10” paddingBottom=”10”
layout=”horizontal”> <mx:TextInput id=”ti1” change=”phoneNumber=ti1.text”
maxChars=”10” restrict=”0-9”/>
<mx:TextInput id=”ti2” text=”{phoneNumber}”/>
</mx:Panel>
</mx:Application>
Listing 3 Custom Button class named MyButton
package
{
import mx.controls.Button;
[DefaultProperty(“label”)]
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
Erickson from Wiley Publishing, Inc./Wrox Press. To
pre-order please visit http://www.everythingflex.com
or http://www.amazon.com/Professional-Flex-2-RichTretola/dp/0470102675.
30
}
Listing 4 Using the MyButton class wih [DefaultProperty]
<?xml version=”1.0” encoding=”utf-8”?>
<mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml”
xmlns:comps=”*”>
<comps:MyButton>
<mx:String>Test</mx:String>
January/February 2007
</comps:MyButton>
</mx:Application>
Listing 5 Custom ButtonLabel class using [Event]
package
{
import mx.controls.Button;
import flash.events.Event;
// Define the custom event
[Event(name=”labelChanged”, type=”flash.events.Event”)]
public class ButtonLabel extends Button {
// property to hold label value
private var _myLabel:String;
// public setter method
public function set myLabel(s:String):void {
_myLabel = s;
this.label = s;
// Create and dispatch custom event
var eventObj:Event = new Event(“labelChanged”);
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”
xmlns:comps=”*”
backgroundColor=”#FFFFFF”>
<mx:Script>
<![CDATA[
import mx.controls.Alert;
import flash.events.Event;
// method to handle custom event
public function labelChanged(eventObj:Event):void {
myTA.text= myTA.text + “\n”+ eventObj.target.label;
myTA.verticalScrollPosition = myTA.verticalScrollPosition +
<![CDATA[
[Inspectable(defaultValue=”Visa”,
enumeration=”Visa,Mastercard,Discover,American Express”
category=”Credit Card” type=”String”)]
public var ccType:String;
]]>
</mx:Script>
</mx:HBox>
Listing 10 Using [NonCommittingChangeEvent]
<?xml version=”1.0” encoding=”utf-8”?>
<mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml”
backgroundColor=”#FFFFFF”>
<mx:Script>
<![CDATA[
import flash.events.Event;
private var eventObj:Event;
[Bindable(event=”triggerBinding”)]
[NonCommittingChangeEvent(“change”)]
private var s:String;
private function triggerBinding():void{
eventObj = new Event(“triggerBinding”);
dispatchEvent(eventObj);
}
]]>
</mx:Script>
<mx:Panel title=”NonCommittingChangeEvent Sample” width=”500”
height=”90”
paddingTop=”10” paddingLeft=”10” paddingRight=”10” paddingBottom=”10”
layout=”horizontal”>
<mx:TextInput id=”ti1” change=”s=ti1.text” enter=”triggerBinding()”
/>
<mx:TextInput id=”ti2” text=”{s}” />
</mx:Panel>
</mx:Application>
20;
}
]]>
</mx:Script>
<mx:Panel title=”Event Sample” width=”500” height=”275”
paddingTop=”10” paddingLeft=”10” paddingRight=”10” paddingBottom=”10”
layout=”absolute”>
<mx:TextInput id=”buttonLabelTI”
change=”myButton.myLabel=buttonLabelTI.text” x=”10” y=”9”/>
<!--Instantiate custom class and define method to handle labelChanged event-->
<comps:ButtonLabel id=”myButton” labelChanged=”labelChanged(event)
;”
x=”10” y=”39”/>
<mx:TextArea id=”myTA” width=”200” height=”200” x=”249” y=”10”/>
</mx:Panel>
</mx:Application>
Listing 7 Add the Effect metadata tag
...
// Define the custom event
[Event(name=”labelChanged”, type=”flash.events.Event”)]
[Effect(name=”labelChangedEffect”, event=”labelChanged”)]
public class ButtonLabel extends Button {
...
Listing 8 Add labelChangedEffect to the Component
Instantiation MXML Tag
<comps:ButtonLabel id=”myButton” labelChanged=”labelChanged(event);”
labelChangedEffect=”myEffect” x=”10” y=”39”/>
Listing 9 Custom component with [Inspectable] defined
<?xml version=”1.0” encoding=”utf-8”?>
<mx:HBox xmlns:mx=”http://www.adobe.com/2006/mxml”>
Listing 11 Custom Class CustomCircle using [Style] tags
package
{
import mx.core.UIComponent;
[Style(name=”borderColor”,type=”uint”,format=”Color”,inherit=”no”)]
[Style(name=”fillColor”,type=”uint”,format=”Color”,inherit=”no”)]
public class CustomCircle extends UIComponent {
public function CustomCircle(){
super();
}
override protected function updateDisplayList(unscaledWidth:Number,
unscaledHeight:Number):void {
super.updateDisplayList(unscaledWidth, unscaledHeight);
graphics.lineStyle(1, getStyle(“borderColor”), 1.0);
graphics.beginFill(getStyle(“fillColor”),1.0);
graphics.drawEllipse(0,0,100,100);
}
}
}
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”
xmlns:comps=”*”
backgroundColor=”#FFFFFF”>
<mx:Panel title=”Style Sample” width=”200” height=”200”
paddingTop=”10” paddingLeft=”10” paddingRight=”10” paddingBottom=”10”
layout=”horizontal”>
<comps:CustomCircle borderColor=”#000000” fillColor=”#FF0000” />
</mx:Panel>
</mx:Application>
<mx:Script>
January/February 2007
31
flexination
Video Rock ’n Roll
with Flex 2
Streaming videos
by Michael Givens
f
Figure 1
lex 2 and the Flash Media Server
are a match made in heaven. By
combining the two technologies, streaming Flash videos at
my office has become a nice part
of my daily routine and a good excuse
to add another monitor to my desktop.
Whether your musical genre taste is classical or rock ’n roll, it’s relatively easy to
quickly create a desktop library of Flash
videos. In this article, I’ll describe one
approach that will have you streaming in
no time.
You will need the Flex 2 Builder (with
Flex 2 SDK), the Flash Media Server (the
Macromedia Communication Server
works as well), and at least one or two
Flash videos (flv). I will omit the installation details in this discussion and get
to the good stuff right away. For a quick
demo, try this example: http://www.
insideflex.com/fmsvideo/bin/fmsvideo.
32
html. The full source code is available at
http://www.insideflex.com/fmsvideo/bin/
srcview/index.html.
Stepwise, first create a new Flex 2
project in the Flex 2 Builder IDE (for this
project there’s one named fmsvideo_flex).
The code and the explanation for the
main MXML file are discussed below (see
Listing 1).
The application is initialized with
the initApp()1 function where the
VideoDisplay control is displayed and the
HttpService is called. This accomplishes
two main things. First, Flex creates a
VideoDisplay control (http://livedocs.
macromedia.com/flex/201/langref/mx/
controls/VideoDisplay.html) with no visible user interface; by setting the source
attribute to an flv and the autoPlay attribute to false, the control gets displayed in
the UI. Second, the data (see Listing 2) for
the ComboBox video list is requested.
The creationComplete attribute
includes a call to the PageLoaded()2
function that kicks off, at one-second
intervals, a function that determines if the
HttpService is complete; the readytoContinue()3 function loads the videos’ names
and labels into an array, dp, that is the
dataProvider of the ComboBox control,
cbxVideos.
Selecting a video triggers the comboBox’s change event and the function,
playVideo(cbxVideo.selectedItem.name)4,
and the video begins streaming its content.
The standard Play, Mute, Pause
and Stop buttons are included, providing complete playback control.
Utilizing an EventListener, vidDisplay.
addEventListener(Event.COMPLETE,
onComplete)5 , the buttons are enabled
or disabled in a logical fashion depending
on the video’s playback state.
This article would not be complete
without discussing the placement of
the Flash video flvs. You should create a
new Flash Media Server application – by
adding new folders (for this demo, videos\streams\_definst_) in the applications
folder (for a default installation, you would
end up with this folder: “C:\Program Files\
Macromedia\Flash Media Server 2\applications\videos\streams\_definst_”). Copy the
flvs and paste them here. If you need some
flvs for your VideoPlayer, you can grab the
URLs from YouTube.com and use a tool
you’ll find at TechCrunch – http://www.
techcrunch.com/get-youtube-movie/. This
effectively allows you to download the flvs
of your choice.
I hope you found this article useful.
If you have any follow-up questions, feel
free to ping me at the e-mail address
listed with this article. Rock on!
Mike Givens is the CTO of U Saw It
Enterprises, a Web technology consulting
firm based in Marietta, GA. He is an Adobe
Community Expert (Flex) as well as an
Adobe Corporate Champion known to share
his experience and evangelism of all things
Adobe. Certified in both ColdFusion 5 and
as an Advanced CFMX Developer, he has
been using ColdFusion since the days of
Allaire Spectra. Mike blogs at http://www.
flexination.info/. info@webmxml.com
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:
mx=”http://www.adobe.com/2006/mxml” initialize=” HYPERLINK
\l “initAppfx” initApp()1” creationComplete=” HYPERLINK
\l
“PageLoadedfx” PageLoaded()2” layout=”vertical”>
<!—this http service is used to supply the dataProvider for
the ComboBox list of videos
<mx:HTTPService id=”videoService” url=”theVideos.xml”
showBusyCursor=”true” />
for (var i:Number=0; i<videoService.lastResult.videos.
video.length; i++) {
aryTemp.push({name: videoService.lastResult.videos.video[i].
name, label: videoService.lastResult.videos.video[i].label});
}
dp = aryTemp;
cbxVideo.dataProvider = dp;
}
blnLoadDelayRunOnce = true;
<mx:Script>
}
<![CDATA[
import mx.events.VideoEvent;
import mx.controls.Alert;
private function playVideo(stream:String)4:void {
if (stream!=null) {
[Bindable] private var dp:Array;
[Bindable] private var bgimage:String = “”;
private var blnLoadDelayRunOnce:Boolean = false;
//Alert.show(stream);
vidDisplay.autoBandWidthDetection = false;
vidDisplay.source = “rtmp:// your_domain /videos/” + stream
+ “.flv”;
private function initApp()1:void {
vidDisplay.autoBandWidthDetection = false;
vidDisplay.source = “rtmp://your_domain/videos/
defleppard_photograph.flv”;
videoService.send();
}
vidDisplay.addEventListener(Event.COMPLETE, onComplete)5;
vidDisplay.play();
btnPlay.enabled = false;
btnMute.enabled = true;
btnPause.enabled = true;
btnStop.enabled = true;
private function PageLoaded()2:void {
var myTimer:Timer = new Timer(1000, 0);
swfLoad.source = “delirio.swf”;
}
}
myTimer.addEventListener(“timer”, onTimer);
myTimer.start();
}
private function onComplete(event:Event):void {
swfLoad.source = null;
btnPlay.enabled = true;
private function onTimer(event:TimerEvent):void {
if (!blnLoadDelayRunOnce) {
readytoContinue();
}
}
btnMute.enabled = false;
btnPause.enabled = false;
btnStop.enabled = false;
}
private function pauseVideo(stream:String):void {
private function readytoContinue()3:void {
if (videoService.lastResult.videos.video!=undefined) {
if (stream!=null) {
vidDisplay.pause();
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;
btnMute.enabled = false;
eo(cbxVideo.selectedItem.name)” enabled=”false”/>
btnPlay.enabled = true;
Video(cbxVideo.selectedItem.name)” enabled=”false”/>
swfLoad.source = null;
<mx:Button id=”btnPlay” label=”Play” click=”playVid
<mx:Button id=”btnPause” label=”Pause” click=”pause
}
}
eo(cbxVideo.selectedItem.name)” enabled=”false”/>
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}”
labelField=”label” change=” HYPERLINK
swfLoad.source = null;
<mx:Button id=”btnStop” label=”Stop” click=”stopVid
<mx:Button id=”btnMute” label=”Mute” click=”muteVid
\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”/>
<mx:SWFLoader id=”swfLoad” source=”{null}” width=”50”
swfLoad.source = “delirio.swf”;
}
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
34
<video>
<label>Select a video...</label>
Advertiser
URL
Phone
Page
Adobe
www.adobe.com
2
CFDynamics
www.cfdynamics.com
866-233-9626
6
</video>
CFUnited
www.cfunderground.com
19
<video>
<name>null</name>
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
JavaOne
11
Intergral
www.fusiondebug.com
5
Omniture
11
PaperThin
www.paperthin.com
37
Stream57
www.stream57.com
212-909-2550x1012
15
Vitalstream
www.vitalstream.com
800-254-7554
24
<video>
<label>Def Leppard - Love Bites</label>
<name>defleppard_love_bites</name>
</video>
</videos>
January/February 2007
/THERCOMPANIESINTHISMAGAZINESPENTALOTOFTIMEONPRETTYADS!S
YOUCANSEEWEDIDNOT7ESPENTOURTIMEHIRINGTHEBESTPEOPLEAND
TRAINING THEM TO DELIVER OUTSTANDING SUPPORT FOR YOUR WEBSITE 7E
SPENTOURTIMEBUILDINGASTATEOFTHEARTDATACENTERANDSTAFFINGITWITH
PEOPLEWHOCAREABOUTYOURWEBSITELIKEITSTHEIROWN#OMPASSION
RESPECTCREDIBILITYOWNERSHIPRELIABILITYhNEVERSAYNOvANDEXCEED
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%-!),
Was this manual useful for you? yes no
Thank you for your participation!

* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project

Download PDF

advertising