AS3 Object Name & Value - actionscript-3

i am trying to return the Value of the Objects name, any help would be a huge help! thank you.
var o:Object = new Object();
var n:String = "NAME"
o[n] = "DATA";
for each (var p in o){
trace("name="+o[p]+" data="+p);
}
outputs -
name=undefined data=DATA
where it should be outputting -
name=NAME data=DATA

For looping thru Object properties, drop the "each":
var o:Object = new Object();
var n:String = "NAME"
o[n] = "DATA";
for (var p in o)
{
trace("name="+o[p]+" data="+p);
}

I believe you want to use a regular for loop vs a "for each" loop http://active.tutsplus.com/tutorials/actionscript/as3-101-loops/

Related

Why does (myMC.myArray = myOtherMC.myOtherArray;) cause any changes to myMC.myArray to also change myOtherMC.myOtherArray?

var myArray:Array = new Array();
var myMC:MovieClip = new MovieClip();
myMC.myArray = myArray;
trace(myMC.myArray[10]); //Output: undefined
var newMC:MovieClip = new MovieClip();
newMC.myOtherArray = myMC.myArray;
newMC.myOtherArray[10] = [];
newMC.myOtherArray[10][0] = 100;
trace(myMC.myArray[10]); //Output: 100
Why does that happen, and is there any way to avoid it?
EDIT:
Found a function that can clone associative arrays here.
Here is the function (from the above link):
function clone(source:Object):*
{
var myBA:ByteArray = new ByteArray();
myBA.writeObject(source);
myBA.position = 0;
return(myBA.readObject());
}
Does making the function return type "*" mean that it can be any type? or is it something specific to objects/arrays?
It's because you have passed a reference of the original array to the new clip. Arrays, as objects, are not primitives and therefore will always be referenced.
If you would like to clone an array, keeping the original intact, use this method:
var b:Array = a.concat();
b will be a new array. a can modified without changing b.

ActionScript 3 - Removing Duplicates in ArrayCollection

I have an ArrayCollection of a list of usernames and user id's. In this list there are duplicates that I need to remove. I've searched the internet and while there are a lot of example of this using Arrays, I can't find any clear examples using ArrayCollection's.
The should be simpler then the other solution.
function removeDuplicatesInArray(val:*, index:uint, array:Array):Boolean {
return array.indexOf(val) == array.lastIndexOf(val);
}
function removeDuplicatesInCollection(collection:ArrayCollection):ArrayCollection {
collection.source = collection.source.filter(removeDuplicatesInArray);
return collection;
}
Here's what I found after quick googling.
//takes an AC and the filters out all duplicate entries
public function getUniqueValues (collection : ArrayCollection) : ArrayCollection {
var length : Number = collection.length;
var dic : Dictionary = new Dictionary();
//this should be whatever type of object you have inside your AC
var value : Object;
for(var i : int= 0; i < length; i++){
value = collection.getItemAt(i);
dic[value] = value;
}
//this bit goes through the dictionary and puts data into a new AC
var unique = new ArrayCollection();
for(var prop:String in dic){
unique.addItem(dic[prop]);
}
return unique;
}
If you find solutions for the array you can do the same with the ArrayCollection. You can change arrayCollection.source and arrayCollection will be changed too. In general, we can assume that ArrayCollection is wrapper for Array.
Array contain a filter function and we can make use of it as following.
var ar:Array = ["Joe","Bob","Curl","Curl"];
var distinctData = ar.filter(function(itm, i){
return ar.indexOf(itm)== i;
});
Alert.show(distinctData.join(","));
Or better yet
Array.prototype.distinct = function():*
{
var arr:Array = this as Array;
return arr.filter(function(itm, i){
return (this as Array).indexOf(itm)== i;
},arr);
};
var ar:Array = ["Joe","Bob","Curl","Curl"];
Alert.show(ar.distinct());
function removeDuplicateElement(_arr:Array):Array{
//set new Dictionary
var lDic:Dictionary = new Dictionary();
for each(var thisElement:* in _arr){
//All values of duplicate entries will be overwritten
lDic[thisElement] = true;
}
_arr = [];
for(var lKey:* in lDic){
_arr.push(lKey);
}
return _arr;
}

AS3 Sort a Collection of Objects?

In AS3, how do i sort this list alphabetically? I'm not a programming expert and i've had a hard time just figuring this out.
var searchObject:Object = new Object();
var mapXML:XML;
var xmlLoader:URLLoader = new URLLoader();
xmlLoader.load(new URLRequest("interactive-map.xml"));
xmlLoader.addEventListener(Event.COMPLETE, parseXML);
function parseXML(event:Event):void {
mapXML = new XML(event.target.data);
for each (var locationElement:XML in mapXML.maplocation) {
searchObject.locationname = locationElement.attribute("locationname");
searchObject.category = locationElement.attribute("category");
trace("Location Name: " + searchObject.locationname);
}
}
first you need to push elements to array/vector.
Then you can sort array with sortOn or sort methods.
Check sortOn/sort methods reference to find sorting options.
var searchObject:Object = new Object();
var searchObjectArray:Array = new Array
var mapXML:XML;
var xmlLoader:URLLoader = new URLLoader();
xmlLoader.load(new URLRequest("interactive-map.xml"));
xmlLoader.addEventListener(Event.COMPLETE, parseXML);
function parseXML(event:Event):void {
mapXML = new XML(event.target.data);
for each (var locationElement:XML in mapXML.maplocation) {
searchObject = new Object();
searchObject.locationname = locationElement.attribute("locationname");
searchObject.category = locationElement.attribute("category");
searchObjectArray.push(searchObject);//pushing elements to array
}
searchObjectArray.sortOn("locationname")//sorting array
for each ( var searchObjectElement:Object in searchObjectArray)
{
trace("Location name: " + searchObjectElement.locationname);//printing sorted array
}
}
Try something ike this:
var nodes:Array = [];
for each (var locationElement:XML in mapXML.maplocation) {
nodes[nodes.length] = locationElement;
}
nodes.sortOn(locationname);
I'm not sure if this will work with XML array elements. If it doesn't, try using sort() with a compareFunction.
I think you need to somehow wrap this in a collection class or map it over like Amy suggests, here's an example that uses an XMLCollection http://www.webdevotion.be/blog/2008/01/22/how-to-sort-an-xmllist-using-e4x/

Dynamically generated Object

I need to dynamically generate a object like this
{type:"typeA",size28:0,size29:0,size30:0 etc...}
I get the sizes from a xml file as an array and I need to insert it like this
{type:"typeA",here the generated size array but as the object properties}
How can I do this?
Thanks in advance.
I assume that the length of the array is variable:
var obj : Object = {type:"typeA"}
for (var i : int = 0; i < generatedArray.length; i++) {
obj['size'+(28+i)] = generatedArray[i];
}
var xmlData:XML = <obj>
<contents>size28:5,size29:3,size30:9</contents>
</obj>;
var obj:Object = new Object();
var xmlObjArray:Array = xmlData.contents.split(",");
for (var i in xmlObjArray)
{
var objProp:Array = xmlObjArray[i].split(":");
obj[objProp[0]] = objProp[1];
}
trace (obj.size29);

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.