View comments | RSS feed

Delegating events

You can import the Delegate class into your scripts or classes to delegate events to specific scopes and functions (see Delegate class in the Components Language Reference). To import the Delegate class, use the following syntax:

import mx.utils.Delegate;
compInstance.addEventListener("eventName", Delegate.create(scopeObject, function));

The scopeObject parameter specifies the scope in which the specified function parameter is called.

There are two common uses for calling Delegate.create():

Delegating events to functions

Calling Delegate.create() is useful if you have two components that broadcast events of the same name. For example, if you have a check box and a button, you would have to use the switch statement on the information you get from the eventObject.target property in order to determine which component is broadcasting the click event.

To use the following code, place a check box named myCheckBox_chb and a button named myButton_btn on the Stage. Select both instances and press F8 to create a new symbol. Click Advanced if the dialog box is in basic mode, and select Export for ActionScript. Enter Cart in the AS 2.0 Class text box. In the Property inspector, set the instance name for the new symbol to anything you want. The symbol is now associated with the Cart class and an instance of the symbol becomes an instance of this class.

import mx.controls.Button;
import mx.controls.CheckBox;

class Cart {
    var myCheckBox_chb:CheckBox;
    var myButton_btn:Button;

    function onLoad() {
        myCheckBox_chb.addEventListener("click", this);
        myButton_btn.addEventListener("click", this);
    }

    function click(eventObj:Object) {
        switch(eventObj.target) {
            case myButton_btn:
                // sends the broadcaster instance name
                // and the event type to the Output panel
                trace(eventObj.target + ": " + eventObj.type);
                break;
            case myCheckBox_chb:
                trace(eventObj.target + ": " + eventObj.type);
                break;
        }
    }
}

The following code is the same class file (Cart.as) modified to use Delegate:

import mx.utils.Delegate;
import mx.controls.Button;
import mx.controls.CheckBox;

class Cart {
    var myCheckBox_chb:CheckBox;
    var myButton_btn:Button;

    function onLoad() {
        myCheckBox_chb.addEventListener("click", Delegate.create(this, chb_onClick));
        myButton_btn.addEventListener("click", Delegate.create(this, btn_onClick));
    }

// two separate functions handle the events

    function chb_onClick(eventObj:Object) {
        // sends the broadcaster instance name
        // and the event type to the Output panel
        trace(eventObj.target + ": " + eventObj.type);
        // sends the absolute path of the symbol
        // that you associated with the Cart class
        // in the FLA file to the Output panel
        trace(this)
    }

    function btn_onClick(eventObj:Object) {
        trace(eventObj.target + ": " + eventObj.type);
    }
}

Delegating the scope of a function

The addEventListener() method requires two parameters: the name of an event and a reference to a listener. The listener can either be an object or a function. If you pass an object, the callback function assigned to the object is invoked in the scope of the object. However, if you pass a function, the function is invoked in the scope of the component instance that calls addEventListener(). (For more information, see About scope in listeners.)

Because the function is invoked in the scope of the broadcaster instance, the keyword this in the body of the function points to the broadcaster instance, not to the class that contains the function. Therefore, you cannot access the properties and methods of the class that contains the function. Use the Delegate class to delegate the scope of a function to the containing class so that you can access the properties and methods of the containing class.

The following example uses the same approach as the previous section (see Delegating events to functions) with a variation of the Cart.as class file:

import mx.controls.Button;
import mx.controls.CheckBox;

class Cart {

    var myCheckBox_chb:CheckBox;
    var myButton_btn:Button;

    // define a variable to access 
    // from the chb_onClick function
    var i:Number = 10

    function onLoad() {
        myCheckBox_chb.addEventListener("click", chb_onClick);
    }

    function chb_onClick(eventObj:Object) {
        // You would expect to be able to access
        // the i variable and output 10.
        // However, this sends undefined 
        // to the Output panel because
        // the function isn't scoped to
        // the Cart instance where i is defined.
        trace(i);
    }
}

To access the properties and methods of the Cart class, call Delegate.create() as the second parameter of addEventListener(), as follows:

import mx.utils.Delegate;
import mx.controls.Button;
import mx.controls.CheckBox;

class Cart {
    var myCheckBox_chb:CheckBox;
    var myButton_btn:Button;
    // define a variable to access 
    // from the chb_onClick function
    var i:Number = 10

    function onLoad() {
        myCheckBox_chb.addEventListener("click", Delegate.create(this, chb_onClick));
    }

    function chb_onClick(eventObj:Object) {
        // Sends 10 to the Output panel 
        // because the function is scoped to
        // the Cart instance
        trace(i);
    }
}

Version 8

Comments


agorman said on Apr 23, 2007 at 3:41 PM :
It is not clear how to remove event listeners that are created using the Delegate.create() method. The following code does not work and results in (essentially) orphaned objects.

note: in the code below, Application is a singelton class that extends mx.screens.Form. So, Application.getInstance() is a static method that returns a refernces to the one and only root form.

// determines whether this responds to mouse events
public function makeActive(active:Boolean):Void {
trace(this._drawingName + " active = " + active);
if (active) {
Application.getInstance().addEventListener("onMouseDown", Delegate.create(this, this.mouseDowm));
Application.getInstance().addEventListener("onMouseMove", Delegate.create(this, this.mouseMove));
Application.getInstance().addEventListener("onMouseUp", Delegate.create(this, this.mouseUp));
} else {
Application.getInstance().removeEventListener("onMouseDown", Delegate.create(this, this.mouseDowm));
Application.getInstance().removeEventListener("onMouseMove", Delegate.create(this, this.mouseMove));
Application.getInstance().removeEventListener("onMouseUp", Delegate.create(this, this.mouseUp));
}
}
No screen name said on May 16, 2007 at 12:04 PM :
Removing listeners created using the Delegate class is discussed at: http://livedocs.adobe.com/flash/8/main/00003431.html

The basic approach is to save the reference returned by the Delegate.create() method. You can use this reference to add and remove listeners. For example...

----
public function makeActive(active:Boolean):Void {
trace(this._drawingName + " active = " + active);
this.isActive = active;
if (active) {
Application.getInstance().addEventListener("onMouseDown", this.mouseDowmDelegate);
Application.getInstance().addEventListener("onMouseMove", this.mouseMoveDelegate);
Application.getInstance().addEventListener("onMouseUp", this.mouseUpDelegate);
} else {
Application.getInstance().removeEventListener("onMouseDown", this.mouseDowmDelegate);
Application.getInstance().removeEventListener("onMouseMove", this.mouseMoveDelegate);
Application.getInstance().removeEventListener("onMouseUp", this.mouseUpDelegate);
}
}
----



Thanks to migas162

 

RSS feed | Send me an e-mail when comments are added to this page | Comment Report

Current page: http://livedocs.adobe.com/flash/8/main/00002988.html