Dictionary uses values as keys - actionscript-3

--Or so it seems. Confused about the AS3 Dictionary. I have this:
map = new Dictionary();
map["someKey"] = 1;
And I try to print it out in two ways:
for each( var key:Object in d ) {
trace( key + ": " + d[key] );
}
This prints 1: undefined
for each( var o:Object in d ) {
var key:String = o.toString();
var val:int = d[o];
trace( key + ": " + val );
}
This prints 1: null
I would expect that it comes out as someyKey: 1. Am I just printing it out wrong?

As shown in Efficient looping through AS3 dictionary you loop though it the wrong way. You should be doing:
for ( var key:Object in d ) {
trace( key + ": " + d[key] );
}

Related

Using recursion, how do you iterate over an object to produce HTML?

I am trying to sort an object of key:values recursively. It seems to work , at least to the console. The code takes the object and iterates over the key value pairs. If it finds another object it calls itself to iterate over that object. The problem I have is that the subsequent call doesn't seem to produce any html, but it does show the key value pairs in the console. This is my first attempt at recursion, I'm not sure if it's the way I'm declaring variables or if I'm missing something in how recursion works.
$(document).ready(function(){
let conditionReport = {
weekNo:"5",
laps:"8",
heat:"6",
feature:"9",
tireSize:
{lf:"15",lr:"16",rf:"16.5",rr:"17"},
airPressure:
{lf:"8",lr:"10",rf:"12",rr:"16"},
tireTemperature:
{lf:"9",lr:"11",rf:"13",rr:"15"},
suspensionAdjustment:
{lf:"4",lr:"5",rf:"6",rr:"7"},
engineRPM:"2000",
trackCondition:"4",
damage2car:"3",
suspensionAdjustment2:
{upper:
{lf:"4",lr:"5",rf:"6",rr:"7"},
lower:
{lf:"4",lr:"5",rf:"6",rr:"7"},
},
notes:"note 3"
}
s = x => document.getElementById(x);
const isObject = val => (typeof val === "object") ? true : false;
const getKeyValue = (obj) => {
let html = '<ul>';
for(let key in obj) {
let value = obj[key]
if(!isObject(value)){
//console.log(isObject(value));
console.log(key + ":" + value);
html += '<li>' + key + ":" + value + "</li>";
}
else{
if(isObject(value)){
//console.log(isObject(value));
console.log(key + "=>");
getKeyValue(value);
html += '<li>' + key + ":"+ "</li>";
}
}
}
html += "</ul>";
s('cards').innerHTML = html;
}
getKeyValue(conditionReport);
});
Use return values:
const getKeyValue = (obj) => {
let html = '<ul>';
for (let key in obj) {
let value = obj[key]
if (!isObject(value)) {
html += '<li>' + key + ":" + value + "</li>";
} else {
var innerValue = getKeyValue(value);
// ^^^^^^^^^^^^^^^^
html += '<li>' + key + ":"+ innerValue + "</li>";
// ^^^^^^^^^^
}
}
html += "</ul>";
return html;
// ^^^^^^
}
Then do
s('cards').innerHTML = getKeyValue(conditionReport);

Make my AS3 code go fetch information on a website that I don't own

