I'm using iteration within a class method to attach a series of button instances from the library to mc in my fla. So far so good, but when I try to use Delegate to give them an onRelease handler, it only works on the last button. Here is the rellevent code:
Code:
//CREATE BUTTONS FROM XML
public function attachButtons (buttonLabel:Array, totalButtons:Number, buttons:Number):Void {
//SET ITEM VARS
numVisibleItems = buttons;
numOfItems = totalButtons;
var thisLb:XmlListBox = this;
var i;
//ITTERATE THROUGH ARRAY TO PLACE BUTTONS
for (i = 0; i < numOfItems; i++) {
buttonContainer_mc = listBoxContainer_mc.background_mc.attachMovie ("listBoxButton", "button" + i, listBoxContainer_mc.background_mc.getNextHighestDepth ());
buttonContainer_mc._y = buttonContainer_mc._height * i;
buttonContainer_mc.title_txt.text = [i + 1] + " " + buttonLabel[i];
buttonContainer_mc.onRelease = buttonContainer_mc.onReleaseOutside = Delegate.create(this, setButtons, i);
buttonContainer_mc.thisSelected_mc._alpha = 0;
}
sizeMask ();
}
function setButtons(i:Number):Void {
buttonContainer_mc._alpha = 100;
trace("IDENT"+buttonContainer_mc.thisSelected_mc._alpha);
trace("I IS:"+ i);
//current_track_number = i;
//stopmusic();
//playmusic();
}
Are you trying to add the hyperlink to the listBoxButtons?
The reason it ends up paying attention to the last on(release) is because you essentially reassign the onRelease every single loop, and the last one is what finally takes.
You need to set up the loop to effect each button instead of the main container clip.
Thanks for getting back to me. That all works great apart from getting the setButtons method to fire the bit of code in blue (I've just edited it) as there is no route back to the button and Delegate won't let me send i as a variable (it returns as undefined);
mx.utils.Delegate class does not take into account any passed variables, there is no third argument in the create method of the class and so it will be ignored.
Instead of delegating the scope of the button events to that of the class, you could just pass a reference to the scope of the class object and use that variable to access the class objects methods and properties from the scope of the buttons. That would probably be how most people would handle it.
However, there is a trick you can do so you can write your own version of the Delegate class that will pass any number of arguments which might save you reworking what you already have...
Code:
class lexicon.utils.Delegate extends Object
{
static function create(obj:Object, func:Function):Function
{
var f = function()
{
var target = arguments.callee.target;
var func = arguments.callee.func;
var args = arguments.callee.args;
return func.apply(target, arguments.concat(args));
};
f.target = obj;
f.func = func;
f.args = (arguments.length>2) ? arguments.slice(2) : [];
return f;
}
function Delegate(f:Function)
{
func = f;
}
private var func:Function;
function createDelegate(obj:Object):Function
{
return create(obj, func);
}
}
so you could assign the event functions to this if you wanted...
Code:
lexicon.utils.Delegate.create(this, setButtons, i, buttonContainer_mc);
and access the passed vars in your setButtons function...
www.lexicon-design.co.uk
If we aren't supposed to eat animals, then why are they made of meat?
If Vegetarians like animals so much, why do they eat all their food?
Instead of delegating the scope of the button events to that of the class, you could just pass a reference to the scope of the class object and use that variable to access the class objects methods and properties from the scope of the buttons. That would probably be how most people would handle it.
I totally understand your "trick" solution, but just out of interest, if you have a couple of spare minutes, can you try to explain the quoted chunk to me. I've read it again and again, but it's not going in.
I meant that you could do something like this, where the reference to the class object is passed to the button so that the function in the class object scope can be called from within the button scope.
It's easier to explain in code ...
Code:
class MyMenu extends MovieClip
{
// declare the button specific vars so you don't get compile errors.
var scope:MovieClip, id:Number;
// constructor
function MyMenu()
{
var _mc:MovieClip;
for(var i:Number=0; i<5; i++)
{
// create the clips and assign the mouse event
_mc = createEmptyMovieClip('_btn'+i, i);
_mc.onRelease = buttonRelease;
// vars to be passed as argument to the someClassFunc
_mc.id = i;
// a reference to the class object so that the someClassFunc can be correctly addressed and executed
_mc.scope = this;
// draw and position the buttons
_mc.beginFill(0xFF, 100);
_mc.lineTo(50,0);
_mc.lineTo(50,50);
_mc.lineTo(0,50);
_mc.lineTo(0,0);
_mc.endFill();
_mc._y = i*55;
}
}
// function will run in the class object scope
private function someClassFunc(id:Number, btn:MovieClip):Void
{
trace("Button id: "+id);
trace("Button ref: "+btn);
trace("Scope of this function: "+this);
}
// the onRelease function running in the individual button's scopes
private function buttonRelease(Void):Void
{
this.scope.someClassFunc(this.id, this);
}
}
www.lexicon-design.co.uk
If we aren't supposed to eat animals, then why are they made of meat?
If Vegetarians like animals so much, why do they eat all their food?
you did not pass the container parameter in you Fla when adding the class object.
you also forgot to add the parenthesis in this line...
var imageLoader:MovieClipLoader = new MovieClipLoader();
Lastly because the MovieClipLoader passes a parameter anyway (e.g. the target), the extra parameters you add with the delegate function will be appended.
e.g.
Code:
private function output(answer:Number)
{
trace("ANSWER "+answer +" "+t)
}
will need to become...
Code:
private function output(target:MovieClip, answer:Number)
{
trace("ANSWER "+answer)
}
so it's better not to use this method to assign the same function to a MovieClipLoader and a MovieClip.
www.lexicon-design.co.uk
If we aren't supposed to eat animals, then why are they made of meat?
If Vegetarians like animals so much, why do they eat all their food?