Jul 23

The Problem.

Well the problem you’re facing is pretty simple, but it can also be tricky. I had the same problem some time ago, and it pretty much ruined my day. (mainly because I rush and I don’t read the documentation, which is BAD by the way)

The Solving.

There are several reasons for which you will get an error message when trying to import a component , but if you have the feeling that you did everything right and it sill doesn’t work, this may help you lot. So, don’t forget that you have to actually drag an instance of the component on the scene from the component’s panel (Window->Components to open it) no matter if you import the component in actionscript. You can delete the component from the stage afterwards but the important thing is to have an instance on your library.

Jul 20

Introduction. Associative Arrays.

An associative array uses keys to organize stored values. That means that you can use strings instead of indexes, so that the next statement becomes perfectly legal.

[-]View Code ACTIONSCRIPT
buttons['home'] = new Button(); //buttons is an associative array
contentSprites[1] = new Sprite(); //contentSprites is an numeric indexed array

Working Example. Dictionary Class.

Although the principle behind the associative array is very simple, we usually use the numeric indexed array. However there are many scenarios in which an associative array would do the job much easier, more organized and nonetheless less cryptic for others.

But what I would really like to talk about is the Dictionary Class. The Dictionary Class is very similar indeed with a associative array but it has the great feature that it can use as indexes any objects from Movieclips to Tweens (usually the object passed as index is an instance of the Object Class, but theoretic it could be anything ).

Next is an example that shows you how and most of all why you should use the Dictionary Class in certain scenarios.

[-]View Code ACTIONSCRIPT
package  {
	import fl.controls.Button;
	import flash.display.Sprite;
	import flash.ui.Mouse;
	import flash.utils.Dictionary;
	import flash.events.MouseEvent;
 
	public class dictonaryEx extends Sprite {
 
		private const buttonsObjects:Array = new Array(
		{ label:"Home", listener:$btn1, no:0 },
		{ label:"Products", listener:$btn2, no:1 },
		{ label:"Clients", listener:$btn3, no:2 },
		{ label:"Contact", listener:$btn4 , no:3 }
		);
 
		public function dictonaryEx() {
			var buttons:Dictionary = new Dictionary();
 
			for each(var obj:Object in buttonsObjects) {
				buttons[obj] = new Button();
				buttons[obj].label = obj.label;
				buttons[obj].addEventListener(MouseEvent.CLICK, obj.listener);
 
				buttons[obj].x = buttons[obj].width * obj.no;
				addChild(buttons[obj]);
 
			}
		}
 
		private function $btn1(evt:MouseEvent):void {
			trace(evt.currentTarget.label+' pressed')//output  "Home pressed"
		}
 
		private function $btn2(evt:MouseEvent):void {
			trace(evt.currentTarget.label+' pressed')//output  "Products pressed"
		}
 
		private function $btn3(evt:MouseEvent):void {
			trace(evt.currentTarget.label+' pressed')//output  "Clients pressed"
		}
 
		private function $btn4(evt:MouseEvent):void {
			trace(evt.currentTarget.label+' pressed')//output  "Contact pressed"
		}
	}
 
}

Closer look to the example.

First, we can look at the buttonsObjects array as a model from the MVC’s terminology, a entity that holds all the data for creating visual buttons. Depending on how complex the buttons are the buttonsObjects array can hold more complex objects. For this example, I choose to use only three properties label, listener, no (the label is the text that will show up on the button, the listener is the function that will be called when the mouse click ocurs and the no is the index of the button counting from left to right). In the dictonaryEx constructor we create a visual button using the Button Class for each object in the buttonsObjects array.

I think Dictionary Class is a great utility first because it does the same thing as an indexed array but with less code and in a way that others will understand better what you did. I certainly use it, but not abuse it.

If you have any questions please leave a comment. Cheers mates!

May 20

Introduction.

Fortunately, Flex 3 has full support for deep linking, that means that you can enable the browser’s back button really easy. The guys from Adobe made 2 classes for this purpose, the HistoryManager class and the BrowserManager class. Both of them are singleton. You cannot use both BrowserManager and HistoryManager in the same application. So in the next example, we will see how to enable the browser’s back button in a fast deployed Flex 3 application, using only mx tags and of course the provided history Javascript file.

Using the browser’s back button with Flex 3 in a fast deployed application.

