November 2003


When creating a movie clip with an associated AS 2.0 class (using the Linkage dialog for the symbol), any components on that movie clip cannot be accessed in the constructor of the class. References to the component instances will be non-null, but they’ll appear as plain movieclip instances and not have any of the methods or fields from their component classes.

Say for example we have a movie clip symbol which contains a TextInput component with an instance name of passwordInput. We associate an AS 2.0 class called PasswordWindow, which extends MovieClip, with the movie clip’s symbol in the library. If we declare passwordInput as a field in PasswordWindow, in the constructor function passwordInput will be non-null and have a type of “movieclip”. Its regular MovieClip fields and methods will work — passwordInput._x will represent he horizontal position, for example. However, TextInput fields such as passwordInput.text will not work.

The solution is to access the components in the onLoad handler instead of the constructor. Whereas passwordInput.text = “foo” will not work in the constructor, the same code will work in an onLoad function (which overrides the default implementation from the MovieClip superclass). This problem probably has something to do with the order in which elements within the movie clip are initialized with respect to the movie clip’s AS 2.0 code.

In the CellRenderer API, the setValue method takes a parameter called “selected”, which is documented to be a boolean indicating whether the cell being rendered is currently selected. In fact, the selected parameter is a String whose possible values are “normal”, “highlighted”, and “selected”. Thus if you treat the parameter as a boolean you’ll always end up with a value of true.

Unfortunately, the “highlighted” value appears to override the “selected” value, so if a row is selected and the cursor is on top of it, the value of the selected param will be “highlighted” and not “selected”. This can cause problems if you’re trying to make the renderer behave differently based on whether or not the row is in a selected state, since if you use the selected param the row will only appear as selected when the mouse is not hovering over it. This can be worked around by using the expression

var reallySelected:Boolean = selected ne "normal" && listOwner.selectedNode == item;

instead to test whether the node for the current row is in a selected state. I’m not sure why the first term of the expression (the “normal” check) is necessary, but I had to include that in order to avoid false positives — I think it has to do with the details of the order in which the various selected flags get updated by the model and component.

The AS2 analogue of Java’s anonymous inner class construct is common for event handlers and looks like this:

class Bar {
var notifier;
public function foo(Void):Void {
var loadListener = new Object();

loadListener.numLoaded = 0;

loadListener.handleEvent = function(evt) {

if (evt.type == "complete") {

trace("all done");
notifier.notify();    // < -- won't work
}
};
myLoader.addEventListener("progress", loadListener);
}
}

In this case the loadListener is an instance of an anonymous class that is declared and used inside the foo method of another class. Let’s say, however, that we want loadListener’s handleEvent method to have access to notifier, which is a member of the enclosing class. Just referencing notifier or this.notifier within the handleEvent body won’t work, because “this” in that context means the loadListener instance itself. What we need to do is provide an explicit reference to the enclosing class context outside the loadListener declaration:

class Bar {
var notifier;
public function foo(Void):Void {
// here we set up a reference to the enclosing class instance
var thiz = this;
var loadListener = new Object();

loadListener.numLoaded = 0;

loadListener.handleEvent = function(evt) {

if (evt.type == "complete") {

trace("all done");
thiz.notifier.notify();        // < -- this works
}
};
myLoader.addEventListener("progress", loadListener);
}
}

By declaring a local variable “thiz” that contains a reference to “this” at the place it’s declared, that is, the Bar (enclosing class) instance, we’re able to access that enclosing class through thiz in the inner class methods. I chose the name “thiz” because it’s kind of (but not really) similar to the way “clazz” is sometimes used in reflection code in Java.