actionscript

mysterious “Where is the debugger or host application running?” dialogue on non-debug swfs

Monday, September 1st, 2008 | actionscript, bugs | 3 Comments

Remember awhile back when you’d go to a flash site and randomly get accosted by a “Where is the debugger or host application running?” modal prompt? Haven’t seen one in a while have you? Happily these days debug swfs normally don’t pop open this dialogue unless you explicitly right click a debug swf and click on “Debugger” from its context menu. Unfortunely there are still some tricky situations where this prompt will still rear its ugly head.

My Google-foo (or Adobe?) has let me down on getting solid information on this but in my tests it appears this functionality changed with Flash Player Debugger 9,0,115,0 (Yeah, I thought it was earlier too). This is the debugger version that installs with Flex so even tho you may no longer get the prompt its keen to note that any viewer with a <9,0,115,0 Flash 9 debugger (like the 9,0,45,0 debugger that installs with Adobe CS3) will still receive it. In most cases this isn’t anything to worry about though as its second nature to turn off debugging on your production swf. However did you know you have to take into account all embedded and run-time loaded swfs as well?

After receiving reports of said infamous debugger on our production swfs and a lot of time spent investigating with Flash Switcher I found a couple insignificant embedded icon swfs and a few run-time loaded font swfs were the debug swf culprits. Duplicating the issue in the Flash 9.0.45.0 Debugger, what made matters worse is that each debug swf that loaded was getting its own modal popup and, atleast in Mac FF3, each consecutive modal popup was showing up blank but still needed to be clicked or the user was locked out of the site.

After another extensive google search the only thing I could find regarding this child swf debugger policy is a brief mention in Tinc Uro’s Blog regarding Flash Player 9 Update 3 (again Player 9,0,115,0). The one line from his release notes was: “210746 When a release swf loads a debug swf, flash player doesn’t look for the debugger”.  I’m assuming that this was the “fix” as this player version does indeed keep the issue from happening. So to prevent your viewers from ever getting spammed with “Where is the debugger” modal windows, ensure all your swfs (embedded and run-time loaded) are non-debug or force your viewers to update to the most recent flash player if they don’t have atleast 9,0,115,0.

With the proliferation of “dot” releases of the Flash Player its now really important to know which sub version of the player you are targeting. Looking at the Flash Player 9 version penetration rates at KickApps I was surprised to find around 80% of our audience had atleast 115. I’m not sure of the remaining 20% how many are debug players though.

Version        Penetration
9,0,124,0:    ~56%
9,0,115,0:    ~24%
9,0,47,0:     ~10%
9,0,28,0:      ~7%
9,0,45,0:      ~4%

Tags: , ,

handy way of removing event listeners via arguments.callee

Saturday, August 9th, 2008 | actionscript | No Comments

Theo’s entry reminded me how useful this can be especially when using an anonymous function as a one time callback. Try it out:

stage.addEventListener(MouseEvent.MOUSE_DOWN, function(event:Event):void { event.currentTarget.removeEventListener(event.type, arguments.callee); trace(’ran once’); });

Tags:

How to make an efficient image proxy

Thursday, February 21st, 2008 | actionscript, bugs, help | 5 Comments

So the work I’m currently doing is centered around loading data from different domains. I’ve got a proxy setup to get around pesky crossdomain issues but I’ve been trying to make it a bit dynamic for efficiency’s sake. I only want to proxy if I know for sure that the data isn’t coming from our servers or a server with a crossdomain file in place.

Creating a “smart” proxy with the URLLoader for text content is a piece of cake. Simply listen for the SecurityErrorEvent then run the url through the proxy. Beautifully simple.

For the Loader class its a different story. The Loader class’s contentLoaderInfo doesn’t have a security error event, just an ioError event. Your supposed to use the childAllowsParent property of the contentLoaderInfo to figure out whether you have bitmapData level access. The only problem is you can’t access that property until the Event.COMPLETE event is dispatched despite the livedocs LoaderContext page stating this property is available on ProgressEvent.PROGRESS which will throw a Error #2099: The loading object is not sufficiently loaded to provide this information. at flash.display::LoaderInfo/get childAllowsParent()

