How do I reference the default `this` reference in Actionscript3 from an external package?
My code is an external .as
file. Google provides this code on their demo, which contains the this
keyword:
import com.google.analytics.AnalyticsTracker;
import com.google.analytics.GATracker;
var tracker:AnalyticsTracker = new GATracker( this, "UA-111-222", "AS3", true );
playGame.addEventListener( MouseEvent.CLICK, onButtonClick );
function onButtonClick ( event:Event ):void
{
tracker.trackPageview("/myGame1");
}
This code probably works fine in the default context, but since I am embedding this code in an external .as
file where I define a package, obviously the this
reference differs since the execution context is different.
Currently, this is how I have it:
package {
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.net.URLRequest;
import flash.net.navigateToURL;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;
import flash.external.ExternalInterface;
import com.google.analytics.AnalyticsTracker;
import com.google.analytics.GATracker;
public class DetailView extends MovieClip {
//private var tracker:GATracker;
private var tracker:AnalyticsTracker;
function slugify(text) {
text = text.replace(/[^-a-zA-Z0-9,&\s]+/ig, '');
text = text.replace(/-/gi, "_");
text = text.replace(/\s/gi, "-");
return text.toLowerCase();
}
public static var NEXTOFFER:String = "DETAIL_NEXTOFFER";
public static var TERMS:String = "DETAIL_TERMS";
private var link:String;
private var fbshare:String;
private var twshare:String;
private var offerID:Number;
private var details:Sprite;
private var terms:Sprite;
public function DetailView() {
ExternalInterface.call( "console.log", 'before');
ExternalInterface.call( "console.log", typeof GATracker );
ExternalInterface.call( "console.log", typeof this );
tracker = new GATracker( this, "UA-WATE开发者_如何学PythonVER", "AS3", true );
ExternalInterface.call( "console.log", 'after');
Notice that I have 4 calls to console.log
. The first 3 fire, but after the new GATracker
statement, the 4th does not fire.
I have a feeling that I'm overriding the entire package with the object created from new GATracker
when I should be passing a different context.
I believe the correct context I should pass is whatever this
defaults to when not inside of a package/external file, I assume it references the main stage object.
If my assumption is right, how would I reference the main stage object from inside of the constructor?
If you want to reference the main stage, you need to wait until your object is added to the stage before you can reference it.
It might look something like this:
public function DetailView()
{
addEventListener( Event.ADDED_TO_STAGE, onAddedToStage );
}
protected function onAddedToStage( event:Event ):void
{
tracker = new GATracker( this, "UA-WATEVER", "AS3", true );
removeEventListener( Event.ADDED_TO_STAGE, onAddedToStage );
}
Another approach to this is listening to the ENTER_FRAME event and in the handler checking for a non-null value for the stage, then removing the handler and initializing your vars.
The problem is that your class object is not on the stage when you try to initialize the tracker. Looking at the source for GATracker, the reference to this
that you pass in is used to obtain the swf url from the stage loaderInfo object: Line 218.
This will fail if whatever displayObject you pass in where currently you use this
is not on the stage:
//_display contains a reference to the first property from the constructor
_env.url = _display.stage.loaderInfo.url;
The solutions are either:
- as jeremynealbrown suggests, to add a listener for
ADDED_TO¬STAGE
and only initiate your tracker at that point. - pass a reference into the class of an object that is already on the stage, and use that reference in place of
this
. The scope you pass for that first parameter is irrelevent as long as the object is on the stage.
精彩评论