passing parameter with eventlistener - actionscript-3

I have the following functions:
private function createContent(slideData:Object):void
{
transitions = new Transitions();
if (slide){
transitions.applyTransition(slide);
transitions.addEventListener(Transitions.TRANSITION_COMPLETE, completeHandler);
}
slide = new Slide(slideData);
addChild(slide);
transitions.applyTransition(slide);
}
private function completeHandler(e:Event):void{
removeChild(slide);
}
I dispatch an event in the first function and when it comes to the completehandler i would like to delete the slide from the first function but it isnt recognized. How can i pass the slide with the eventlistener so i can remove it in the completeHandler?(i have several instances from slide so i have to pass it through to have the right instance).
Anyone who can help me?

Here are a couple of ways to pass the slide to the event listener.
1/ As a property of the event
//Assuming that:
// 1/ you create a custom Event class that takes two parameters
// type: String
// slide:Slide
// 2/ that you have assigned the slide object to a variable in the
// applyTransition method , which you can then assign to the event
transitions.dispatchEvent( new TransitionEvent(
Transitions.TRANSITION_COMPLETE , slide ) );
2/ As a property of the dispatcher
//Assuming that:
// you assign the slide object to a variable in the
// applyTransition method
private function completeHandler(e:Event):void{
var target:Transitions = event.currentTarget as Transitions;
removeChild(target.slide);
}

You can use the name property of the slide if you wish.
(Though you have not described how & where slide is actually declared - sprite, mc, etc)
Using name property :
Set slide as slide.name = "instanceName" (In your first function)
Get slide as getChildByName("instanceName") (In your second function)
Alternatively you can also:
Set the slide as class member,
accessible by all the function of
the class.
Add reference of every slide to
an array available as class
member to all its functions.

If the variable is not dynamic, you could probably use an anonymous function to pass the variable.
transitions.addEventListener(Transitions.TRANSITION_COMPLETE, function (evt:Event) {
completeHandler(evt, variable1, variable2);
});
function completeHandler(evt, catch1, catch2) {
//do stuff
}

Related

nested function cant find itself in Typescript

