Actionscript: get textfields and assign them dynamically - actionscript-3

I'm trying to create a highscore list.
I have a movieclip ("highscore") and in it i have dynamic textfields with instance names. Now i'm trying to get those textfields so that i can change the text inside. Since i'm getting them in a loop i get them with getChildByName (and this works). But what i get back is a displayObject and therefore i get the error: implicit coercion of a value of type class to an unrelated type...
I know what the error is.. but i have no idea how to fix it.
Here is my code:
private function updateSingleList(result:XML):void
{
if(result['header']['success'] != 'true'){
return;
}
for(var i:uint = 0; i < result['items']['item'].length(); i++)
{
var pos:uint = i+1;
var name:String = 'name_' + pos;
var score:String = 'score_' + pos;
var rowName:TextField = highscore.getChildByName(name);
var rowScore:TextField = highscore.getChildByName(score);
rowName.text = result['items']['item'][i]['name'].toString();
rowScore.text = result['items']['item'][i]['score'].toString();
}
}
thanks!

Specify that the child you want is a TextField :
var rowName:TextField = highscore.getChildByName('name_' + pos) as TextField;
rowName.text = result['items']['item'][i]['name'].toString();

Related

Remove the clicked objects

I'm trying to remove the array objects that are being clicked and add them into another array to display them else where. I posted the current code.
I think the problem maybe with .currentTarget. I tried replacing the .currentTarget to .target but the function wasn't getting past this line : if (socket_Array[i] == in_event.target) (in this version its .currentTarget, I am just saying when I tried changing it to .target)
The error I get is this:
TypeError: Error #1034: Type Coercion failed: cannot convert []#2c2a8f11 to flash.display.DisplayObject.
Function that creates the objects:
function createSockets():void
{
var socket_one:socket = new socket ();
var socket_two: socketyellow = new socketyellow ();
var socket_three: socketdarkorange = new socketdarkorange ();
var socket_four: socketlightgreen= new socketlightgreen ();
var socket_five: socketpurple = new socketpurple ();
var socket_six: socketdarkgreen = new socketdarkgreen ();
socket_Array.push(socket_one, socket_two,socket_three, socket_four, socket_five, socket_six);
for (var i:int=0; i<socket_Array.length; i++)
{
addChild(socket_Array[i]);
socket_Array [i].x = socket_x_position;
socket_Array [i].y = socket_y_position;
socket_Array[i].addEventListener(MouseEvent.MOUSE_DOWN, removeItemOnClick);
}
temp_update ();
}
Function that is suppose to get rid of the object clicked and add it to an array.
function removeItemOnClick(in_event:MouseEvent):void
{
var i:int = 0;
for (i=0; i<socket_Array.length; i++)
{
if (socket_Array[i] == in_event.currentTarget)
{
trace ("it goes here");
var removed = socket_Array.splice(i, 1);
trace (removed);
trace (socket_Array );
var drop:Sprite = in_event.currentTarget as Sprite;
removeChild (drop);
removedItem[removedItem.length] = removed;
createremovedItem ();
trace (removedItem);
updateDisplay ();
choice_updateDisplay ();
}
}
}
var removedItem_position = 0
function createremovedItem () {
for (removedItem_position; removedItem_position<removedItem.length; removedItem_position++){
addChild (removedItem [removedItem_position]);
}
}
First of all, .currentTarget is correct.
Secondly, there's no point in calling removeChild() and then calling addChild(). The net effect of both calls is nothing.
Almost all of the code in the second function is unnecessary. Here's a shorter version:
function removeItemOnClick(in_event:MouseEvent):void {
var index:int = socket_Array.indexOf(in_event.currentTarget);
var drop:Sprite = socket_Array.splice(index,1) as Sprite;
removedItem.push(drop);
updateDisplay();
choice_updateDisplay();
}
If you want to display the new item elsewhere, just change drop.x and drop.y.
As the error suggests it looks like it is problem with type coercion.
Try to replace the condition of your if statement with this:
if (DisplayObject(socket_Array[i]) == DisplayObject(in_event.currentTarget))
In case this is not working your might have more information while debugging by storing the two objects you want to compare into temporary variables

