eventListner parameters and functions

nth1971
nth1971 used Ask the Experts™
on
Hi can anyone advise why my parameters are not being passed into the function

hoverGrow.addEventListener(MouseEvent.MOUSE_UP, DeltaShareExp(315000, 350));
hoverGrow1.addEventListener(MouseEvent.MOUSE_UP, DeltaShareExp(280000, 350));
hoverGrow2.addEventListener(MouseEvent.MOUSE_UP, DeltaShareExp(315000, 1150));
hoverGrow3.addEventListener(MouseEvent.MOUSE_UP, DeltaShareExp(200000, 1150));
hoverGrow4.addEventListener(MouseEvent.MOUSE_UP, DeltaShareExp(315000, 28000));
hoverGrow5.addEventListener(MouseEvent.MOUSE_UP, DeltaShareExp(595000, 28000));





function DeltaShareExp(event:Event, startingNumber:Number, endingNumber:Number):void
{
	var i:uint = 1;
	var myTimer:Timer = new Timer(10,100);
	myTimer.addEventListener(TimerEvent.TIMER, function(event:TimerEvent):void 
	 {
		 
	  var xNum:Number = startingNumber - i++ * endingNumber
	    myText.text = String(xNum); 
	  
	});
	myTimer.start();
}

Open in new window

Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®

Author

Commented:
i've kind of done it but it seems like a lot of code.. is this the best way??

hoverGrow.addEventListener(MouseEvent.MOUSE_UP, function(event:MouseEvent):void{  
						   var startingNumber:Number = 315000;  
						   var endingNumber:Number = 350;  
						   var deltaDrop:Boolean = true;
						   DeltaShareExp(event, startingNumber,endingNumber,deltaDrop);  

 }); 
hoverGrow1.addEventListener(MouseEvent.MOUSE_UP, function(event:MouseEvent):void{  
						   var startingNumber:Number = 280000;  
						   var endingNumber:Number = 350;
						   var deltaDrop:Boolean = false
						   DeltaShareExp(event, startingNumber,endingNumber, deltaDrop);  

 }); 
hoverGrow2.addEventListener(MouseEvent.MOUSE_UP, function(event:MouseEvent):void{  
						   var startingNumber:Number = 315000;  
						   var endingNumber:Number = 1150; 
						   var deltaDrop:Boolean = true
						   DeltaShareExp(event, startingNumber,endingNumber, deltaDrop);  

 }); 
hoverGrow3.addEventListener(MouseEvent.MOUSE_UP, function(event:MouseEvent):void{  
						   var startingNumber:Number = 200000;  
						   var endingNumber:Number = 1150; 
						   var deltaDrop:Boolean = false
						   DeltaShareExp(event, startingNumber,endingNumber, deltaDrop);  

 }); 
hoverGrow4.addEventListener(MouseEvent.MOUSE_UP, function(event:MouseEvent):void{  
						   var startingNumber:Number = 315000;  
						   var endingNumber:Number = 2800; 
						   var deltaDrop:Boolean = false
						   DeltaShareExp(event, startingNumber,endingNumber, deltaDrop);  

 }); 
hoverGrow5.addEventListener(MouseEvent.MOUSE_UP, function(event:MouseEvent):void{  
						   var startingNumber:Number = 595000;  
						   var endingNumber:Number = 2800;
						   var deltaDrop:Boolean = true
						   DeltaShareExp(event, startingNumber,endingNumber, deltaDrop);  

 }); 





function DeltaShareExp(event:Event, startingNumber:Number, endingNumber:Number, deltaDrop:Boolean):void
{
	var i:uint = 1;
	var myTimer:Timer = new Timer(10,100);
	myTimer.addEventListener(TimerEvent.TIMER, function(event:TimerEvent):void 
	 {
		 
		 if(deltaDrop == true){
	  var xNum:Number = startingNumber - i++ * endingNumber
	  myText.text = String(xNum); 
		 }else{
	  var xNum2:Number = startingNumber + i++ * endingNumber 
	  myText.text = String(xNum2); 
		 }
		   
	});
	myTimer.start();
}

Open in new window

Top Expert 2011
Commented:
Let me give you my usuful function you can create as util in your class

public static function FunctionParaUtil(callBack:Function, ...args:Array):Function{
				var handler:Function;
				handler = function(event:Event):void{
					var func:Function = arguments.callee.prototype.func;
					var args:Array = arguments.callee.prototype.args;
					func.apply(null, [event].concat(args));
				};
				handler.prototype.func = callBack;
				handler.prototype.args = args;
				return handler;
			}

Open in new window


Its very simple to use for example:

hoverGrow.addEventListener(MouseEvent.MOUSE_UP, FunctionParaUtil(DeltaShareExp, 315000, 350));

for DeltaShareExp function will get all your parameters
@dgofman: that's a pretty cool approach. I must say I've never seen anyone encapsulate the arguments in a closure and send that back as the callback argument. Neat.

@nth1971: the reason your approach doesn't work is that addEventListener is expecting a pointer to a function, not the function call itself. When you say addEventListener(EVENT_TYPE, myFunction(a, b)); you're actually EXECUTING myfunction right there at that time, rather than telling AS that you want to execute that function when the event occurs. addEventListener(EVENT_TYPE, myFunction) would be the way you set up your event listener, but of course then it doesn't get the parameters that you'd like to pass.

