Archive of June 2009

June 17, 09

Dried eye syndrome

Few days ago I saw this eye blinking detector written in JavaScript using HTML5 and canvas (Firefox 3.5 needed) and I set myself a challenge of writing similar one in AS3 from scratch during my lunch break today.

Actually, it turned out to be much simpler than I had initially thought!

Click image to activate, hold your head still and blink your eyes. Hit space to toggle motion areas visibility.

In case it's not working, move your head closer/further away from the camera.

The SWF has 2.5 kilobytes, no heavy calculations are needed to detect eyes blinking. Here's how it works:

  1. Detect all motion areas (hit space to see them)
  2. Apply blur filter to get rid of the noise
  3. Apply threshold to get 1 bit image
  4. Use blob detection algorithm to find blobs
  5. Reject all blobs that are either too big or too small
  6. Draw bounding boxes around blobs that meet the size criteria

Currently, the code is a mess (or I would rather call it experimental state) so no source codes yet.

But I am planning to improve this a lot, i.e. make it possible to track the head movement and position and maybe even eyes. There is also an AIR app stopping your eyes drying coming out soon, meanwhile make sure you'll read a few tips on that very subject.

10:15 PM | | 2 Comments | Tags: , , ,
June 12, 09

The end of anonymous clicks (but don't be afraid)

Recently Google has enabled events tracking for all Analytics accounts – that opens a whole new world for the click hunters – just imagine how useful it might be for usability testing – you can find out if anyone is actually interacting with the new interface that took you 3 weeks to develop.
The official Google Analytics for Flash guide covers pretty much everything what you need to know to set it up for your SWFs and it's all easy peasy when you've got ga.js handy on your HTML page.

But what if you want to give your SWF away (by providing the embed code that links to your SWF) and still be able to track the referrer? You don't know who will be embedding your SWF thus you can't tell if the ga.js will be available.

Fortunately Google covers that matter as well – all you need to do is to import the whole AnalyticsTracker class (which is 100% compatible with the latest ga.js tracking code – at least that's what Google says) available at http://code.google.com/p/gaforflash, set the MODE to AS3 and stop worrying about any Analytics specific Javascript on the HTML page.

All pretty. The only thing is that there's no (direct) way of getting the referrer URL of the SWF that generated the event into your stats, so you won't know who had embedded your file. You could check loaderInfo.url but this will ONLY return the SWF's host location aka your site address and that's no use.

How to get the URL of a page that embeds my SWF then?
There's a simple trick – the page URL is stored in window.location.href and you can use ExternalInterface to get that out. It's actually pretty easy.

Let's go with the example code:

import com.google.analytics.AnalyticsTracker;
import com.google.analytics.GATracker;

const TRACKING_CODE:String = "UA-XXXXXXX-X";
const MODE:String = "AS3";
const DEBUG:Boolean = false;

var GAtracker:AnalyticsTracker;
var referrer:String;

GAtracker = new GATracker(this, TRACKING_CODE, MODE, DEBUG);

if (ExternalInterface.available)
{
    try
    {
        referrer = ExternalInterface.call("window.location.href.toString");
        if (referrer && referrer.indexOf("file:/") != -1) referrer = "localhost";
        if (!referrer) referrer = "unknown";    
    }
    catch (error:SecurityError)
    {
        trace("A SecurityError occurred: " + error.message);
    }
    catch (error:Error)
    {
        trace("An Error occurred: " + error.message);
    }

} else {
    trace("External interface is not available.");
}

As we don't use any Javascript we have to set the tracking code in AS3 along with the MODE set as AS3. Also, there's built-in debugger in the GATracker library which might be actually pretty handy.

Castles in the sand... box
Then we'll try to get the referrer URL – it's important to set <param name="allowscriptaccess" value="always" /> on the <object> tag, and the attribute for the <embed> tag allowscriptaccess="always" in your embed code to allow ExternalInterface access Javascript, otherwise Flash Player will spit out this SecurityError: A SecurityError occurred: Error #2060: Security sandbox violation: ExternalInterface caller [your SWF's host address] cannot access [the URL of the site where your SWF is embedded on].
We can catch it (which we do) but ain't get no URL then.

Got ya, how do I get to track events?
Easy tiger! For example, if you want to track the event of user pressing the video play button to start playback, just fire up this line:

GAtracker.trackEvent("Video", "Play: " + referrer, fileURL);

Where fileURL is the video file URL.

And finally...
Make sure you deploy your SWF on the live site, nothing gets tracked when the SWF is tested in Flash IDE or the local file system as Google explains:

Currently, Flash tracking is available for any Flash content embedded in a web page. Tracking of data sent from Adobe Air, Shockwave, or via the Flash IDE (e.g. using Test Movie) is not supported at this time.

Oh, well.

Any example/demo?
Sure, try to embed the code below on your blog (i.e. as a private post) to see how it works.

<object width="400" height="300" type="application/x-shockwave-flash">
    <param name="movie" value="http://play.blog2t.net/files/event-tracking/tracker.swf" />
    <param name="allowscriptaccess" value="always" />
    <embed
        type="application/x-shockwave-flash"
        width="400" height="300"
        allowscriptaccess="always"
        src="http://play.blog2t.net/files/event-tracking/tracker.swf"
    />
</object>
06:27 PM | | 1 Comment | Tags: , , ,
June 05, 09

Using SWFAddress exclusively with jQuery

I've just spent an hour today trying to work out why SWFAddress was not picking up any events from the browser (i.e. back button click).

It turned out that by default it [SWFAddress] relies on SWFObject, UFO or AC_FL_RunContent but it's not supporting jQuery, which I was using to embed my SWF (precisely with jQuery Flash plugin).

I posted a comment on Asual's blog and I got a quick answer by Rostislav:

@Og2t
You just need to use SWFAddress.addId(flashObjectId) in order to use the library with any Flash embedding script.

Thanks a million! Again and over again, RTFM! SWFAddress is awesome, I am just a moron [*sighs].

Make sure you read this great article on how to use SWFAddress by Greg MacWilliam aka bigmac.

12:30 AM | | 2 Comments | Tags: , , ,
June 04, 09

Useful OS X terminal shortcuts

Create a file named .inputrc in your home directory and paste the following code:

# this makes the "delete" key work rather than 
# just entering a ~
"\e[3~": delete-char

# these allow you to use ctrl+left/right arrow keys
# to jump the cursor over words
"\e[5C": forward-word
"\e[5D": backward-word

# these allow you to start typing a command and 
# use the up/down arrow to auto complete from 
# commands in your history
"\e[B": history-search-forward
"\e[A": history-search-backward

# this lets you hit tab to auto-complete a file or
# directory name ignoring case
set completion-ignore-case On

# Two escapes clear command line
"\e\e": "\C-a\C-k"

It will add a few useful keyboard commands.

01:20 PM | | 1 Comment | Tags: ,
June 03, 09

Assassinating jumpy htmlText hyperlinks

UPDATE: Read this great tutorial on styling the HTML text field

I read quite recently that people are still swearing Flash jumpy hyperlinks in htmlText with Anti-aliased for readability option turned on. What are they talking about? – here's the example.

Roll over and out the links in the left column and carefully observe what happens to the text. Pretty bad stuff.

Fortunately, there is a perfect workaround discovered by Jonnie Hallman aka Destroy Today, but not everybody knows about it yet. So, (to save the world), I wrote a simple TextField wrapper class that automatically deals with the issue, additionally it also fixes another annoying bug – selectable code>TextField scrolls one line on text select – when you click and drag down the mouse while selecting the text, the content scrolls vertically! (and it shouldn't as the text height is the same as the box height, so there's nothing to scroll)

The fixed TextField is presented in the right column – again, try rollover the links.

How does the fix work then?
Basically, after setting the htmlText property, store the height of the TextField, then set autoSize to NONE. That will lock it, so no no more jumping is happening. It is all done at one go by overriding htmlText setter method.

override public function set htmlText(value:String):void
{
    autoSize = TextFieldAutoSize.LEFT;
    super.htmlText = value;
    recordedHeight = height;
    autoSize = TextFieldAutoSize.NONE;
    // adding extra height will prevent "vertical scroll on text select" bug
    // the extra height value should be just bigger than the default leading
    height = recordedHeight + getTextFormat().leading + 1;
}

Additionally, we're adding few pixels extra the TextField default leading value plus 1 to the height there (discovered by Luke Sturgeon), it will prevent "vertical scroll on text select" bug described above.

How should I apply this fix to my broken TextField?
By creating a FixedTextField instance instead, exactly the same way as you would instantiate an ordinary TextField:

var textTF:FixedTextField = new FixedTextField();

Alternatively, you could clone an existing TextField by referencing to it:

var textFieldFixed:FixedTextField = new FixedTextField(someOtherTextFieldToClonePropertiesFrom);

In fact, you can even attach the TextField stored in the Flash IDE library (obviously wrapped up in a MovieClip symbol) – I wrote a separate blog post on that matter.

Download zipped demo including the FixedTextField class.

01:30 PM | | 22 Comments | Tags: , , , , ,
Next → Page 1 of 2