Archive for the “flash” Category


I noticed recently that my Flex application SWF was loading twice. I would see the main Flex SWF file load at full size (~500kb), and then I would see it requested a second time, at a significantly lower file size: 64kb. It appears that this second load is the Flex framework loading in your styles that were compiled into the app. If you check the “Compile CSS to SWF” option in Flex Builder, this probably won’t happen in your app.

With that said, there doesn’t appear to be a major downside to this, other than that you might see an additional HTTP request for your SWF.

Comments and additional research are always welcome!

Comments No Comments »

E4X is a tidy little querying language. Of all the new features in AS3, this one is probably the best.

Most people use E4X for retrieving data straight up, which is good if you have your server-side code doing the filter crunching, but if you’re going for chunky data calls, it’s nice to be able to filter on the client-side too. Thankfully, E4X gives us plenty of capability for filtering.

Let’s start by laying out our common data set. I’m using an XML file with automotive data consisting of Makes->Make->Models->Model. You can see the XML file here: AutomotiveData.xml

In my code, I’ve set a variable called xmlData to the value of the data in AutomotiveData.xml. xmlData corresponds to the root node (Makes) in the data.

Basic E4X filters:

Let’s retrieve the list of Honda models:

trace(xmlData.Make.(@name == “Honda”).Models.toXMLString());

“name” is the attribute of the Make node that we’re working with, so you target attributes with the @ symbol in front. Everything inside of the parentheses is interpreted as normal ActionScript, so you can run pretty much any code that you want to inside there, even if it doesn’t make sense. Just remember, in order to actually filter data, you need to run a function that evaluates to a Boolean: true or false.

Multiple E4X filters:

Let’s get all Makes that have models that cost less than $30,000 and have at least 8 models (this will return Honda and Toyota).

trace(xmlData.Make.(@minMSRP < 30000 && @modelCount >= 8).Models.toXMLString());

Now, you’ll notice that I have an attribute called @modelCount that contains a sum of the model count for that Make. If you don’t have that attribute, you could also count quite easily:

trace(xmlData.Make.(@minMSRP < 30000 && Models.Model.length() >= 8).Models.toXMLString());

E4X recognizes Models as the currently scoped Models node, since we’ve already descended to xmlData.Make. It would not work to say xmlData.(Models.Model.length() >= 8) because the scope of “xmlData.” only gets you to Make, not Models.

In the above example, notice that I ran a function, .length() on the XML, and that I in fact ran E4X inside of E4X. You can nest E4X pretty much as far as you would ever need without hitting any limits. If you do hit limts, you should restructure your XML or consider using a filtering function, which I will talk about later.

Nested E4X and Local Variables

Let’s say we want to find all Makes that have a Model that starts with the letter “R”:

var strModelFirstCharacter:String = “R”;
trace(xmlData.Make.(Models.Model.(@name.toString().indexOf(strModelFirstCharacter) == 0).length() > 0).@name.toXMLString());

Notice that we’re running a nested query so that we can keep the Make scope and get the Make.@name attribute. Also, we’ve passed in a variable this time so that we can modify this E4X to run off of any character or phrase.

If a user was selecting the filters, you could also have them pass in a value, like so:

var strAttribute:String = “mpgCity”; //mpgHighway
var intMinValue:uint = 22;
trace(xmlData.Make.Models.Model.(attribute(strAttribute) > intMinValue).@name.toXMLString());

E4X Filter Functions

Something that just using variables above leaves out is the ability to change the greater than operator without a bunch of messy inline code. However, since we can do basically anything inside of the parentheses, you can create a function to handle variance:

function GenericFilter(data:XML, attributeName:String, value:Object, comparison:String = "equal"):Boolean {
    switch(comparison) {
        case "<":
        case "less":
            return data.attribute(attributeName) < value;
        case ">":
        case "greater":
            return data.attribute(attributeName) > value;
        case "=":
        case "equal":
            return data.attribute(attributeName) == value;
    }
    return false;
}

Then, your E4X can be structured as such:

var strAttribute:String = “seating”;
var intValue:Object = 8;
var comparisonType:String = “=”;
trace(xmlData.Make.Models.Model.(GenericFilter(valueOf(), strAttribute, intValue, comparisonType)).@name.toXMLString());

