as3 air File.File.applicationDirectory.resolvePath - check when loaded - arrays

I am trying to load folder names into an array for later use. It works fine on my desktop but when I test it on a mobile device (both Android and iPhone) and it is calling another function - displayFlags(); - before I get the folder names into an array.
displayFlags() needs this array of names to work and I am getting errors from this line in of code in displayFlags(); Again its because the array is empty.
flag.load(new URLRequest(LangPath[i] + "/flag.png"));
Below is the code that loads file and the array.
Is there a way to check when the array is available and call a function after its loaded?
var folderLanguages:File = File.applicationDirectory.resolvePath("Languages");
var availLang:Array = folderLanguages.getDirectoryListing();
var Lang:Array;
var LangPath:Array;
var flagButton:MovieClip;
function getLang(evt:Event = null)
{
Lang = new Array();
LangPath = new Array();
for (var i:uint = 0; i < availLang.length; i++)
{
if(availLang[i].isDirectory)
{
//trace(availLang[i].name);// gets the name
Lang.push(availLang[i].name);
LangPath.push(availLang[i].nativePath);
trace(availLang[i].nativePath);// gets the name
}
}
displayFlags();
}

Related

Cannot push past 1 element to basic AS3 Array

I am very new to this and hoping it's something that should have been obvious.
When I run the code below, the Array newHole and newArray both return 1 on the trace. Originally the code was built with only the newHole array, but I created the newArray in the hopes of troubleshooting. It did not help. The class for bulletHole contains no extra code so I didn't post that.
Thank you.
import flash.display.*;
import flash.events.*;
import flash.ui.Mouse;
Mouse.hide();
var myReticle:MovieClip;
var holeArray:Array = new Array();
var randomHole:Number = randomNumber(1, 5);
var newHole:bulletHole = new bulletHole();
var newArray:Array = new Array();
stage.addEventListener(MouseEvent.MOUSE_MOVE, followReticle);
stage.addEventListener(MouseEvent.CLICK, myFire);
stage.addEventListener(MouseEvent.CLICK, checkCount);
function followReticle(event:MouseEvent):void
{
myReticle.x = mouseX;
myReticle.y = mouseY;
}
function myFire(int):void
{
stage.addChild(newHole);
newHole.x = myReticle.x;
newHole.y = myReticle.y;
//holeArray.push(newHole);
newHole.gotoAndStop(randomHole);
//trace(holeArray.length);
}
function checkCount(int):void
{
newArray.push("A");
trace(newArray.length);
}
function randomNumber(low:Number=0, high:Number=1):Number
{
return Math.floor(Math.random() * (1+high-low)) + low;
}
Most likely the issue is that the code you've posted is running over and over again. In other words, you have a looping timeline that eventually goes back to the frame that the code you've shown is on.
Whenever that frame is reached, you have the following:
var holeArray:Array = new Array();
Which creates a new array replacing what used to be in that var.
To solve this, you either need to:
take the code out of the timeline (put it in a class file and attach that as the document class of your project)
re-architect your timeline so the first frame is only reached 1 time
put some checks in so that the code only runs the first time the frame is reached.
Here is an example of the latter option:
//just define the array, don't create it
var holeArray:Array;
//if the array is null, create it (it will only be null the first time this code is run
if(!holeArray){
holeArray = new Array();
}
This line is incorrect:
function myFire(int):void {
Because the function is triggered from a mouse event listener it should read:
function myFire(e:MouseEvent):void {
What you are doing is passing a undefined int to the function. Hope this helps.
EDIT: You should delete the clickCount event listener and function as they're not needed.
Also notice that you should move this line to the top of your myFire function or else you will keep replacing this MovieClip instead of creating it again:
var newHole:bulletHole = new bulletHole();

What is the best effective way to collect data from a table using protractor?

What is the best effective way to collect data from a table using protractor.
I collecting the data shown in the code below and it is taking 20-30 seconds for 10 rows.
The buildStr counter is for creating a object for every row, 8 is the number of columns.
row = {};
gridRows = [];
element.all(by.css('#contenttableGrid div[role="gridcell"] div')).each(function(element){
element.getText().then(function(text){
row[headerName[buildStr]] = text;
buildStr++;
if(buildStr === 8){
buildStr = 0;
gridRows[rowCounter] = row;
rowCounter++;
row = {};
}
});
});
One way to speed it up that I see is to extract all the data right on the page by injecting script on it. It could be done with the help of browser.executeScript() (docs). In your sample Protractor has to make a request to the browser any time you call getText(), nubmer of calls it makes = number of cells in your table. But using browser.executeScript() it will make one call and do all the stuff in the browser, which can be really fast. Then you can simply return this data back to a test spec and use it via Promises.
var headerName = {};
// I assume that this variable holds names for headers
// you can pass data from test spec to injected script as arguments (below)
// promise will be resolved with the value you return from `executeScript`
var promise = browser.executeScript(function (headerName) {
// all the stuff inside this function happens on your page under test
// it is not a Protractor environment
var buildStr = 0;
var rowCounter = 0;
var row = {};
var gridRows = [];
var cells = document.querySelectorAll('#contenttableGrid div[role="gridcell"] div');
for (var i = 0, l = cells.length; i < l; i++) {
var text = cells[i].textContent;
// `headerName` object is passed as an argument from test spec
row[headerName[buildStr]] = text;
buildStr++;
if (buildStr === 8) {
buildStr = 0;
gridRows[rowCounter] = row;
rowCounter++;
row = {};
}
}
// return all collected data back to test spec
return gridRows;
}, headerName); // pass helper object from test spec to injectable function
promise.then(function (gridData) {
console.log(gridData); // result of computations
});
Make sure to read docs for browser.executeScript() if you want to use it, because it has a lot of specific moments.

In Actionscript 3, how to create many instances of the same symbol?

Though coding, I must make many copies of the same MovieClip to be placed on the stage, each to be manipulated code-wise on its own
For instance, I have a MovieClip named MC and I wish to have 99 copies of ít loaded onto the stage, each in a different x coordinate. What should I do?
I think on doing this:
Step 1: in the library, turning MC into a class
Step 2: placing the following code in the scene's script
var MyArray:Array = new Array
for (var i:int = 0; i<99;i++)
{
var MCInstance:MC = new MC
MC Instance = MyArray[i]
MovieClip.(MyArray[i]).x = i*30
}
Would that make sense?
That's probably the right idea, your syntax is just a little off. Try this:
var myArray:Array = [];
for (var i:int = 0; i < 99;i++)
{
var mc:MC = new MC();
myArray[i] = mc;
mc.x = i * 30
}
AS3 style conventions: use lowerCamelCase for variable names, don't omit constructor parens even though they are optional, and create arrays using literals (source).
You could push each MovieClip to an Array after adding it to the Stage.
var myArray = [];
for(var i:int = 0; i < 99; i++)
{
var myMc:MC = new MC();
addChild(myMc);
myMc.x = myMc.width * i + 2;
myMc.y = 10;
myArray.push(myMc);
}

AS2 push to array outside of clip does nothing

was wondering if someone could show me what I'm doing wrong here.
I have some old AS2 flash code I'm trying to get working.
First I create a few arrays in frame 1 of the main timeline like so-
var typeArr:Array = new Array();
for (var i:Number = 1; i < 5; i++)
{
_root.typeArr[i] = "data goes here";
}
Then I have a movieclip dynamically attached on the main stage that when clicked appends one of the arrays we created by pushing the string 'foo' to it-
stop();
_root.myType=3;//this can be any of our array numbers
this.onPress=function(){
var foo:String="test";
_root.typeArr[_root.myType].push(foo);
trace(_root.typeArr[_root.myType]);
}
Where _root.typeArr[_root.myType] is the array name and number _root.typeArr3, but pushing the data does not work and returns nothing.
However, if I test it directly using-
_root.typeArr[_root.myType]=foo;
It will store the data once (_root.typeArr3=test), so I can't see why it won't push to that array as multiple elements each time like- "test,test,test"
It's driving me crazy.
Thanks! :)
_root.typeArr[_root.myType] is equal to "data goes here" so you are pushing string to a string, which doesn't work.
If you would like to append the new string, you should do something like:
_root.typeArr[_root.myType]+=foo;
and you will get: data goes heretest
If you have different data structure instead of "data goes here" the key may lie in the format of this data.
var typeArr:Array = new Array();
// 'i' must start from 0 because the first element is typeArr[0]
for (var i:Number = 0; i < 5; i++)
{
typeArr[i] = i;
// trace(typeArr[i]); // 0,1,2,3,4
}
// trace(typeArr); // 0,1,2,3,4
myType = 3;
bt.onPress = function()
{
var foo:String = "test";
// push method puts the element at the end of your array
// typeArr.push(foo);
// trace(typeArr); // 0,1,2,3,4,test
// splice method replace the 4e element (index 3) of your array
typeArr.splice(myType, 1, foo);
trace(typeArr); // 0,1,2,test,4
}

Reordering an array in flash as3

I have an array of objects, each of which is assigned an ID when it is first created. I give the user the ability to visually reorder the objects, which changes their position in the array. They then have the option to save that order using a flash sharedObject or "cookie" and then later, if they reopen the flash file, I want them to be able to hit a button to restore that order. I'm just not sure what the syntax would be to set the object's index within the array. Here's my code:
VARIABLES:
var project_settings = SharedObject.getLocal("settings"); //saves all project settings for the next time the file is opened
var project_order:Array = []; //saves project order for the next time the file is opened
var project_display:Array = []; //saves whether each project should be displayed or hidden for the next time the file is opened
SAVE CODE:
function saveOrder(){
for (var i=0;i<project_array.length;i++){
project_order[i] = project_array[i].id;
project_display[i] = project_array[i].projectThumb.thumbActive;
}
project_settings.data.order = project_order;
project_settings.data.active = project_display;
//trace (project_settings.data.active[1]);
project_settings.flush(); //saves most recent "cookie"
}
RESTORE CODE:
function loadOrder(){
for (var i=0;i<project_array.length;i++){
/* NEED THE CODE THAT GOES HERE. BASICALLY, PROJECT_ARRAY[i] SHOULD BE THE ITEM WITH AN ID EQUAL TO PROJECT_SETTINGS.DATA.ORDER[i] */
}
}
Something like this should work:
function loadOrder()
{
var dict = new Dictionary();
for (var i = 0; i < project_array.length; i++)
dict[project_array[i].id] = project_array[i];
project_array = [];
for (var i = 0; i < project_settings.data.order.length; i++)
project_array[i] = dict[project_settings.data.order[i]];
}
Just load in your array and sort on the ID. Something like this should work:
private function _loadArray():void
{
// fill in your array
project_array.sort( this._sortFunc );
}
// replace the * by whatever your object type is
private function _sortFunc( a:*, b:* ):int
{
return a.id - b.id;
}
More info: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/Array.html#sort()
Or even the sortOn() function (which might be easier) should work:
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/Array.html#sortOn()

Resources