There is this website : http://www.swellmap.co.nz/ and I'd like to make my AS3 code go fetch some infos and displays it flash.
Is it possible if I don't own the website ?
Exemple :
I want to display these infos in my AS3 code. Is this possible ? How can I do ?
Thx for your help,
EDIT
Thx to the full answer of VC.One I've managed to paste infos in a String.
Here's what I did :
var myString:String;
var request:URLRequest = new URLRequest("http://www.swellmap.co.nz/ajr.php?r=plugin&a=Surfing&s=Anse%20Vata&country=nz&swellmap=1&country=ncd&swellmap=1&_=1460963404274");
var loader:URLLoader = new URLLoader();
loader.load(request);
loader.addEventListener(Event.COMPLETE,weatherLoaded);
function weatherLoaded(e:Event):void{
myString = e.target.data;
trace(myString); //output is {"tides":"High: 05:40 am (1.32 m); Low: 12:10 pm (0.57 m); High: 06:10 pm (1.19 m); ","seatemp":"27°C","forecastdate":"17h","rating":"<img src='http:\/\/www.swellmap.co.nz\/style\/img\/weathericons\/1r.png' alt='Poor conditions' title='Poor conditions' \/>","rating_class":"<span class='badge badge-important' alt='Poor conditions' title='Poor conditions'>1<\/span>","summary":"<img class='wx-summary' src='http:\/\/www.swellmap.co.nz\/style\/img\/weathericons\/suncloud.png' title='Sunny with some cloud' \/>","title":"Anse Vata","smaplink":"http:\/\/www.swellmap.co.nz\/surfing\/new-caledonia\/anse-vata","vars":{"hs_sw":{"value":"0.4","title":"Swell","unit":"m"},"hs":{"value":"0.6","title":"Wave","unit":"m"},"wface":{"value":"0.8","title":"Set face","unit":"m"},"tp":{"value":"13","title":"Period","unit":"s"},"dpm":{"value":"S","title":"Swell dir","unit":"°"},"windma":{"value":"E 12","title":"Wind","unit":"kts"},"gstma":{"value":"16","title":"Gusts","unit":"kts"}}}
}
Now, I didn't quite understand how could I retrieve only some infos (like the swell for exemple).
Is it possible to show me in AS3 code, how could I do that ? (in this exemple, we can see that the swell is "0.4 m # 13 s")
exemple of what I'd like to do :
function(searchTheSwell){
var swell_AnseVata;
swell_AnseVata =.... ?
info_txt.text = swell_AnseVata;
}
If you use the Developer Tools of your browser then you'll see that there's a PHP file being accessed to get the information. It starts http://www.swellmap.co.nz/ajr.php?r= and you need to find what it says for you. Now to view the contents just remove the part of the URL with &callback=XYZ where XYZ will be whatever the link has..
1)
Here's an example of how to get data for a location :
http://www.swellmap.co.nz/ajr.php?r=plugin&a=Surfing&s=ZZZZZ&country=nz&swellmap=1&country=YYY&swellmap=1&_=1460950764514
Replace &s=ZZZZZ with name of location, so if I want Anse Vata it becomes &s=Anse%20Vata and La Nera becomes &s=La%20Nera. So use %20 for any spaces in location name. Replace &country=YYY with example &country=fra.
2)
To get the JSON data for Anse Vata, declare your new String variable to later hold the JSON text and then just use URLStream in AS3 to load the link (open in browser tab to check contents) : http://www.swellmap.co.nz/ajr.php?r=plugin&a=Surfing&s=Anse%20Vata&country=nz&swellmap=1&country=ncd&swellmap=1&_=1460963404274
In the Event Complete listener function of URLStream you just use (example) myString = e.target.data;. Then use a JSON parser on your myString or do it manually yourself using String functions (like indexOf to word search).
3) If you opened the above link in an new tab you'll see the JSON entries you need to parse.
Swell : "hs_sw":{"value":"0.4","title":"Swell","unit":"m"} and for
extracting the # 13 s period use :
"tp":{"value":"13","title":"Period","unit":"s"}
Wind : "windma":{"value":"E 12","title":"Wind","unit":"kts"}
Icon : "summary":"<img class='wx-summary'
src='http:\/\/www.swellmap.co.nz\/style\/img\/weathericons\/suncloud.png'
You'll have to clean up the icon links so it becomes for example :
http://www.swellmap.co.nz/style/img/weathericons/suncloud.png
EDIT :
The code below extracts the expected information from the JSON string. Just replace &s= with any other location (eg: &s=Ilot%20Tenia) and it extracts the Swell, Wind and Icon URL entries...
var myURL : String = "http://www.swellmap.co.nz/ajr.php?r=plugin&a=Surfing&s=Anse%20Vata&country=nz&swellmap=1&country=ncd&swellmap=1&_=1460963404274";
var URL_Req : URLRequest = new URLRequest( myURL );
var URL_load:URLLoader = new URLLoader();
URL_load.addEventListener(Event.COMPLETE, completeHandler);
try { URL_load.load( URL_Req ); }
catch (error:Error)
{ trace("Could not load - Please check URL is correct : " + error.message); }
var idx_start : int = 0; var idx_end : int = 0;
var str_Swell : String = "";
var str_Swell_Period : String = "";
var str_Swell_Dir : String = "";
var str_Wind : String = ""; var url_Icon : String = "";
function completeHandler(e : Event):void
{
//var myData : Object = JSON.parse(e.target.data);
//for each (var s:* in myData) { trace("key:",s,"value:",myData[s]); }
var myString : String = String(e.target.data);
//trace ( "myString : " + myString);
//# Get Swell
idx_start = myString.indexOf("\"hs_sw\":" , 0 );
idx_end = myString.indexOf("," , idx_start + 1 );
str_Swell = myString.substring(idx_start + 18, idx_end-1);
str_Swell = str_Swell + " m";
//trace ("Swell : " + str_Swell );
//# Get Direction (for Swell)
idx_start = myString.indexOf("\"dpm\":" , 0 );
idx_end = myString.indexOf("," , idx_start + 1 );
str_Swell_Dir = myString.substring(idx_start + 16, idx_end-1);
//trace ("Swell dir : " + str_Swell_Dir );
//# Get time Period (for Swell)
idx_start = myString.indexOf("\"tp\":" , 0 );
idx_end = myString.indexOf("," , idx_start + 1 );
str_Swell_Period = myString.substring(idx_start + 15, idx_end-1);
str_Swell_Period = " # " + str_Swell_Period + " s";
//trace ("Period : " + string_Period );
//# Join Swell Direction, Size & Period entries into one sentence
str_Swell = str_Swell_Dir + " " + str_Swell + str_Swell_Period;
trace ("Swell : " + str_Swell );
//# Get Wind
idx_start = myString.indexOf("\"windma\":" , 0 );
idx_end = myString.indexOf("," , idx_start + 1 );
str_Wind = myString.substring(idx_start + 19, idx_end-1);
str_Wind = str_Wind + " kts";
trace ("Wind : " + str_Wind );
//# get Image URL
idx_start = myString.indexOf("\'wx-summary\'" , 0 );
idx_end = myString.indexOf("'" , idx_start + 18 );
url_Icon = myString.substring(idx_start + 18, idx_end);
url_Icon = url_Icon.replace(/\\/g, "");
trace ("URL : " + url_Icon );
//# load image using : new URLRequest (url_Icon);
}