In this example we will use the HistoryManager class, although it doesn’t offer us the flexibility that BrowserManager class does, it helps us to enable the browser’s back button really quick using only mx tags.

Ok, first we have to copy in our project folder the Adobe provided history folder. If you use Flex 3 Builder you have to follow the next steps:

1. Select Project > Properties.
2. Select the Flex Compiler option.
3. Select the “Enable integration with browser navigation” option.

After that, Flex 3 Builder will copy the history folder in your project folder.

If you use FlexSDK, just copy the history folder located here: (FlexSDK main folder) /templates/client-side-detection-with-history/history to your project folder. The next steps are really easy.

Step 1: Create your mxml file. Here we will create an accordion that changes whenever the browser’s back button is pressed. Here is the code.

<?xml version="1.0"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
	<mx:Accordion
		historyManagementEnabled="true"
		height="80%"
		width="30%"
		>
		<mx:VBox label="Panel 1">
			<mx:TextArea width="100%" height="100%" borderColor="0xFFFFFF" text="Some text for the first panel." />
		</mx:VBox>
		<mx:VBox label="Panel 2">
			<mx:TextArea width="100%" height="100%" borderColor="0xFFFFFF" text="Now here we have some text for the second panel." />
		</mx:VBox>
		<mx:VBox label="Panel 3">
			<mx:TextArea width="100%" height="100%" borderColor="0xFFFFFF" text="And to finish the things" />
		</mx:VBox>
	</mx:Accordion>
</mx:Application>

The historyManagementEnabled=”true” line does all the trick. Now you have an accordion that reacts to browser’s control. Of course the historyManagementEnabled=”true” property is available not only to the accordion container, but also to other containers that have user interaction (like TabNavigator for example). I think this is the easiest way to enable the browser’s back button.

Ok, now that we have the SWF, we have to place it into a HTML wrapper. The best way to insert a SWF into a HTML is by using SWFobject. In your project folder copy the swfobject.js into a folder with the same name as the file (swfobject). Here is the HTML code for the wrapper

[-]View Code HTML4STRICT
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
    <head>
 
		<title>Back button example in Flex</title>
                <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
		<link href="history/history.css" rel="stylesheet" type="text/css"/>
		<link href="main.css" rel="stylesheet" type="text/css"/>
 
 
    </head>
 
 
	<body>
 
        <div id="flashcontent">
            This content here will be replaced by the SWF.
        </div>
		<script src="swfobject/swfobject.js" type="text/javascript"></script>
        <script src="history/history.js" type="text/javascript"></script>
		<script type="text/javascript">
		   var so = new SWFObject("backbutton.swf", "backbutton", "100%", "100%", "8", "#CCCCCC");
		   so.addParam("allowScriptAccess", "always");
		   so.addParam("swliveconnect", "true")
		   so.write("flashcontent");
		</script>
 
    </body>
</html>

The code simply creates a div with “flashcontent” id and puts in it the backbutton.swf (for better understanding please check the swfobject examples). Don’t forget to add the main.css to your project folder for a nice layout. This is it, you have enable the browser’s back button in your fast deployed application.
Here is a working example.

I think that Adobe made a great thing with the HistoryManager class and the BrowserManager class in Flex, so that standard browser experiences are the same with Flash as they are with HTML. If you have any questions please leave a comment.

Cheers!

May 12

Introduction.

Breaking standard browser experiences with Flash is an old problem and i’ve seen that although there are a bunch of tutorials for As2 and some for As3, using different or same adapted Javascript library there is still a big question mark about this issue.In the past 2 days i’ve tried to find the best solution for this problem, I’ve surf the net and i’ve found some interesting things. I’ll try to show you the solutions which i think that are best from most of the aspects. The entire tutorial is written in As3.

Using the browser’s back button with Flash.

I’ve seen many people searching for a so called As3 solution, without javascript. Well, unfortunately , there is no such solution. Imagine the SWF as a guest and the HTML wrapper as a host, you simply can’t let your guest to give commands in your own house right? Of course you are polite and give him everything he needs but if he asks kindly. He could ask kindly via Javascript.

From all the Javascript libraries for Flash (As3), that help the SWF to ask or give kindly data to browsers, i think the best is SWFAddress. The next example shows how to enable the browser’s back button using SWFAddress.

Step 1: Download the latest distribution of SWFObject and SWFAdress. You can also download the FlashIDE example and follow from there the tutorial.