Now the method @dgofman suggested is right to the point and probably the most direct fix for your solution. However, I would propose that you re-evaluate your solution architecture a little because you really shouldn't have to use this pseudo-delegated closure approach.

One approach you might try is to associate those parameters as properties of the MovieClip or Button that the user is clicking. Since MovieClips are dynamic objects, we can freely associate new properties to store our values. Consider this example:

hoverGrow.deltaShareA = 315000;
hoverGrow.deltaShareB = 350;
hoverGrow1.deltaShareA = 280000;
hoverGrow1.deltaShareB = 350;
etc...

hoverGrow.addEventListener(MouseEvent.MOUSE_UP, handleDeltaShareClick);
...

private function handleDeltaShareClick(event:MouseEvent):void {
  var theHoverGrow:MovieClip = MovieClip(event.target); // which button did we click on?
  var startingNumber:Number = theHoverGrow.deltaShareA;
  var endingNumber:Number = theHoverGrow.deltaShareB;
 // etc...
}

Open in new window


What we've done is we've encoded those properties that you wanted to pass to the event handler, INSIDE the object itself. When the event triggers the handleDeltaShareClick event, we retrieve the object that was clicked from event.target. Then we read back in those stored values and proceed as normal.

Now I think we'll all agree that this is a lot more code than the previous suggestion. I'm not even going to claim it's more "correct" since whatever gets the job done AND is easier to read and understand later is probably the best solution.

You could certainly make the assignment part of my example above a lot more efficient if you parametrized your initialization for all these hoverGrow objects. For example, you could create an initialization object like this:
var hoverGrowInit:Object = {
 hoverGrow: [315000, 350],
 hoverGrow1: [280000, 350].
 etc...
};

// now go through each hoverGrow object and assign the parameters to them!
// set up the event listener while you're at it to really save time
for each (var hoverObject in hoverGrowInit){ 
  var theHoverGrow:MovieClip = getChildByName(String(hoverObject)); 
  theHoverGrow.deltaShareA = hoverGrowInit[hoverObject][0]; // get the first item
  theHoverGrow.deltaShareB = hoverGrowInit[hoverObject][1];

  theHoverGrow.addEventListener(MouseEvent.MOUSE_UP, handleDeltaShareClick);
}

Open in new window


And that sets them all up in one fell swoop. This is even arguably more elegant because that initialization object is pretty easy to read and change if you want to change your numbers. Heck you could even read it in from an external text file or an XML file.

For me, the best solution would be to use Object Oriented principles. This may or may not be what you want to get into though depending on how much of a "coder" you are and what your understanding of OOP is.

What I would do is make each hoverGrow clip an instance of a Base Class that extends MovieClip (or Button or Sprite or whatever your base class is when you created your hoverGrow). Then you could extend this base class for each of your individual HoverGrow objects specifying the specific parameters. Since it would be its own class, you wouldn't need to register these properties against the MovieClip at all. Here's a sample of what I'm talking about:

file: HoverGrowBase.as

package {
  import flash.display.MovieClip;
  import flash.events.MouseEvent;

  public class HoverGrowBase extends MovieClip {
    protected var _deltaShareA:Number;
    protected var _deltaShareB:Number;

    public function HoverGrowBase() {
      // nothing much to do here...   
      addEventListener(MouseEvent.MOUSE_UP, handleMouseUp);
    }

    public function set firstNumber(num:Number):void {
      _deltaShareA = num;
    }

    public function get firstNumber():Number {
      return _deltaShareA;
    }

    public function set secondNumber(num:Number):void {
      _deltaShareB = num;
    }

    public function get secondNumber():Number {
      return _deltaShareB;
    }
    
    protected function handleMouseUp(event:MouseEvent):void {
      // we already have access to firstNumber and secondNumber so go ahead and implement your code here
    }
  }
}

file: HoverGrow1.as

package {
  public class HoverGrow1 extends HoverGrowBase {
    public function HoverGrow1(){
      firstNumber = 315000;
      secondNumber = 350;
    }
  }
}

file - your main file

nothing! Everything is handled through the objects.

Open in new window


Now, in order to make this magic work, you just need to make sure you tell Flash that each of the hoverGrow movieClips you created in your timeline are associated with the correct classes. So look at your library, click Properties for each of your hoverGrow movieclips, and turn on "Export for ActionScript". Then type in 'HoverGrow1' or whatever in the "Class" field. LEAVE THE BASE CLASS as flash.display.MovieClip! I know this sounds confusing, but do NOT instantiate your HoverGrowBase class.

Okay I know this post is a lot to digest. Some of it may not be useful to you now, hopefully most of it will. Between @dgofman's cool hack and my more conservative approaches, hopefully you'll be able to get the code to work the way you feel is best for your project.

Regards,

Tom
DISCLAIMER: you're not meant to copy and pasted my code verbatim as I typed it directly into the EE editor and haven't done any testing. There are certainly typos. Sorry about that.

Author

Commented:
Tom, Interesting particularly the way you have approached it... take a while to absorb this but I get the gyst and I understand what you say in the first comment so thanks that really helps.... and thanks dgofman works perfectly.

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial