Archive for July, 2006

Flash Player 9 security white paper released on Developer Center

Developer Center had a few updates today, and one of the more notable updates was the Flash Player 9 security white paper.

Learn how the Flash Player 9 security architecture and new APIs help you deliver trusted content to your users.

See White paper: Flash Player 9 security (PDF, 584k) [Adobe.com]

Using FlashVars with ActionScript 3.0

I was building a small app in Flash/ActionScript 3.0 over the weekend and needed to find out how to use FlashVars (Using FlashVars to pass variables to a SWF) to pass variables to my SWF file.

Previously, in ActionScript 2.0, you could pass variables along the query string or using FlashVars and the variables would be available in _level0, in ActionScript 3.0, it is a bit tricker:

<!-- using query string -->
<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"
codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0"
width="550"
height="400"
align="middle"
id="main">
<param name="allowScriptAccess" value="sameDomain" />
<param name="movie" value="main.swf?one=1&two=2" />
<param name="quality" value="high" />
<param name="bgcolor" value="#ffffff" />
<embed src="main.swf?one=1&two=2"
width="550"
height="400"
autostart="false"
quality="high"
bgcolor="#ffffff"
name="main"
align="middle"
allowScriptAccess="sameDomain"
type="application/x-shockwave-flash"
pluginspage="http://www.macromedia.com/go/getflashplayer" />
</object>

The previous code passes two variables (one and two) along the querystring (main.swf?one=1&two=2) and makes those variables available in your SWF file in the root’s loaderInfo object (or more accurately, within the loaderInfo’s parameters property).

Also, the same technique works if you pass the variables within a FlashVars parameter, as seen below:

&lt!-- using FlashVars -->
<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"
codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0"
width="550"
height="400"
align="middle"
id="main">
<param name="allowScriptAccess" value="sameDomain" />
<param name="movie" value="main.swf" />
<param name="quality" value="high" />
<param name="bgcolor" value="#ffffff" />
<param name="FlashVars" value="one=1&two=2" />
<embed src="main.swf"
width="550"
height="400"
autostart="false"
quality="high"
bgcolor="#ffffff"
FlashVars="one=1&two=2"
name="main"
align="middle"
allowScriptAccess="sameDomain"
type="application/x-shockwave-flash"
pluginspage="http://www.macromedia.com/go/getflashplayer" />
</object>

But enough of my rambling, how do you access these from within your FLA document? Read on!

// AS3
var tf:TextField = new TextField();
tf.autoSize = TextFieldAutoSize.LEFT;
tf.border = true;
addChild(tf);

tf.appendText("params:" + "\n");
try {
var keyStr:String;
var valueStr:String;
var paramObj:Object = LoaderInfo(this.root.loaderInfo).parameters;
for (keyStr in paramObj) {
valueStr = String(paramObj[keyStr]);
tf.appendText("\t" + keyStr + ":\t" + valueStr + "\n");
}
} catch (error:Error) {
tf.appendText(error.toString());
}

The previous code creates a new TextField instance on the Stage (named tf), uses a for..in loop to iterate over each of the passed parameters and displays the parameter’s names and values in the text field.

Nothing ground breaking or overly fascinating, but hopefully this helps somebody out there or saves them about 3 minutes of searching.

Spry 1.2 released on Adobe Labs

Good news for Spry users, Adobe just released version 1.2 of Spry!
I had a chance to play around with it a bit last weekend and was really impressed. I managed to easily parse some XML and build expanding/collapsing tables and record viewers as well as integrate Spry with Google Maps and Yahoo! Maps (I’ll post some examples when I get some time).

In the meantime, go download the latest version of Spry and check out the changelist.

For those of you who aren’t familiar with Spry (yet have managed to read this far down), here’s a brief clip from the release notes:

The Spry framework for Ajax is a JavaScript library for web designers that provides functionality that allows designers to build pages that provide a richer experience for their users. It is designed to bring Ajax to the web design community who can benefit from Ajax, but are not well served by other frameworks. The first release of the Spry framework is a preview of the data capabilities that enable designers to incorporate XML data into their HTML documents using HTML, CSS, and a minimal amount of JavaScript, without the need for refreshing the entire page. The Spry framework is HTML-centric, and easy to implement for users with basic knowledge of HTML, CSS and JavaScript. The framework was designed such that the markup is simple and the JavaScript is minimal. The Spry framework can be used by anyone who is authoring for the web in their tool of choice. (more)

Good Spry/PHP tutorial

Just spotted this on digg. macdiggs.com has a good overview of using Spry (Adobe’s AJAX framework) with PHP and MySQL. Go download Spry and follow along!

[Integration of Spry and PHP/MySQL (Spry primer) via digg]

Using the Timer class in ActionScript 3.0

Another great new addition in ActionScript 3.0 is the Timer class (flash.utils.Timer), which essentially replaces the setInterval() and setTimeout() methods in ActionScript 2.0. For example, here’s an example of the setTimeout() method in ActionScript 2.0:

// AS2
var intID:Number = setTimeout(runOnce, 1000); // 1 second
function runOnce():Void {
trace("runOnce() called @ " + getTimer() + " ms");
}