Notice the valueOf() function; this is passing Model nodes into the GenericFilter, which is why that function accepts an XML node as the data parameter. The comparisonType is simply a string that you can pass in. I’m using a switch because I don’t think there’s a way to pass an actual equality or greater than operator as a parameter in ActionScript. You could of course extend GenericFilter() to accept greater than or equal, or do fuzzy logic, whatever you want to do is acceptable.

These E4X filter functions are pretty much the most powerful thing in E4X; you can run anything that you could possibly want to.

More to come…

I’ll update this article with more information as requests come in or I try new things. Keep in mind that E4X attribute filters don’t work in switch statements.

Comments 2 Comments »

Download the Date Utility referenced in this article: DateUtility.as

Despite what you’ve heard, it’s actually really easy to get a Date() with AS3. You just have to know how the right things to say so that you can smooth-talk her a little bit.

Let’s get started:

Get the current date & time:

var dtCurrent:Date = new Date();

This will give you the current date and time, according to the computer that Flash Player is running on. It will use the computer’s timezone and DST settings.

Create an arbitrary date & time:

var dtWhenever:Date = new Date(2008, 4, 7, 16, 5, 30, 250);
This gives you  May 7th, 2008, at 4:05:30.250pm. Take special care to notice that month (4) is zero-based, meaning that January is 0, and December is 11. Hour, the 4th parameter, starts with 0 as midnight, and ends with 23 as 11pm. The constructor is in the format new Date(year, month, day, hours, minutes, seconds, milliseconds).

Adding to and Subtracting from a date:

Fortunately, AS3 makes this very easy. Say that you want to add 4 days to a date. All you have to do is say:
dtMyDate.date += 4;

Remember, .date is the property that you and I think of as the day of the month. So, you’re probably starting to think of some edge cases, such as “what if it’s the last day of the month?”. The great news is that AS3 will automatically bump the month up as well, rather than having September 34th or something silly.

This works with any of the properties of a Date as well. For example:
dtMyDate.fullYear += 1;
or
dtMyDate.minutes += 300

Subtraction works the exact same way, except you of course would say
dtMyDate.minutes -= 300;

Number of days in a month:

AS3 doesn’t easily give you the number of days in a month, such as “April has 30 days”. However, we can use the subtracting technique from above and set a day of the month of “0″, which is the same as the last day in the previous month. So, if you wanted to get the number of days in March, you could say new Date(new Date().year, 2 + 1, 0).date;

This fills in the current year, then a month of 2 (March) + 1 (April), and then sets the day of the month to 0. In the DateUtility class, you can say DateUtility.GetDaysInMonth(monthIndex);. Remember, AS3 uses a zero-based index for months, so January is 0, December is 11; the GetDaysInMonth() function follows that standard.

Difference in days between two dates:

If you would like to find the difference between two dates, you can simply find the number of milliseconds between them with the .time parameter, and then divide that by 86400000, the number of milliseconds in one day.

var dtDate1:Date = new Date(2008, 4, 1); //May 1st, 2008
var dtDate2:Date = new Date(2008, 6, 20); //July 20th, 2008
var difference:uint = Math.floor(Math.abs((dtDate2.time - dtDate1.time) / 86400000));

We use Math.floor so that we don’t get a partial date, such as 20.2 days. Math.abs is so that you’re actually finding the difference between the days. You can of course remove that if you need to know which date is greater than the other.

Switching to a different timezone:

First of all, you need to get back to UTC, which is easy with the Date.getTimezoneOffset() function.

var dtNow:Date = new Date();
dtNow.minutes += dtNow.getTimezoneOffset();

At this point, you have UTC time, and it’ll be easy to convert to a different timezone. Let’s say we have

var timezone:Number = -7; //Mountain time

To convert, this simple math will work:
dtNow.minutes -= (convertToTimezone * 60);

However, you’re quickly going to run into Daylight Savings Time. A silly little way I get around it is with creating an arbitrary date in January and seeing if it has a timezone offset that’s greater than the date I’m working with, like so:

var blnIsDST:Boolean = (dtNow.getTimezoneOffset() < new Date(2000, 0, 1).getTimezoneOffset());