I cant remove child of this movie clip upon clicking the back button to go function goHomePage (evt:Event):void{

Help. I need to remove the newContainer(this is a movie clip) after clicking the back button to go back to homepage.
But it just loads the homepage and the newContainer is still there. :( where did i go wrong?
import flash.events.MouseEvent;
import flash.events.Event;
import fl.motion.MotionEvent;
import flash.net.URLVariables;
import flash.display.MovieClip;
import flashx.textLayout.elements.Configuration;
var ctr:int = 0;
var now:Date = new Date();
var myurl:String = "http://localhost:8888/eventspictures/getdata.php";
var scriptLoader:URLLoader = new URLLoader();
var scriptRequest:URLRequest = new URLRequest();
var newContainer:MovieClip;
scriptRequest.url = myurl + "?ck=" + now.getTime();
scriptLoader.addEventListener(Event.COMPLETE, handleLoadSuccess);
scriptLoader.addEventListener(IOErrorEvent.IO_ERROR, handleError);
scriptRequest.method = URLRequestMethod.POST;
scriptLoader.load(scriptRequest);
function handleLoadSuccess(evt:Event):void
{
for (var j:Number = 0; j <4; j++)
{
var newContainer:MovieClip = new con();
newContainer.name = String(ctr);
newContainer.y = j*80 +65;
newContainer.x= 16;
stage.addChild(newContainer);
var variables:URLVariables = new URLVariables(evt.target.data);
trace(variables.output);
var parse:String = variables.output;
var parsed:Array = parse.split("<|>");
var tab:String = ' ';
var eventname:String = '';
var date:String='';
var slotsleft:String='';
// different variable names to assign to different column names(etc; eventname, date, slotsleft)
// loop through.. start from O
for (var i:Number = 0; i<parsed.length-1; i++)
{
trace(parsed[i]);
var item:String = parsed[i];
var itemarray:Array = item.split(",");
eventname += itemarray[2] + tab + "<br>";
date += itemarray[3] + tab;
slotsleft += itemarray[4] + tab;
trace(eventname);
newContainer.eventname_txt.htmlText = eventname;
newContainer.date_txt.htmlText= date;
newContainer.slotsleft_txt.htmlText=slotsleft;
}
}
//slotsleft_txt.x = 270;
}
function handleError(evt:IOErrorEvent):void
{
}
backbutton_mc.addEventListener(MouseEvent.CLICK, goHomePage);
function goHomePage (evt:Event):void{
gotoAndPlay("dashboard");
removeChild(newContainer);
}
stop();
In your function handleLoadSuccess() you have a loop that creates 4 MovieClip's and adds them to the stage.
But in your goHomePage() function you only try to remove one object from the stage. It turns out this object is probably null in your example (trying to remove an object that is null should generate an error if you are using the debug Flash player).
The reason it is probably null is because you have defined two variables named newContainer in your code: one is declared at the beginning of the script, and the second one inside the function handleLoadSuccess() (because you are using the keyword var on each line).
The variable created inside the function only exists while that function is executing. The variable created outside the function never seems to receive a value.
Two approaches you can use:
Keep track of the things you add to the stage, by putting them in an Array:
Replace the newContainer variable that is outside the function with an Array called containers:
var containers:Array = [];
In the function handleLoadSuccess(), when you add each MovieClip to the stage, also add them to the containers array:
stage.addChild(newContainer);
containers.push(newContainer);
Finally in the function goHomePage() iterate over the containers array to remove each MovieClip:
for (var j:int = 0; j < containers.length; j++)
{
stage.removeChild( containers[j] );
}
// reset the containers array so it's empty for the next time
// and to remove the references to the MovieClips (to prevent a memory leak)
containers=[];
Blindly remove everything from the stage
If this is accetpable, it is much easier. Just iterate backwards over the children of the stage in your goHomePage() function:
for (var j:int = stage.numChildren; j >= 1; j--)
{
stage.removeChildAt(j - 1);
}

as3 error loading "good" "bad" array

I am creating a "good" "bad" array to display on screen which i can later use simple if statements to do something upon if the player has collided with the "good" "bad" objects.
I cant get the objects to randomly generate on screen with the following code.
// Create and Set good/bad random Word objects
public function newObject(e:Event)
{
var goodObjects:Array = ["WordObject1"];
var badObjects:Array = ["WordObject2"];
if (Math.random() < .5)
{
var r:int = Math.floor(Math.random()*goodObjects.length);
var classRef:Class = getDefinitionByName(goodObjects[r]) as Class;
var newObject:MovieClip = new classRef();
newObject.typestr = "good";
} else
{
r = Math.floor(Math.random()*badObjects.length);
classRef = getDefinitionByName(badObjects[r]) as Class;
newObject = new classRef();
newObject.typestr = "bad";
}
newObject.x = Math.random();
newObject.y = Math.random();
addChild(newObject);
objects.push(newObject);
placeWords();
}
// create random Word objects
public function placeWords() {
objects = new Array();
for(var i:int=0;i<numWordObjects;i++) {
// loop forever
while (true) {
// random location
var x:Number = Math.floor(Math.random()*mapRect.width)+mapRect.x;
var y:Number = Math.floor(Math.random()*mapRect.height)+mapRect.y;
// check all blocks to see if it is over any
var isOnBlock:Boolean = false;
for(var j:int=0;j<blocks.length;j++) {
if (blocks[j].hitTestPoint(x+gamesprite.x,y+gamesprite.y)) {
isOnBlock = true;
break;
}
}
// not over any, so use location
if (!isOnBlock) {
newObject.x = x;
newObject.y = y;
newObject.gotoAndStop(Math.floor(Math.random()*1)+1);
gamesprite.addChild(newObject);
objects.splice(newObject);
break;
}
}
}
}
i get the following errors:
1119: Access of possibly undefined property x through a reference with static type Function.
1119: Access of possibly undefined property y through a reference with static type Function.
1067: Implicit coercion of a value of type Function to an unrelated type flash.display:DisplayObject.
Try renaming var x and var y to something else. Those are public properties in any class that extends as a display object (Sprite/MovieClip/Shape).

Closure problem? - passing current value of a variable

I'm trying to pass the current value of a variable when an a dynamically generated navigation 'node' is clicked. This needs to just be an integer, but it always results in the last node's value.. have tried some different methods to pass the value, a custom event listener, a setter, but I suspect it's a closure problem.. help would be appreciated ;-)
function callGrid():void {
for (var i:Number = 0; i < my_total; i++) {
var gridnode_url = my_grid[i].#gridnode;
var news_category= my_grid[i].#category;
var newstitle = my_grid[i].#newstitle;
var news_content = my_grid[i]..news_content;
var news_image = my_grid[i]..news_image;
var gridnode_loader = new Loader();
container_mc.addChild(gridnode_loader);
container_mc.mouseChildren = false;
gridnode_loader.load(new URLRequest(gridnode_url));
gridnode_loader.contentLoaderInfo.addEventListener(Event.COMPLETE, gridLoaded);
gridnode_loader.name = i;
text_container_mc = new MovieClip();
text_container_mc.x = 0;
text_container_mc.mouseEnabled = false;
var textY = text_container_mc.y = (my_gridnode_height+18)*y_counter;
addChild(text_container_mc);
var tf:TextSplash=new TextSplash(newstitle,10,0,4 );
container_mc.addChild(tf);
tf.mouseEnabled = false;
tf.height = my_gridnode_height;
text_container_mc.addChild(tf);
var text_container_mc_tween = new Tween(text_container_mc, "alpha", Strong.easeIn, 0,1,0.1, true);
gridnode_loader.x = (my_gridnode_width+5) * x_counter;
gridnode_loader.y = (my_gridnode_height+15) * y_counter;
if (x_counter+1 < columns) {
x_counter++;
} else {
x_counter = 0;
y_counter++;
}
}
}
function gridLoaded(e:Event):void {
var i:uint;
var my_gridnode:Loader = Loader(e.target.loader);
container_mc.addChild(my_gridnode);
_xmlnewstarget = my_gridnode.name;
//||||||||||||||||||||||||||||||||||||||||
//when a particular grid node is clicked I need to send the current _xmlnewstarget value to the LoadNewsContent function...
//||||||||||||| ||||||||||||||||||||||||
my_tweens[Number(my_gridnode.name)]=new Tween(my_gridnode, "alpha", Strong.easeIn, 0,1,0.1, true);
my_gridnode.contentLoaderInfo.removeEventListener(Event.COMPLETE, gridLoaded);
my_gridnode.addEventListener(MouseEvent.CLICK, loadNewsContent);
}
function loadNewsContent(e:MouseEvent):void {
createNewsContainer();
getXMLNewsTarget();
news_category = my_grid[_xmlnewstarget].#category;
var tfnews_category:TextSplash=new TextSplash(news_category,20,16,32,false,false,0xffffff );
tfnews_category.mouseEnabled = false;
newstitle = my_grid[_xmlnewstarget].#newstitle;
var tftitle:TextSplash=new TextSplash(newstitle,20,70,24,false,false,0x333333 );
news_container_mc.addChild(tftitle);
tftitle.mouseEnabled = false;
news_content = my_grid[_xmlnewstarget]..news_content;
var tfnews_content:TextSplash=new TextSplash(news_content,20,110,20,true,true,0x333333,330);
news_container_mc.addChild(tfnews_content);
tfnews_content.mouseEnabled = false;
news_image = my_grid[_xmlnewstarget].#news_image;
loadNewsImage();
addChild(tfnews_category);
addChild(tftitle);
addChild(tfnews_content);
var news_container_mc_tween = new Tween(news_container_mc, "alpha", Strong.easeIn, 0,1,0.3, true);
news_container_mc_tween.addEventListener(Event.INIT, newsContentLoaded);
}
I'm not going to try to read your code (try to work on your formatting, even if it's just indenting), but I'll provide a simplified example:
for (var i = 0; i < my_total; i++) {
var closure = function() {
// use i here
}
}
As you say, when closure is called it will contain the last value of i (which in this case would be my_total). Do this instead:
for (var i = 0; i < my_total; i++) {
(function(i) {
var closure = function() {
// use i here
}
})(i);
}
This creates another function inside the loop which "captures" the current value of i so that your closure can refer to that value.
See also How does the (function() {})() construct work and why do people use it? for further similar examples.
Umm, as mentioned above, the code is a bit dense, but I think you might have a bit of type conversion problem between string and integers, is the "last value" always 0? try making these changes and let me know how you get on.
// replace this gridnode_loader.name = i;
gridnode_loader.name = i.toString();
// explictly type this as an int
_xmlnewstarget = parseInt(my_gridnode.name);
// replace this: my_tweens[Number(my_gridnode.name)] = new Tween(......
my_tweens[parseInt(my_gridnode.name)] = new Tween();
Oh and I think it goes without saying that you should massively refactor this code block once you've got it working.
Edit: after further study I think you need this
//replace this: my_gridnode.addEventListener(MouseEvent.CLICK, loadNewsContent);
var anonHandler:Function = function(e:MouseEvent):void
{
loadNewsContent(_xmlnewstarget);
};
my_gridnode.addEventListener(MouseEvent.CLICK, anonHandler);
Where your loadNewsContent has changed arguements from (e:MouseEvent) to (id:String)
Firstly, you do not need to call addChild for the same loader twice (once in callGrid) and then in (gridLoaded). Then you can try putting inside loadNewsContent: news_category = my_grid[int(e.target.name)].#category;instead of news_category = my_grid[_xmlnewstarget].#category; As _xmlnewstarget seems to be bigger scope, which is why it is getting updated every time a load operation completes.

Creating multiple TextInput fields in for loop

I need to loop through an array and for each element create a textfield. My problem is how to create a new identifier for each new TextInput
this is my code;
var count:Number = 0;
for (var i:String in columnsData)
{
var myTI:TextInput = new TextInput();
myTI.width = 70;
myTI.height = 25;
myTI.text = columnsData[i];
myTI.name = "myTI" + count;
addChild(myTI);
count++;
}
all this does however is overwrite the previously created TextInput field, any ideas?
Try this:
var count:uint = 0,
textInputs:Array /* of TextInputs */ = [];
for(var i:String in columnsData){
textInputs[count] = new TextInput();
// Customize textInput[count] instead of myTI
addChild(textInputs[count]);
count++;
}
Outside of this loop, you should be able to look inside the textInputs array for references to each of your new TextInputs. Note that, inside the loop, you probably want to change the x/y coordinates for each TextInput so they don't overlap.