I have the following code:
//Main Entry Point.
start() {
this.init();
this.gameLoop();
}
//Init, runs only once.
init() {
let initalEntity1: Entity = new Entity(10, 10, Gender.female);
let initalEntity2: Entity = new Entity(60, 60, Gender.male);
console.log("There are " + this.Entities.length + " Items in the entities Array")
this.Entities.push(initalEntity1, initalEntity2);
console.log("There are " + this.Entities.length + " Items in the entities Array")
}
gameLoop() {
console.log("Performing a Game Loop");
requestAnimationFrame(this.gameLoop);
//MAIN LOOP THROUGH ENTITIES
for (let i in this.Entities) {
this.Render.drawEntitysToScreen(this.Entities[i].EntityPosition, this.Entities[i].gender);
}
}
It enters into start() fine, and also performs all of the init() functionality. it them proceeds onto gameloop() which it will run once, however the line requestAnimationFrame(this.gameLoop); which is ment to retrigger the function to be called as a Canvas frame is causing the following error:
TypeError: this is undefined
trying to requestAnimationFrame(gameLoop); but it causes the typescript compiler to get upset...
This is due to how this binding works in javascript. The way by which you are passing this.gameLoop to requestAnimationFrame is essentially passing an unbound gameLoop function, and so when it is called, it has lost reference to its this.
There are a number of possible solutions to this problem:
You can bind this.gameLoop to this inside of the class constructor, like so:
constructor() {
this.gameLoop = this.gameLoop.bind(this);
}
You can bind this.gameLoop to this as part of the gameLoop method definition. Rather than defining gameLoop like
gameLoop() {
If you instead use
gameLoop = () => {
it will be automatically bound to this. This is a property of using the fat arrow for function declarations: it automatically performs binding to the this that exists at the function declaration.
You can change how you pass gameLoop to requestAnimationFrame:
requestAnimationFrame(() => this.gameLoop());
This again takes advantage of the automatic this binding performed by the arrow function, but instead of doing it as part of the class method declaration you can simply do it lazily at the time you need it to be bound.
Note, however, that doing it this way does mean that a new function will be created each time gameLoop is called.
When you call this.gameLoop() within start, the value for this inside gameLoop's body will be the class gameLoop belongs to, because you call gameLoop as a property of this (the class).
When you pass a function reference its value for this might be anything when the function is called from somewhere else.
Solution 1 | Using Function.prototype.bind
bind the value for this as you give the function to requestAnimationFrame. By doing this you explicitly say:
Let the argument to bind be this inside any call to gameLoop, regardless of how it is called, or where it is called from.
requestAnimationFrame(this.gameLoop.bind(this));
Note that bind returns you a new function, so the original gameLoop function that is still a property of your class remains unchanged.
Solution 2 | Using an arrow function
Define an arrow function to eventually execute the call to gameLoop instead of requestAnimationFrame. The this value within arrow functions is static, and is inherited from the execution context enclosing the function declaration.
requestAnimationFrame(() => this.gameLoop());

how can i access to child in object in as3

i want to access the child of Object!
for instance:
we a have child(that name is a1) in k1 object.
how can i access it(my means a1 which in the k1)
var k1:keypad=new keypad();
k1.x=7.05;
k1.y=229.20;
add Child(k1);
this.k1.a1.addEventListener(Mouse Event.CLICK,ts);
function ts(event:Mouse Event):void{
trace("OK");
};
thank you.
event has a property target. this one is the child which was clicked.
function ts(event:MouseEvent):void{
trace(event.target);
};
You are doing it wrong. You declare a local variable k1:
var k1:keypad
which is not a member of this object, you cannot access it
this.k1
So your code will probably work this way:
// Bad class name: lowercase.
var k1:keypad = new keypad;
k1.x = 7.05;
k1.y = 229.20;
// This is addChild() method, it is spelled without space.
addChild(k1);
// Then you access k1 just as you did above, without this.
// This will work if you designed your keypad with
// Adobe Flash IDE on default publish settings.
k1.a1.addEventListener(Mouse Event.CLICK, onA1);
// This will work too if a1's instance name is a1:
// k1.getChildByName("a1").addEventListener(Mouse Event.CLICK, onA1);
// Event handler. MouseEvent is a class name,
// it has no space inside.
function onA1(e:MouseEvent):void
{
trace("OK");
}
// Normally you don't need ; after function body.

Removing an EventListener from an object decided via an Array

I am making a simple calculator for an assignment in my IT-Class. It has 3 textboxes where the user can add his numbers, and the boxes start with a "0" inside of them, to show that the user is supposed to write numbers here. What I wanna do, is have this zero go away as the user puts focus on the box.
Since I have 3 boxes, I wanted to make the EventListener call up a function that removes the text and the Eventlistener, instead of writing the same code 3 times.
Using an array containing the different textboxes I managed to call them up, and change the text as I wanted, but the EventListener isn't being removed, so the text the user writes in is being removed when they focus on the textbox again
///////////////////////////////////////////////////////////////////////////////////
//The Array containing all the TextFields
var textFieldArr:Array = new Array(txtNumber1,txtNumber2,txtNumber2)
function onFocus(i:int){
return function (evt:FocusEvent){
textFieldArr[i].text = "";
textFieldArr[i].removeEventListener(FocusEvent.FOCUS_IN, onFocus(i))
}
}
//Calls up the onFocus function and declares variable i
txtNumber1.addEventListener(FocusEvent.FOCUS_IN, onFocus(0));
txtNumber2.addEventListener(FocusEvent.FOCUS_IN, onFocus(1));
txtNumber3.addEventListener(FocusEvent.FOCUS_IN, onFocus(2));
///////////////////////////////////////////////////////////////////////////////
Your event listener isn't being removed, because when you call onFocus(i) within the removeEventListener param, you are being returned a new function, and not the function that was originally being triggered by the event. The other problem with your code is that 'i' does not exist in the listener function you have declared -- you need to use only the properties of evt to figure out which text field to target, and the correct event listener to remove.
The common/correct way to do this is to use a event-accepting function, and listen to each text field with it. You don't even need the array anymore unless you have some other use for it.
function onFocusIn(evt:FocusEvent):void{
trace("onFocusIn("+evt.target+")");
var focusedField:TextField = TextField(evt.target);
if(focusedField){
focusedField.text = "";
focusedField.removeEventListener(FocusEvent.FOCUS_IN, onFocusIn);
}
}
txtNumber1.addEventListener(FocusEvent.FOCUS_IN, onFocusIn);
txtNumber2.addEventListener(FocusEvent.FOCUS_IN, onFocusIn);
txtNumber3.addEventListener(FocusEvent.FOCUS_IN, onFocusIn);
Listener is not removed, because onFocus returns on each invocation new Function instance.
You might try use target property of FocusEvent class:
var textFieldArr:Array = new Array(txtNumber1,txtNumber2,txtNumber2)
function onFocus(evt:FocusEvent){
TextField(evt.target).text = "";
TextField(evt.target).removeEventListener(FocusEvent.FOCUS_IN, onFocus)
}
//Calls up the onFocus function and declares variable i
txtNumber1.addEventListener(FocusEvent.FOCUS_IN, onFocus);
txtNumber2.addEventListener(FocusEvent.FOCUS_IN, onFocus);
txtNumber3.addEventListener(FocusEvent.FOCUS_IN, onFocus);

How to pass parameters to external function through map.event.addListener

I want to add listeners to google map events, but not using anonymous functions but named, external functions as this happens inside a loop, I do not want to define an anonymous function right there, but instead use a named, external function:
Not:
for (...) {
googleMap.event.addListener(instance, eventName, function() {...});
}
But rather sth. like:
doSomething = function(parameter1, parameter2...) {
...
}
for (...) {
googleMap.event.addListener(instance, eventName, params, doSomething);
}
When "instance" is a google map marker, I can add the parameter(s) to the marker using marker.set(paramName, paramValue) and then access the parameters inside the event handler function via this.paramName, but is there any other way to pass values to the event handler function when I don't want to use an anonymous one?
Any advice welcome, Roman.
I had the same problem. Here is a solution. It genuinely avoids the create function in a loop problem, by using the pattern described here
In JavaScript, what are specific reasons why creating functions within a loop can be computationally wasteful?
Which I call the "function factory" pattern.
The other ingredients are that inside the function "this" refers to the object which raised the function (the thing on the map which was clicked, or whatever), and because JavaScript is completely dynamic, you can attach additional properties at will to the thing which was clicked, and query them by calling this.blah inside the function
function doSomethingHandlerFactory(){
var f = function(event){
//do something, for example call a method on a property we attached to the object which raised the event
this.blah.clicked(event);
};
return f;
}
//add a property to the google overlay object (for example a polyline which we've already set up)
thePolyline.blah = ...;
//get a handle for a function, attach the event (in this case to a polyline), and keep
//a reference to the event (in case we want to call removeListener later). The latter
//is optional.
var f = doSomethingHandlerFactory();
var ev = google.maps.event.addListener(thePolyline, 'click', f);
I hope this helps someone out.
How about wrapping your named function in an anonymous function:
google.maps.event.addListener(instance, eventName, function() { doSomething(parameter1, parameter2,...) });

AS3 passing a callback function into a class constructor for use with addEventListener

This has been bugging me for a few days now. I have written a multi-functional messageBox class, and it works pretty well, but there's one thing I'm stuck on. First, though, here's some code:
in the document class I have:
var tMsg:Msg = new Msg("Test Message", "This is a test Message", Msg.INPUT);
tMsg.addEventListener('Answered', qa, false, 0, true);
function qa(e:Event):void{
trace(e.target.label,e.target.result);
tLabel.label = e.target.result;
}
When either the 'cancel' or 'ok' buttons are clicked, the result property is set and the 'Answered' event is dispatched. Since this event listener will always need to be added, I thought it would be better to include it within the class constructor; however, each instance of the Msg class would need its own callback, depending on what the result is being used for. Also, the callback functions should be declared in the document class.
I thought this could be accomplished by simply passing the function to the Msg class constructor, and then use that reference to generate the addEventListener dynamically.
For example:
/// in document class
var tMsg:Msg = new Msg("Test Message", "This is a test Message", Msg.INPUT, qa);
function qa(e:Event):void{
trace(e.target.label,e.target.result);
tLabel.label = e.target.result;
}
/// in Msg class
public function Msg(txt:String='', msg:String='', type:String=ALERT, callback:Object=null) {
_callback = callback;
addEventListener(Event.ADDED, setup, false, 0, true);
}
private function setup(e:Event){
stage.addEventListener('Answered', _callback, false, 0, true);
}
This doesn't work. I don't know if it's because I'm trying to store the callback reference (the event listener should be added to the stage object) or what? The upside to getting this to work would be I wouldn't have to add an event listener each time I create a new message, just pass along the associated function.
Thank you in advance for any help you could provide me.
You should add the event listener to the object that dispatches the event. If that object isn't on the display list or the event doesn't bubble then the stage will not receive the event.