Sorted Object/Map in AS3 Flex?

Is it possible to sort an object or have some sort of order in an object in Actionscript 3 Flex? I have an object which is created like so:
private var data:Object = new Object();
I then go on to put some keys and values into it:
this.data.someKeyOne = 0;
this.data.someKeyTwo = 1337;
this.data.someKeyThree = 123;
After that I loop through the object:
for (var dataPart:String in this.data) {
trace("Key: " + dataPart = " Value:" + this.data["dataPart"]);
}
But my issue is that the data will not be displayed in the order I initialized them in. This is frustrating as it is required to be in the order initialized.
As #helloflash said in his answer about loop through an object, and according to Adobe's definition of associative array (which is an instance of the Object class) :
An associative array, sometimes called a hash or map, uses keys instead of a numeric index to organize stored values. Each key in an associative array is a unique string that is used to access a stored value. An associative array is an instance of the Object class, which means that each key corresponds to a property name. Associative arrays are unordered collections of key and value pairs. Your code should not expect the keys of an associative array to be in a specific order.
The behavior that you got is normal and you can not get ordered keys in your case (using an Object like that).
If you don't need keys, you can do as #helloflash said in his answer, using a simple Array or Vector. Otherwise you can use an Array of objects, like this :
var obj:Object, i:int, s:String;
var data_array:Array = [
{key: 'someKeyOne', value: 0},
{key: 'someKeyTwo', value: 1337},
{key: 'someKeyThree', value: 123}
]
for(i = 0; i < data_array.length; i++){
obj = data_array[i];
trace('Key : ' + obj.key + ', Value = ' + obj.value);
}
for (s in data_array) {
obj = data_array[s];
trace('Key : ' + obj.key + ', Value = ' + obj.value);
}
for each (obj in data_array){
trace('Key : ' + obj.key + ', Value = ' + obj.value);
}
// all these 3 loops give :
// Key : someKeyOne, Value = 0
// Key : someKeyTwo, Value = 1337
// Key : someKeyThree, Value = 123
Or you can use Object and then sort it into an Array like this :
var data_object:Object = new Object();
data_object.someKeyOne = {index:0, value: 0};
data_object.someKeyTwo = {index:1, value: 1337};
data_object.someKeyThree = {index:2, value: 123};
var tmp_array:Array = sort_obj(data_object);
for(i = 0; i < tmp_array.length; i++){
obj = tmp_array[i];
trace('Key : ' + obj.key + ', Value = ' + obj.value);
}
for (obj in tmp_array) {
obj = tmp_array[obj];
trace('Key : ' + obj.key + ', Value = ' + obj.value);
}
for each (obj in tmp_array){
trace('Key : ' + obj.key + ', Value = ' + obj.value);
}
function sort_obj(obj:Object):Array {
var a:Array = [];
for (var key:String in obj) {
a.push({key: key, index: obj[key].index, value: obj[key].value});
}
a.sortOn('index', Array.NUMERIC);
return a;
}
// all these 3 loops give :
// Key : someKeyOne, Value = 0
// Key : someKeyTwo, Value = 1337
// Key : someKeyThree, Value = 123
Hope all that can help you.
Adobe help about looping:
The for..in loop iterates through the properties of an object, or the
elements of an array. For example, you can use a for..in loop to
iterate through the properties of a generic object (object properties
are not kept in any particular order, so properties may appear in a
seemingly random order)
Conclusion
If you want your keys to appear in order, you must use an Array (or a Vector):
var myArray:Array = [0, 1337, 123];
for (var i:String in myArray) {
trace(myArray[i]);
}
// output: 0, 1337, 123