I can finagle with the LoaderContext and try/catches all I want but there doesn’t seam to be a creative solution to this problem. The result: I have to load every image that doesn’t have a policy file TWICE. Once to check childAllowsParent, the next to proxy the image. This doesn’t make any sense considering on the same livedocs LoaderContext page it states:

When you call the Loader.load() method with LoaderContext.checkPolicyFile set to true, Flash Player does not begin downloading the specified object in URLRequest.url until it has either successfully downloaded a relevant cross-domain policy file or discovered that no such policy file exists.

I can see the “Error: Request for resource at http://… by requestor from http://… is denied due to lack of policy file permissions.” errors being outputted to the trace window but I don’t seam to have a way to catch it in code. Is something as significant as this, really a bug? Can anyone give me a hand?

Tags: , ,

Using the “include” directive to update multiple classes

Wednesday, February 6th, 2008 | actionscript, flex | No Comments

I recently subclassed Flex’s Canvas to utilize my own custom scrollbars (what a pain!) and soon found I needed to do the same with the Box container (VBox, HBox). Due to the clean OOP nature of these components my overrides and implementation turned out exactly the same for my CustomScrollBarCanvas and CustomScrollBarBox. After a few refactoring sessions copying and pasting my changes to both subclasses I ended up moving all my code to a separate include file and its worked out beautifully with Flex still checking the code during incremental compile:

public class CustomScrollBarCanvas extends Canvas {
public function CustomScrollBarCanvas(){
super();
}
include “CustomScrollBarImplementation.as”
}

public class CustomScrollBarCanvas extends Box {
public function CustomScrollBarCanvas(){
super();
}
include “CustomScrollBarImplementation.as”
}