In ActionScript 3.0, the same code could be rewritten as follows:

// AS3
var myTimer:Timer = new Timer(1000, 1); // 1 second
myTimer.addEventListener(TimerEvent.TIMER, runOnce);
myTimer.start();

function runOnce(event:TimerEvent):void {
trace("runOnce() called @ " + getTimer() + " ms");
}

Note that the Timer() constructor takes two parameters. The first parameter controls how frequently the TimerEvent.TIMER event gets dispatched (in milliseconds). The second parameter is the number of times that the TimerEvent.TIMER event will be dispatched before stopping. In this example, the timer will dispatch only once before quitting. If you set the second parameter to 0 (zero) or omitted it completely, the timer would run forever (or until you called the stop() method on the timer instance.

If you wanted the code to continuously run in ActionScript 2.0, you would use the setInterval() method instead of the setTimeout() method, as seen in the following example:

// AS2
var intID:Number = setInterval(runMany, 1000); // 1 second
function runMany():Void {
trace("runMany() called @ " + getTimer() + " ms");
}

The previous code snippet would continue to run until the interval was stopped by calling the clearInterval() method and passing in the interval id (which was saved in the variable intID). The same code could be rewritten in ActionScript 3.0 as follows:

// AS3
var myTimer:Timer = new Timer(1000); // 1 second
myTimer.addEventListener(TimerEvent.TIMER, runMany);
myTimer.start();

function runMany(event:TimerEvent):void {
trace("runMany() called @ " + getTimer() + " ms");
}

Playing back FLVs with ActionScript 3.0

OK, this isn’t a huge difference between ActionScript 2.0 and ActionScript 3.0, but it is good to know anyways…

In previous versions of ActionScript, in order to play back and FLV (without using a component) you’d need to create a Video object in the library, add it to the Stage, and give it an instance name, as seen in the following example:

// AS2
// requires: Video symbol on Stage with instance name of "myVideo".
var nc:NetConnection = new NetConnection();
nc.connect(null);
var ns:NetStream = new NetStream(nc);
myVideo.attachVideo(ns);
ns.play("http://www.helpexamples.com/flash/video/cuepoints.flv");

In ActionScript 3.0, you can now create a new Video object using the Video() constructor, and adding it to the display list using the addChild() method, as seen in the following example:

// AS3
var myVideo:Video = new Video();
addChild(myVideo);
var nc:NetConnection = new NetConnection();
nc.connect(null);
var ns:NetStream = new NetStream(nc);
myVideo.attachNetStream(ns);
ns.play("http://www.helpexamples.com/flash/video/cuepoints.flv");

Where it starts to get a bit more interesting, is when you want to work with video cue points and meta data. ActionScript 2.0 used the onCuePoint and onMetaData event handlers to process cue points and meta data, as shown in the following example:

// AS2
// requires: Video symbol on Stage with instance name of "myVideo".
var nc:NetConnection = new NetConnection();
nc.connect(null);
var ns:NetStream = new NetStream(nc);
ns.onCuePoint = function(infoObject:Object):Void {
trace("cuePoint");
}
ns.onMetaData = function (infoObject:Object):Void {
trace("metaData");
}
myVideo.attachVideo(ns);
ns.play("http://www.helpexamples.com/flash/video/cuepoints.flv");

In ActionScript 3.0, you have a few more options for handling the information. One of the simplest methods is to create a simple Object which processes the onCuePoint and onMetaData event handlers in ActionScript 3.0. You can see an example of this in the following code:

// AS3
var customClient:Object = new Object();
customClient.onCuePoint = cuePointHandler;
customClient.onMetaData = metaDataHandler;

var myVideo:Video = new Video();
addChild(myVideo);

var nc:NetConnection = new NetConnection();
nc.connect(null);
var ns:NetStream = new NetStream(nc);
ns.client = customClient;
myVideo.attachNetStream(ns);
ns.play("http://www.helpexamples.com/flash/video/cuepoints.flv");

function cuePointHandler(infoObject:Object):void {
trace("cuePoint");
}
function metaDataHandler(infoObject:Object):void {
trace("metaData");
}

This code begins by creating a new Object instance named customClient which defines listeners for the onCuePoint and onMetaData event handlers. The cuePointHandler and metaDataHandler variables point to user-defined functions which are defined later in the code. Later, the client property on the NetStream instance is set to the customClient object.

Another way of handling the cue points and meta data is to create a new class which you can use with the client property. The code is roughly similar to the previous example:

// AS3
var myVideo:Video = new Video();
addChild(myVideo);

var nc:NetConnection = new NetConnection();
nc.connect(null);
var ns:NetStream = new NetStream(nc);
ns.client = new CustomClient();
myVideo.attachNetStream(ns);
ns.play("http://www.helpexamples.com/flash/video/cuepoints.flv");

This time, instead of defining an object to handle the onCuePoint and onMetaData event handlers, the code is moved into an external file named “CustomClient”, which contains the following code:

package {
public class CustomClient {
public function onCuePoint(infoObject:Object):void {
trace("onCuePoint");
}
public function onMetaData(infoObject:Object):void {
trace("onMetaData");
}
}
}

On the other hand, if you wanted to ignore the cue point and meta data information from an FLV altogether, you could use either one of the following snippets:

// AS3
var myVideo:Video = new Video();
addChild(myVideo);

var nc:NetConnection = new NetConnection();
nc.connect(null);
var ns:NetStream = new NetStream(nc);
ns.client = new Object();
myVideo.attachNetStream(ns);
ns.play("http://www.helpexamples.com/flash/video/cuepoints.flv");

The previous example sets the client property to a new Object instance, which doesn’t have any event handlers for the onCuePoint and onMetaData callbacks. As an alternative, you could also set up an event listener for the AsyncErrorEvent.ASYNC_ERROR event which does nothing, as seen in the following code:

// AS3
var myVideo:Video = new Video();
addChild(myVideo);

var nc:NetConnection = new NetConnection();
nc.connect(null);
var ns:NetStream = new NetStream(nc);
ns.addEventListener(AsyncErrorEvent.ASYNC_ERROR, asyncErrorEventHandler);
myVideo.attachNetStream(ns);
ns.play("http://www.helpexamples.com/flash/video/cuepoints.flv");

function asyncErrorEventHandler(event:AsyncErrorEvent):void {
// ignore
}

Creating clickable movie clips in ActionScript 3.0

One of the biggest improvements in the ActionScript 3.0 language is the new event model. In previous versions of ActionScript, the event model may have differed slightly (or not so slightly) depending on which symbols you were using. A MovieClip’s event model may have been different from a component or other class/symbol, but now, everything uses the EventDispatcher and addEventListener() method. For an example of the old versus new methods, look at the following example:

// AS2
this.createEmptyMovieClip("mc", this.getNextHighestDepth());
mc.beginFill(0xFF0000);
mc.moveTo(0, 0);
mc.lineTo(100, 0);
mc.lineTo(100, 80);
mc.lineTo(0, 80);
mc.lineTo(0, 0);
mc.endFill();
mc._x = 80;
mc._y = 60;
mc.onRelease = clickHandler;

function clickHandler():Void {
trace("You sunk my battleship!");
}

NOTE: This code often uses an anonymous method, such as: mc.onRelease = function():Void {...}.

In ActionScript 3.0, the same code could be rewritten as follows:

// AS3
var mc:MovieClip = new MovieClip();
mc.graphics.beginFill(0xFF0000);
mc.graphics.drawRect(0, 0, 100, 80);
mc.graphics.endFill();
mc.x = 80;
mc.y = 60;
mc.addEventListener(MouseEvent.CLICK, clickHandler);
addChild(mc);

function clickHandler(event:MouseEvent):void {
trace("You sunk my battleship!");
}

If you test the following code, you’ll notice that the shape on the Stage is clickable, although the mouse cursor doesn’t show the hand icon. If you want the hand cursor to appear when your mouse is over the movie clip, add the following line of code before the call to the addEventListener() method:

mc.buttonMode = true;

Creating new MovieClips in ActionScript 3.0

Creating new instances of a class has been greatly simplified in ActionScript 3.0. In previous versions of ActionScript, you needed to call createEmptyMovieClip() or createTextField() if you wanted to create a new MovieClip or TextField. Now, in ActionScript 3.0, you can simply call new MovieClip() or new TextField() directly, as shown in the following examples:

// AS2
this.createEmptyMovieClip("mc", this.getNextHighestDepth());
mc.beginFill(0xFF0000);
mc.moveTo(0, 0);
mc.lineTo(100, 0);
mc.lineTo(100, 80);
mc.lineTo(0, 80);
mc.lineTo(0, 0);
mc.endFill();
mc._x = 80;
mc._y = 60;

The previous code creates a new movie clip instance, draws a red rectangle which is 100×80 pixels, and moves the instance to 80,60 on the Stage. Compare that to the following code which does the exact same thing, although using the new drawRect() method instead of having to use the moveTo() and lineTo() methods:

// AS3
var mc:MovieClip = new MovieClip();
mc.graphics.beginFill(0xFF0000);
mc.graphics.drawRect(0, 0, 100, 80);
mc.graphics.endFill();
mc.x = 80;
mc.y = 60;
addChild(mc);

Note that there are a few differences. Most obvious is the use of the MovieClip() constructor instead of ActionScript 2.0’s createEmptyMovieClip(). Other notable differences are that the drawing methods (beginFill(), drawRect(), and endFill()) are called on the graphics property instead of on the instance itself. Also, in ActionScript 3.0, the x and y properties aren’t prefixed with underscores. Finally, in ActionScript3.0 the instance isn’t added to the display list until you explicitly call the addChild() method.

TIP: In addition to the drawRect() method, you can also call the drawCircle(), drawEllipse(), or drawRoundRect() methods to draw shapes.

If you wanted to instead draw a rounded rectangle, instead of calling the lineTo() and curveTo() methods, you could use the new drawRoundRect() method, as shown in the following code:

mc.graphics.drawRoundRect(0, 0, 100, 80, 15, 15);