Changing text with AS3 in a for loop - works for first one, others don't - actionscript-3

I have a movieclip called Tab that has two text-fields: named toptxt and bottomtxt. When I create new instances of Tab in a for loop and change the text, only the first instance's text is changed. The rest is the default text in the movieclip.
Here is the code I am using:
for(var i = 0; i < 5; i++){
var newTab = new Tab();
newTab.toptxt.text = nameArray[i]; //nameArray is fine
trace(newTab.toptxt.text); //returns expected value, textfield isn't
newTab.bottomtxt.text = jobs[i];
bottom.addChild(newTab); //bottom is a class var.
newTab.x = i * (newTab.width + 3);
}
Even if I change nameArray[i] to "Test", only the first one works.
This problem does not occur if I don't do it in for loops, however I'd like to do it in a for loop.
Here is a screenshot of the problem: http://i.imgur.com/hgPZ5.png

Pull your declaration of var newTab = new Tab(); outside of the for loop, so your code looks like this:
var newTab:Tab;
for(var i:int = 0; i < 5; i++){
newTab = new Tab();
newTab.toptxt.text = nameArray[i]; //nameArray is fine
trace(newTab.toptxt.text); //returns expected value, textfield isn't
newTab.bottomtxt.text = jobs[i];
bottom.addChild(newTab); //bottom is a class var.
newTab.x = i * (newTab.width + 3);
}
Actionscript is becoming confused when you create an instance and assign newTab as a pointer to it, instead of creating a pointer or reference initially, and then creating new instances and adding them to your displayList.
Also, trace your output of nameArray[i] and confirm that those values are correct (i.e. trace(nameArray[i]);. It's possible the data isn't set properly earlier in your code.

Related

ActionScript 3 Adding images; different positions

In short, I have clickable objects with varying colours. I want these colours upon being clicked to appear in my placeholders (there will be 6). I currently have managed to code so that upon clicking any colour it is placed in the first placeholder.
In what way am I able to code to recognise that the first placeholder has been filled and that once filled, the second placeholder should become the target?
Preferably until the 6th has been filled and then stopped, so that the user can see all 6.
I am thinking something like a for loop would be fitting, but I am not sure how to go about it.
So far it's looking something like this:
//Placeholder
var placeHolder1:MovieClip = new MovieClip();
placeHolder1.x = 20;
placeHolder1.y = 245;
stage.addChild(placeHolder1);
//Placeholder2 (UNUSED CURRENTLY)
var placeHolder2:MovieClip = new MovieClip();
placeHolder2.x = 60;
placeHolder2.y = 245;
stage.addChild(placeHolder2);
//Click and select colours
var newBlue:cBlue = new cBlue();
numBlue.addEventListener(MouseEvent.CLICK, fBlue)
function fBlue(e:MouseEvent){
placeHolder1.addChild(newBlue);
}
var newRed:cRed = new cRed();
numRed.addEventListener(MouseEvent.CLICK, fRed)
function fRed(e:MouseEvent){
placeHolder1.addChild(newRed);
}
First, you probably want to learn about Arrays (or Vectors). Arrays/Vectors are lists, so you would put all your placeholders into an array:
var placeHolders:Array = [placeHolder1, placeHolder2];
Though, since there is a formula to your place holder creation, you probably would want to do this in a loop to make it DRYer (Don't Repeat Yourself)
This loop would create 10 place holders and add them to the array:
var placeholders:Array = new Array();
for(var i:int=0; i < 10; i++){
var placeHolder = new Sprite(); //if your not using timelines, just use Sprite instead of MovieClip as it's less overhead
placeHolder.x = 20 * (i + 1); //i starts at 0, and goes to 9
placeHolder1.y = 245;
stage.addChild(placeHolder); //add it to the display list
placeholders.push(placeHolder); //add it to the array
}
Now (continuing to be DRY), attached the same event listener to all your color buttons:
numBlue.addEventListener(MouseEvent.CLICK, selectColor);
numRed.addEventListener(MouseEvent.CLICK, selectColor);
In that event handler I've called 'selectColor' (see code comments)
function selectColor(e:Event):void {
//get the first element in the array
var placeHolder:Sprite = placeholders.shift(); //shift removes the first item from the array, and returns it
placeHolder.addChild(e.currentTarget); //e.currentTarget refers to item that you attached the event listener to, in this case either numBlue or numRed
}
So to summarize, this gets the first placeholder in the array, remove that item from the array, then adds color button that was clicked as a child of that placeholder.

Array of stagewebviews

I am in the need of multiple staged WebViews for holding multiple loaded websites at the same time.
I was hoping to manage this by making an array of webviews object, so i could call them later as view[i].
var view:Array=[webview0, webview1, webview2];
for each (var v in view){
var v:StageWebView = new StageWebView();
This gives error: 1086: Syntax error: expecting semicolon before left bracket.
Does someone know how to make an array like that?
You're doing something really weird there in terms of syntax. If you just want an Array of freshly created instances, it goes like that:
// Initialize the array.
var Views:Array = new Array;
// This loop counts 0,1,2.
for (var i:int = 0; i < 3; i++)
{
// Create a new instance.
// Yes, you can omit () with new operator if there are no arguments.
var aView:StageWebView = new StageWebView;
// Assign the new element to your array.
Views[i] = aView;
}
Or, if you need only 3 then you don't need to go algorithmic.
var Views:Array = [new StageWebView, new StageWebView, new StageWebView];
Not on topic but related:
Here is an example of one HTML page hold multiple StageWebViews
https://www.w3schools.com/graphics/tryit.asp?filename=trymap_basic_many

How to push instantiated MC into Array dynamically?

Im really stuck. I have 5 MC´s that are being spliced from one array at a certain time. In that same function I want to push another movieclips into another array. The two arrays holds mc's that represent right or wrong answers. So when one question is being given a correct answer that questions visualisation alters.
This function holds a incrementing variable as I do want the mc's to be pushed by the user and one at the time. The thing is I cant seem to refer them properly.
I´ve tried
pQuestSum = this[pQuest + pQuestNumber];
and
pQuestSum = this[pQuest] + pQuestNumber;
and pretty much everything I´ve imagined would work...but the problem is I havent tried
the right thing.
when I trace pQuestSum (which would be the reference) I get an error saying thats its not a number.
this is one of 5 mc's named from 1-5:
var passedquest1:PassedQuest = new PassedQuest();
this is the vars that i try to to build a reference of
var pQuest = "passedquest";
var pQuestNumber = 1;
var pQuestSum;
var questCorrArray:Array = [];
if(event.target.hitTestObject(questArray[ix])){
removeChild(questArray[ix]);
questArray.splice(ix,1);
pQuestNumber ++;
pQuestSum = this[pQuest] + pQuestNumber;
trace("pQuestSum"); // NaN
questCorrArray.push(pQuestSum);
//trace(questArray.length);
pointsIncreased = false;
questPoints = 0;
}
How do I refer an existing movieclip when the reference consists of both a string and a number? Hope I made myself somewhat clear:)
If you had an instance of an object on your timeline called "passedquest1" (as an example), then you could access it this way:
var myObj = this["passedquest" + 1];
Or,
var pQuest = "passedquest";
var pQuestNumber = 1;
var myObj = this[pQuest+ pQuestNumber.toString()];
When you do this: pQuestSum = this[pQuest] + pQuestNumber;, you are trying add the number to an object (this[pQuest]), unless you have number/int var called "passedquest", this will result in NaN.

as3 dynamic variable within a loop

I need to have the screenPage var accessible for later calls. I am dynamically creating several pages. The issue is when I call screenPage.startDrag(); then it only drags the last page. How can I add a var in the name or make all the screenPages accessible through code?
Here is code in short:
var screenPage:MovieClip;
for(var p = 1; daTotalPages >= p; p++)
{
screenPage = new theFlagScreen();
}
Can I make screenPage a dynamic var and add like a 1 at the end and then a 2 and so forth with the loop?
Why not use an array ?
var pages:Array = new Array;
for(var p = 1; daTotalPages >= p; p++)
{
var screenPage:MovieClip = new theFlagScreen();
pages.push(screenPage)
}
Now you have an array containing all of your instances.
var myPage:MovieClip = pages[5] as MovieClip;
myPage.startDrag();
Also, the code you have above is creating an instance each time through, but since you then go ahead and create a new one each iteration and assign it to the same variable without storing it or adding it to the display list.... once you create a new one, the last one is marked for garbage collection.
The result is only the LAST instance you created still exists as it's the only one that has a variable that references it.
screenPage is a reference to just ONE thing. In your loop you keep overwriting it as you go and so you end up with it pointing to the very last instance of theFlagScreen... all the others are now lost.
You should follow prototypical's advice and store these instances in an array, that way you don't lose them.

Trying to remove all children, receiving error #1009

The idea with my setup is that I have an input text field and three separate buttons on stage. When you type something in the text field and press the input button, the text inside the field is added to an array.
When you press the display button the contents of the array are displayed on screen (each value of the array is displayed underneath the last value).
The final button is supposed to remove all the current values on the array, and clear all displayed values on screen. But I cannot get my code to work as intended, since I receive,
TypeError: Error #1009: Cannot access a property or method of a null object reference.
With this block of code:
import flash.text.TextField;
import flash.events.MouseEvent;
var myArray:Array = new Array ("");
var tf:TF;
btnInput.addEventListener(MouseEvent.CLICK, txtInput);
function txtInput(event:MouseEvent):void
{myArray.push(txtInput.text);}
btnDisplay.addEventListener(MouseEvent.CLICK, txtDisplay);
function txtDisplay(event:MouseEvent):void
{for (var i:int = 0; i < myArray.length; i++)
{var tf:TF = new TF();
tf.txt.text = myArray[i];
tf.y = 280 + (i * 25);
tf.x = 265;
addChild(tf);
tf.name="test";}
}
btnClear.addEventListener (MouseEvent.CLICK, txtClear);
function txtClear(event:Event){
myArray.splice(1);
if (tf.numChildren != 0){
removeChild(getChildByName("test"));}
}
Alternatively, when I add
var tf:TF = new TF;
It removes only one displayed value on screen. Also I might add, that "TF" is a movie clip in the library that contains a dynamic text field that's instance name is txt. Is the problem only with the last button, or should I change something else as well? I don't know how to make this work as I want it to. I'm pretty new to coding so any tips or help would be much appreciated. Thanks in advance!
In your condition if(tf.numChildren != 0) the tf object is null since you never created it. That's why you're getting the #1009 error.
On the other hand, in order to delete all items you should replace the if (tf.numChildren != 0) with while (tf.numChildren != 0).