2

I have an array of movie clips that represent buttons the user can click on, and so I need to use addEventListener function so the click can be handled.

I can use a loop and create an addEventListener for each element, I have 26 elements in the array, but I want to try another solution by using only one addEventListener and apply it on the array instead of the elements.

I want to know how to recognize which button was clicked, I mean what's its index in the array.

Thanks.

1
  • It's been a while. Mark an answer as correct if you found a correct answer Commented Jan 10, 2012 at 7:40

6 Answers 6

6

This is probably a good time to learn about event bubbling. You could just add one listener to the common parent of all your buttons

buttonContainer.addEventListener(MouseEvent.CLICK, buttonContainerClickHandler);

Then try and work out what was clicked

private function buttonContainerClickHandler(e:MouseEvent):void 
{
    var targetButton:Sprite = e.target as Sprite;
    //do something with targetButton.
}

To find out what button was clicked, you could use the indexOf method of your array, and pass it the targetButton.

One thing you will have to do is make sure each of your buttons has mouseChildren set to false, or e.target will return the child assets of the buttons.

Sign up to request clarification or add additional context in comments.

1 Comment

+1 - I was in the middle of writing this is exact same suggestion. All the other answers on this page fail to do the one thing asked for: use a SINGLE event listener. Thank you for being a voice of reason!
0

Add it to the movieclip. Adding an event listener to an array doesn't make a whole lot of sense. You are basically saying "Hey array, let me know when something about you changes" and Array isn't a subclass of EventDispatcher so that is a no-go. But in any case you don't want to know about the array, you want to know about the movieclip so the logical thing to do is to make the loop and add it to the movieclip.

Comments

0

You can't assign an event listener to an array.

What I think you're doing is applying a different event listener function to each clip in the array.

For each of the clips you can add the same event listener:

clips[i].addEventListener(MouseEvent.CLICK, handleClick);

and the handleClick function looks something like:

function handleClick(e:MouseEvent):void {
    trace(clips.indexOf(e.target)) // outputs index the movieclip that was clicked on
}

Comments

0

Create a class for your buttons and add the event listener to the class. This way you don't even have to loop through your movie clips as the method will be part of the class

Comments

0

You can't get out of looping directly -- some loop will have to apply somewhere, but you can get out of looping indirectly -- you can let the VM loop for you. You should look at Array.forEach.

A simple application might be:

// assuming myArr is your array.
myArr.forEach( function(item:*, index:int, array:Array):void
{ 
    item.addEventListener( MouseEvent.CLICK, myClickHandler );
} );

To get the item's index, you might make something more complicated:

myArr.forEach( function(item:*, index:int, array:Array):void
{ 
    item.addEventListener( MouseEvent.CLICK, function( event:Event ):void
    {
        trace( "my index is", index );
    } );
} );

I do have to recommend that you simply cache the array someplace accessible to your listener function and then use Array.indexOf along with event.currentTarget, but if you don't find that acceptable, you can use forEach this way:

myArr.forEach( function(item:*, index:int, array:Array):void
{ 
    item.addEventListener( MouseEvent.CLICK, function( event:Event ):void
    {
        trace( "my index is", array.indexOf( item ) );
    } );
} );

Depending on how often you call those methods, it might not be faster to simply us this:

// probably not best to have this public
protected var myArr:Array = [/* whatever goes in here */]

public function register():void
{
    myArr.forEach( addHandler );
}

protected function addHandler( item:IEventListener, index:int, arr:Array ):void
{
    item.addEventListener( MouseEvent.CLICK, myClickHandler );
}

protected function myClickHandler( event:MouseEvent ):void
{
    trace( event.currentTarget, "is at", myArr.indexOf( event.currentTarget ) );
}

But, I can't be sure without knowing more about your particular use case.

Comments

0

You could create your own custom vector class for IEventDispatcher objects that has a custom method that adds an event listener to all its elements. The best way to do this is to create a proxy class that acts as a wrapper for a Vector.<IEventDispatcher> object. I've created an example to demonstrate this:

package 
{
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.events.IEventDispatcher;

    public class Main extends Sprite 
    {
        private var _eventDispatcherVector:EventDispatcherVector;

        public function Main():void 
        {
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);

        }// end function

        private function init(e:Event = null):void 
        {
            removeEventListener(Event.ADDED_TO_STAGE, init);

            var redCustomButton:CustomButton = new CustomButton("RED", 0xFF0000);
            addChild(redCustomButton);
            var blueCustomButton:CustomButton = new CustomButton("BLUE", 0x00FF00);
            blueCustomButton.x = 100;
            addChild(blueCustomButton);
            var greenCustomButton:CustomButton = new CustomButton("GREEN", 0x0000FF);
            greenCustomButton.x = 200;
            addChild(greenCustomButton);

            _eventDispatcherVector = new EventDispatcherVector(Vector.<IEventDispatcher>([redCustomButton, 
                                                                                          blueCustomButton, 
                                                                                          greenCustomButton]));

            _eventDispatcherVector.addEventListener(MouseEvent.CLICK, onCustomButtonClick);

        }// end function

        private function onCustomButtonClick(e:Event):void
        {
            var customButton:CustomButton = e.target as CustomButton;

            trace("You clicked: " + customButton.name + "\n" +
                  "Its index is: " + _eventDispatcherVector.indexOf(customButton));

        }// end function

    }// end class

}// end package

import flash.utils.Proxy;
import flash.utils.flash_proxy;
import flash.events.IEventDispatcher;

use namespace flash_proxy;

dynamic internal class EventDispatcherVector extends Proxy
{
    private var _eventDispatcherVector:Vector.<IEventDispatcher>;

    public function EventDispatcherVector(eventDispatcherVector:Vector.<IEventDispatcher>)
    {
        _eventDispatcherVector = eventDispatcherVector;

    }// end function

    override flash_proxy function getProperty(name:*):* 
    {
        return _eventDispatcherVector[name];
    }

    override flash_proxy function setProperty(name:*, value:*):void 
    {
        _eventDispatcherVector[name] = value;

    }// end function

    public function indexOf(searchElement:*, fromIndex:*= 0):int
    {
        return _eventDispatcherVector.indexOf(searchElement, fromIndex);

    }// end function

    public function addEventListener(type:String,
                                     listener:Function,
                                     useCapture:Boolean = false,
                                     priority:int = 0, 
                                     useWeakReference:Boolean = false):void 
    {
        for each(var eventDispatcher:IEventDispatcher in _eventDispatcherVector)
        {
            eventDispatcher.addEventListener(type, listener, useCapture, priority, useWeakReference);

        }// end for each

    }// end function

}// end class

import flash.display.Sprite;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;

internal class CustomButton extends Sprite
{
    public function CustomButton(name:String, color:uint)
    {
        graphics.beginFill(color);
        graphics.drawRect(0, 0, 100, 100);
        graphics.endFill();

        var textField:TextField = new TextField();
        textField.autoSize = TextFieldAutoSize.LEFT;
        textField.text = name;
        textField.mouseEnabled = false; 
        textField.x = (100 / 2) - (textField.width / 2);
        textField.y = (100 / 2) - (textField.height / 2);
        addChild(textField);

        this.name = name;

    }// end function

}// end class

The output from clicking on the CustomButton objects is the following:

You clicked: RED
Its index is: 0
You clicked: BLUE
Its index is: 1
You clicked: GREEN
Its index is: 2

You can check out Stigglers answer for the question Actionscript 3.0 Best Option for Subclassing Vector Class (Flash Player 10) for more detail.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.