The Actionscript “include” directive is useful when you have a variable or several lines of code that are mirrored in several classes and you want to maintain that code in a central file. Flex and other frameworks use it commonly to write out framework version numbers on all their classes explicitly during compile time. Flex also uses it to write out groups of meta style tags by type (TextStyles.as, BorderStyles.as, etc) into the components that use them. Its really quite ingenious for upkeep but really simple to implement. (FYI in AS3 you no longer prepend the include statement with a “#”)

Tags: ,

GoogleReader and some great flash / flex blog entries

Thursday, January 31st, 2008 | actionscript, flex | No Comments

Google Reader has been the perfect resource for me to manage all the blogs (flash and otherwise) that I read everyday. I can categorize my feeds by label, view an aggregated feed of those feeds chronologically, and it even keeps track of new entries. I’ve even found some great new flash blogs via its recommendation system (I’m up to 40 now :O).

A couple entries of interest I’ve read lately and wanted to share:

Eric Feminella’s great Quick Tip blog posts:
Using a parameter class instead of an anonymous object to replace unwieldy method parameters
Using fully qualified paths to define custom event constants to avoid conflicts

This one deserves a post of its own when I have some time to really tinker with it but Metal Hurlant who created the AS3 Crypto Library has created an AS3 run-time compiler written in AS3 by porting parts of the Tamarin project’s “esc” compiler. You can create functions and even classes during runtime. Check out the live demo! Its an exciting time to be a flash developer.

Using the class path resolution to your advantage

Sunday, January 13th, 2008 | actionscript, flex | No Comments

Heres a interesting, albeit questionable hack when extending flex classes that cockblock you with a private property or require you to extend several classes when you just want to tweak 1 line of insignificant code in the component.

You can grab the class you want to tweak and copy it to your project folder, mirroring its package with the appropriate folders. When classes get resolved your project folder gets checked before default system paths so your edited version will get compiled in.

I don’t recommend doing this, probably ever, but its been my best friend when I just wanted to tweak that dark 1 pixel line that the Panel component’s title bar receives via TitleBackground without making it a long and convoluted proccess. I don’t know how well this will work with Flex 3’s framework caching but its nice to know this quick and dirty method is there.

Tags: ,

notes from O’reilly’s Essential Actionscript 3.0 (eas3)

Monday, December 24th, 2007 | actionscript | No Comments

I read a lot of programming books and jot down some notes when I find something interesting that I didn’t know or reinforces something I’ve only previously found out through trial and error. Here are some I’d like to share from Colin Moock’s book Essential Actionscript 3.0

Namespaces
Namespaces in flash are the same ones used in xml. Infact, the built in ‘access-control’ modifiers in AS3 like private
and public are namespaces that can also be used with the Namespace class. Using the import directive technically opens the public namespace of the imported package to the current scope and all nested scopes.

The mx_internal namespace used in internal flash and flex framework classes is a custom namespace they’ve defined to share methods and properties between their framework classes, without making those things immediately visible to outside classes. If marked public, code outside the framework could access it, if marked internal it couldn’t be shared across packages. Thus mx_internal.

Other useful tidbits:

  • User defined namespaces can be used as attributes within the top level of a class definition only
  • you can use variable references to a namespace as in: var p:Namespace = mypredefinednamespace;
  • you can refer to a namespaced variable via namespacename::variableormethod: trace(p::variableormethod);
  • you can’t use variable refrences to namespaces in ‘open namespace’ however

Shared Events
An Alternative to allowDomain() = Shared Events
Allows .swf files from different domains to share events without allowing full cross-scripting privileges.
When a swf loads a swf from a different domain, the first can forward its events to the latter by dispatching
its events to the latter’s loaderInfo.sharedEvents object. (ex. loader.contentLoaderInfo.sharedEvents.dispatchEvent(event));

Garbage Collection
Even if an event listener holds the only reference to a clip, the clip won’t be destroyed and the listener will keep listening.
One can’t depend on useWeakReference in events. Though the item will get garbage collected, until it eventually happens, the event will still be dispatched, especially pertinent to something like enterframe events

Events
You can prevent default behavior in many built-in events like TextEvent.Text_INPUT.
By default the text event automatically adds the input to the text. But you could do evt.preventDefault()
and add X’s instead. Check the event’s cancelable property.
Just like built-in events, custom events can define default behavior that can be canceled via preventDefault()
in the event listener check isDefaultPrevented() to see whether an event has had its default behavior prevented
ex.
var toggleEvent:ToggleEvent = newToggleEvent(ToggleEvent.TOGGLE_ATTEMPT, true, true);
dispatchEvent(toggleEvent);
if (!toggleEvent.isDefaultPrevented()){
toggle();
}

Marker Interfaces
An empty interface to “mark” a class as having some feature.
Ex. flash API includes a marker interface IBitmapDrawable, which desginates a class as eligible for drawing into a Bitmap Data object.
The BitmapData class will draw only those classes that implement IBitmapDrawable.

null and undefined
Both null and undefined conceptually represent the absence of data. The null value represents the absence of data for variables, parameters, and return values with a specified type annotation set to anything but Boolean, int, uint, and Number.

undefined represents the absence of data for variables, parameters, and return values without a specified type annotation.
Ex. dynamic variables on a property. Also represents the complete absence of a variable or method on an object whose class is defined as dynamic.

Casting
Difference between casting: AsClass(Class) and (Class as AsClass)
Both make the compiler and runtime see one class as another class (unless casting to primitive wherein it gets converted)
but as returns null in all cases where a cast operation would generate a runtime error.

For legacy reasons, the cast syntax ToClass(Class) cannot be used to case a value to the built-in Date or Array classes. The result of the expression Date(someValue) is identical to new Date().toString() (which returns a string representing the current time). The result of the expression Array(someValue) is identical to new Array(someValue) (which creates a new Array object with someValue as its first element).

Static Methods
though static methods and static variables are not inherited, parent static methods and static variables can be referred to directly without the class name.
Static methods will maintain the scope of the original class they are defined in

Package Level and Global Functions
To create a function that is available throughout a package or an entire program, place a function definition directly within a package body. An ActionScript source file’s name must match the name of its sole externally visible definition even if its a function.

Functions defined at the package-level within the ‘unnamed package’ [package thats generated for all path-less packages] are known as global functions because they can be referenced globally, throughout a program, without the need for the import statement. like trace().

You can also put a access-control modifier less function outside the package, it’ll be accessible to that file only.

Optimization
Code in the class initializer (includes constructor code) runs in interpreted mode, and is not compiled by the JIT compiler. Because JIT-compiled code executes much faster than interpreted code, you should moving processor-intensive code out pf the class initializer when performance is a priority.

Meta

Search