How to access name of key in dynamically created json in action script 3

I have a json object coming from my java code as string :
{
"ABC":["ABC","XYZ","pqr"],
"OMG":["ABC","XYZ","pqr"],
"Hello":["ABC","XYZ","pqr"]
}
on decoding it as
myObj : Object = JSON.decode(result);
Now how do I access key names like ABC, OMG, HELLO...??
Try this will help you.
When you want properties in object use for-in loop or you want value use foreach statement.
var obj:Object = {
"ABC":["ABC","XYZ","pqr"],
"OMG":["ABC","XYZ","pqr"],
"Hello":["ABC","XYZ","pqr"]
};
var jsonText:String = JSON.stringify(obj);
var jsonObj:Object = JSON.parse(jsonText);
for(var key:String in jsonObj){
Alert.show("Key is"+key + " value is "+ jsonObj[key]);
}
Your case exactly
var myObj:Object = JSON.decode(result);
for(var key:String in myObj){
Alert.show("Key is"+key + " value is "+ myObj[key]);
}

Issue while converting actionscript object into XML

I'm new to flex. I'm trying to convert a complex object into an XML.
I'm facing a problem when i'm trying to traverse through the object. here i'm adding the code snippet.
Creating Employee Object
var result:String = new String();
employeeDept = new EmployeeDept();
employee = new Employee();
employee.employeeId = "56789";
employee.employeeName = "XYZ";
//tempString = tempString + "--- Step n ---";
/*employee.employeeDept.deptId = "2";
employee.employeeDept.deptName = "APPLE";*/
employeeDept=new EmployeeDept();
employeeDept.deptId = "3";
employeeDept.deptName = "MS";
employee.employeeDept.addItem(employeeDept);
employeeDept=new EmployeeDept();
employeeDept.deptId = "2";
employeeDept.deptName = "APPLE";
employee.employeeDept.addItem(employeeDept);
empCollection.addItem(employee);
Calling converter method on employee object
recursive(employee, "ShopServiceLifeCycleArtifacts");
Converter method
public function recursive(obj:Object, str:String):String
{
try
{
var xml:XML=new XML('<' + str + '></' + str + '>' );
if(obj is Array && obj.length!=0)
{ //tempString = tempString + "--- Recursive IF Loop---" + obj.length;
var ac:ArrayCollection=new ArrayCollection(obj as Array);
var xml2:XML=new XML(<dept></dept>);
for (var i:Number=0; i<ac.length; i++)
{
var myObj:Object=ac.getItemAt(i);
for (var prop:String in myObj)
{
xml2.appendChild(new XML("<" + prop + ">" + myObj[prop] + "</" + prop + ">"));
}
}
xml.appendChild(xml2);
} else {
if (obj==null)
tempString = tempString + "--- Obj is null ---";
else
{
tempString = tempString + "--- Obj is not null ---";
}
for (var property:String in obj)
{
tempString = tempString + property;
if(obj[property] is Array)
{
tempString = tempString + "--- obj[property] is Array---";
xml.appendChild(recursive(obj[property] as Array, property));
} else {
tempString = tempString + "--- obj[property] is not Array---";
xml.appendChild(XML("<" + property + ">" + obj[property].toString() + "</" + property + ">"));
}
}
}
}catch(e:Error)
{
return tempString+"----------"+e.message;
}
tempString = tempString +xml.toString();
return xml.toString();
}
}
But the issue now is, my employee object is not an array so it will go to else block. I'm check whether the object is null. Object is not null.
I'm going to next step i.e. for loop
for (var property:String in obj){
here comes the issue. Its not going into this for loop & returning null. :(
instead of creating employee object in an action script file & geting a instance of that employee in here if i declare & define an employeeName object here only then the logic is working. i will show that code also.
else {
//tempString = tempString + "--- Recursive Else Loop---";
var employeeNew:Object = {employeeId:"123", employeeName:"San Francisco",
empDept :[{empDeptId:"12345", empDeptName:"XYZ"},{empDeptId:"54568", empDeptName:"ABC"}]};
for (var prop:String in employeeNew) {
//trace("myObject."+prop+" = "+employeeNew[prop]);
if(employeeNew[prop] is Array)
{
xml.appendChild(recursive(employeeNew[prop] as Array, prop));
} else {
tempString = tempString + "--- obj[property] is not Array---";
xml.appendChild(XML("<" + prop + ">" + employeeNew[prop].toString() + "</" + prop + ">"));
}
}
If i use this object its able to convert it into XML. Plz do let me know what is the mistake i'm doing here because of which i'm not able to traverse through the object.
Thanks in Advance.
The for ... in loop only works on dynamic properties of objects. A dynamic property is one that can be added to the object/class at run time.
Your second approach works because you are iterating over an actual Object to which you have added properties to.
The first example does not work because you are iterating over an Employee object. The employee class is not marked as dynamic, and therefore it you cannot add additional properties to it. Even if you made it dynamic (which has a performance impact), it would only iterate over the additional properties that you added at run time, not the properties you define in the class.
One solution to this type of problem is to use describeType():
looping through object property names in actionscript
http://www.actionscript.org/forums/showthread.php3?t=183820