Then, to convert, you can say:
dtNow.minutes += blnIsDST ? 60 : 0;

If you would prefer, I’ve wrapped up all of the timezone switch functionality in my DateUtility.as that you can download. Download DateUtility.as »

Date Formatting

If you want a formatted date that’s more robust than dtNow.toString(), then you can use the DateFormatter class found in mx.formatters.DateFormatter.

var df:DateFormatter = new DateFormatter();
df.formatString = "EEEE, MMMM DD, YYYY @ L:NNA";
trace(df.format(new Date()));

This should print out something like “Tuesday, September 09, 2008 @ 1:41am”. You can see the full docs on the formatString parameter on the Adobe LiveDocs page.

Date()-ing Tips and Gotchas

Remember that the hours, month, and day properties are zero-based. Hour 0 is midnight, month 2 is March, and day 6 is Saturday.

Date.time is the number of milliseconds since midnight, 1/1/1970 UTC, also known as the Epoch: an arbitrary point in time used to store the value of a date. I like to use Date.time to do a quick compare to see if one Date is greater than another, as in the date difference example above.

Also, Date.date is the day of the month, while Date.day is the day of the week.

Please let me know if there’s something I’ve forgotten that you’re interested in.

Download DateUtility.as »

Comments 8 Comments »

By default, browsers with a built-in popup blocker will usually block Flash navigateToURL requests that open in a “_blank” window. For example: navigateToURL(”http://www.google.com”, “_blank”); will generally get blocked. Even if you have a mouse click event to send off the navigateToURL call, it will be blocked.

The good news is that you can get around this behaviour by calling out to JavaScript to handle the request for you. Go ahead and download URLNavigator.as and save it as ~/com/zorked/URLNavigator.as, where ~ is the folder that your FLA or Flex project resides within. In your ActionScript code, import com.zorked.URLNavigator, then call out to method with URLNavigator.ChangePage(”http://www.example.com”, “_blank”); in the mouse event that you’re capturing.

Now, I’ve tested this with a variety of systems, and it works on a lot of them but it’s not foolproof. So far, it works in IE 6, 7, & 8 (beta), Firefox 2 & 3, Opera 9.x, Safari 3, and runs on XP, Vista, and OSX. It may work on additional systems, but my testing is limited. You may also have problems if you embed your SWF in a strange way. It seems to work with most JavaScript embed libraries, but different parameters on the <object> and <embed> could conceivably cause problems.

However, the caveat is this: you CANNOT call this code except within a click mouse event that you’re listening for. Popup blockers will rightfully block an automatic popup, and there is no way around it. If you ask me how to do an auto-popup, I’ll find your house while you’re sleeping; this method is for white-hat developers looking to open a new browser window for good reason.

Additionally, I made an update to the link that was originally saved: Wordpress likes to save files as lowercase names, which Flash had problems with, since the file didn’t match the name of the class. You should be able to download and work with it without having to rename it.

I’m open to suggestions and improvements, and if anyone has access to additional browsers or operating systems that it’s worked for them on, please let me know.

Download: URLNavigator.as

Comments 85 Comments »

Ok, so we all know how much the Flash Player security model blows. So, because we weren’t in enough pain, Adobe is in the process of making the player even more strict (which is good) by giving you even more mundane tasks to complete if you ever want to do something totally crazy and out there like load SWFs from a subdomain.

You’ve probably already dealt with the crossdomain.xml file, but there are a few changes that you can make to it now, specifically to prohibit crossdomain spoofing if you allow file uploads. You can set the crossdomain file in the root of your folder to be the meta-mega-powerful-nothing-else-counts crossdomain file now.

The really great part about all of this is that regardless of how your set your crossdomain files, Flash Player will NEVER let you load a SWF from another domain and operate on it without the Security.allowDomain() set on the loaded SWF. It doesn’t matter if your crossdomain is as loose as a college cheerleader, or if you do the meta-crossdomain file, or set a crossdomain on both the loading and loaded domain. It doesn’t matter. The only way to get around this is to create a proxy SWF on the domain of the loaded site and pass in the URL that’s on the same domain as the proxy that you actually want to load.

More info on the Flash Player 9 Security Updates.

Comments No Comments »