Step 2: In your project folder (which should be empty right now) copy the swfobject.js and swfaddress.js into 2 folders with the same name as the files (swfaddress, swfobject). Next create an index.html that will serve as a wrapper for the swf. Put the next tags into it.

[-]View Code HTML4STRICT
<div id="flashcontent">
            This content here will be replaced by the SWF.</div>
<script src="swfobject/swfobject.js" type="text/javascript"><!--mce:0--></script>
        <script src="swfaddress/swfaddress.js" type="text/javascript"><!--mce:1--></script>
		<script type="text/javascript"><!--mce:2--></script>
 
<!-- Google Analytics Plugin is set to ignore your user role -->

The code simply creates a div with “flashcontent” id and puts in it the backbutton.swf (for better understanding please check the swfobject examples). There are 2 things here that we have to pay attention to. First, the order in which we add the swfobject.js and swfaddress.js, it will always be first the object and second the address, this is very important. Second, we have to put the Javascript after we create the div because the Javascript uses the div and we don’t want it to use a null value. Don’t forget to add the main.css to the index.html by using the “link” tag
Then, add the two AS3 classes from the SWFAddress package(SWFAddress.as and SWFAddressEvent.as) to the root directory of your project.

Step3:Now we have it all set up, the index.html (wrapper), the swfaddress.js, the swfobject.js and the CSS linked to it, and the two SWFAdress class at their place. What we need to do next is to create the SWF, so compile the backbutton.as Actionscript code with Flash.(don’t forget to name the document class “backbutton”).

To understand the code you need a basic knowledge in using Flash Components. If you don’t have it, but you choose to write the code don’t forget that when you create a new component by code (ex: var cd=new ComboBox) you need to add the component also in the Library ( Drag and Drop from the Component Panel to Library)

[-]View Code ACTIONSCRIPT
package {
	import flash.display.MovieClip;
	import fl.controls.ComboBox;
	import fl.data.DataProvider;
	import flash.events.Event;
	import fl.controls.TextArea;
	import fl.containers.UILoader;
	import flash.net.URLRequest;
	import SWFAddress;
	import SWFAddressEvent;
 
	public class backbutton extends MovieClip {
		private var dp:DataProvider = new DataProvider();
		private var myCombo = new ComboBox();
		private var mytextArea = new TextArea();
		private var mySWFAddress=SWFAddress;
		private var image=new UILoader();
		private var urlreq=new URLRequest();
 
		public function backbutton() {
 
			dp.addItem( { label:"Spring" , pictureUrl:"images/1.jpg" , shortDes:"We love it!!!"} );
			dp.addItem( { label:"Summer" , pictureUrl:"images/2.jpg" , shortDes:"Lazy days"} );
			dp.addItem( { label:"Winter" , pictureUrl:"images/3.jpg" , shortDes:"Is really cold here in Cluj"} );
 
			myCombo.dataProvider=dp;
			myCombo.x=50;
			myCombo.y=50;
			addChild(myCombo);
			myCombo.addEventListener(Event.CHANGE, onComboBoxChange);
 
			mytextArea.width = 300;
			mytextArea.height = 80;
			mytextArea.x = 200;
			mytextArea.y = 50;
			addChild(mytextArea);
 
			image.x=200;
			image.y=140;
			image.scaleContent=false;
			addChild(image)
 
			mySWFAddress.addEventListener(SWFAddressEvent.CHANGE, onLinkChange);
 
		}
 
		private function onComboBoxChange(e:Event) {
			var newLink = e.target.selectedIndex;
			mySWFAddress.setValue(newLink);
		}
 
		private function onLinkChange(e:SWFAddressEvent) {
			var newLink = mySWFAddress.getValue();
			newLink = newLink.substr(1);
			mytextArea.text = dp.getItemAt(newLink).shortDes;
			urlreq.url=dp.getItemAt(newLink).pictureUrl;
			image.load(urlreq);
			mySWFAddress.setTitle(dp.getItemAt(newLink).label);
			myCombo.selectedIndex = newLink;
		}
	}
}

So this is it, pay attention to the comments in the backbutton.as file to understand how it works. Everything should work just fine. If not, leave a comment, and i will help.
Here is a working example.
Just choose a item in the ComboBox and then hit the browser’s back button

Well I hope you got the idea, in the second part of the tutorial I’ll talk a little about how to implement something like this in a large application (best practices, design patterns and all).