Locale.loadLanguageXML() Won't work in external script - actionscript-3

I have a script for multi-language-use working when added to the first frame of a timeline. However, when I try to adapt it to work in an external .as script, it throws a TypeError and I can't figure out why.
Here is the code that works in a timeline:
import fl.data.DataProvider;
import fl.text.TLFTextField;
import flash.text.Font;
import flashx.textLayout.elements.*;
import flashx.textLayout.formats.*;
//------------------
// CREATE TLFTEXTFIELD:
var field_001:TLFTextField = new TLFTextField();
field_001.x = 20;
field_001.y = 50;
field_001.width = 342
field_001.height = 54;
field_001.background = true;
addChild(field_001);
// Create text format
var format:TextLayoutFormat = new TextLayoutFormat();
format.fontFamily = "Arial";
format.fontSize = 36;
format.color = 0x666666;
// Apply the format
var textFlow:TextFlow = field_001.textFlow;
textFlow.hostFormat = format;
//------------------
// SETUP LOCALE OBJECT:
var languages:Object = new Object(); // Stores flags for loaded languages
var localeDefault:String = "ar"; // Default language
var locale:String = "ar"; // Current language selected in combobox
// Event handler for Locale object
function localeLoadedHandler(success:Boolean):void
{
if( success )
{
// Mark language as loaded and show localized string
languages[locale] = true;
field_001.text = Locale.loadStringEx("IDS_FIRSTFIELD", locale);
// field_002 is a field already on stage
field_002.text = Locale.loadStringEx("IDS_SECONDFIELD", locale);
}
}
// Load the default language...
Locale.setDefaultLang(localeDefault);
Locale.setLoadCallback(localeLoadedHandler);
trace("Locale.getDefaultLang() is: " + Locale.getDefaultLang());
Locale.loadLanguageXML(Locale.getDefaultLang());
Here is my adaptation to an external script and set up as the class for a standalone swf called "tempchild.swf" I want to open inside a parent swf at a later time:
package com.marsinc {
import fl.text.TLFTextField;
import flash.text.Font;
import flashx.textLayout.elements.*;
import flashx.textLayout.formats.*;
import flash.display.MovieClip;
import fl.lang.Locale;
public class tempchild extends MovieClip {
//------------------
// SETUP LOCALE OBJECT:
private var languages:Object; // Stores flags for loaded languages
private var localeDefault:String; // Default language
private var locale:String; // Current language selected in combobox
private var field_001:TLFTextField;
private var format:TextLayoutFormat;
public function tempchild()
{
// constructor code
languages = new Object();
localeDefault = "es";
locale = "es";
//------------------
// CREATE TLFTEXTFIELD:
field_001 = new TLFTextField();
field_001.x = 20;
field_001.y = 50;
field_001.width = 342
field_001.height = 54;
field_001.background = true;
addChild(field_001);
// Create text format
format = new TextLayoutFormat();
format.fontFamily = "Arial";
format.fontSize = 36;
format.color = 0x666666;
// Apply the format
var textFlow:TextFlow = field_001.textFlow;
textFlow.hostFormat = format;
// Load the default language...
Locale.setDefaultLang(localeDefault);
Locale.setLoadCallback(localeLoadedHandler);
trace("Locale.getDefaultLang() is: " + Locale.getDefaultLang()); // displays "es"
Locale.loadLanguageXML(Locale.getDefaultLang()); // this line returns an error
}
// Event handler for Locale object
private function localeLoadedHandler(success:Boolean):void
{
trace("running the loaded handler");
if( success )
{
// Mark language as loaded and show localized string
languages[locale] = true;
field_001.text = Locale.loadStringEx("IDS_FIRSTFIELD", locale);
//field_002.text = Locale.loadStringEx("IDS_SECONDFIELD", locale);
}
}
}
And this is the error in the output window:
TypeError: Error #1010: A term is undefined and has no properties.
at fl.lang::Locale$/loadXML()
at fl.lang::Locale$/loadLanguageXML()
at com.marsinc::tempchild()
Been digging around for an answer for a couple days now and I am stuck. Any help is greatly appreciated. Thanks!
--Kevin

You can make it .as file in one of (at least) two ways
1) copy paste all exactly as it is to .as file and do:
include "[path]filename.as"
2) change the code to be a class
- make field_001, format, textFlow, languages, localeDefault, locale as public vars
- insert all code in a function named "init"
- add the "localeLoadedHandler" as a function
- click on your stage and change in the properties panel the stage's class to the new class
Good Luck!!

Related

Access of undefined propety and other errors (AS3)

ok so I am trying to work on making my scripts external .as files.
I had them on the timeline and they worked fine but when I put them in the as file they don't work at all.
This is my code as of right now
so I got the script working externally thank you very much :)
I just need to addchild to the stage. I use
import Scripts.resources.main;
var Main:main = new main;
addChild(Main);
In my external script I addchild in the main function now.
package Scripts.resources
{
import flash.events.Event;
import flash.events.MouseEvent;
import flash.net.URLRequest;
import flash.net.URLVariables;
import flash.net.URLLoader;
import flash.net.URLRequestMethod;
import flash.events.OutputProgressEvent;
import flash.display.Sprite;
import flash.display.MovieClip;
import flash.display.Stage;
import flash.events.EventDispatcher;
public class main extends EventDispatcher{
private var _stage:Stage;
var url:String = "php/data_user.php";
//declare our graphic vars
var stmBar:resourceBar;
var tenBar:resourceBar;
var potBar:resourceBar;
var spdBar:resourceBar;
var crtBar:resourceBar;
var awrBar:resourceBar;
var resBar:resourceBar;
var statUp:Sprite;
//This Returns the number of milliseconds since midnight January 1, 1970
//Tacking the time variable at the end of your php file locations will ensure their is no caching
var now:Date = new Date();
var time:Number = now.getTime();
/*
* These should point to your PHP files. I recommend NOT using an http path because accessing
* the site via 'www.yoursite.com' versus 'yoursite.com' makes a difference and will cause undefined
* issues. Instead use a relative path like: var registerLocation:String = "membership/php/register.php";
*/
var registerLocation:String = "php/register.php" + "?" + time;
var loginLocation:String = "php/login.php" + "?" + time;
var editProfileLocation:String = "php/editprofile.php" + "?" + time;
var forgotPWLocation:String = "php/forgotpw.php" + "?" + time;
var statsLocation:String = "php/user_stats.php" + "?" + time;
var statsGylph:String = "php/data_user.php" + "?" + time;
//userInfo is the Object that gets populated that stores all of the users information.
var userInfo:Object = new Object();
//The minimum length of a password.
var passwordLength:Number = 4;
/*
* var cookie refers to swfObjects addVariable. If you look at membership.php, where swf
* object is defined, addVariable shows a var called usercookie.
* This help decide if the program should remember the users username or not.
*/
//cookieUserName would be the username that gets put into the user field if the cookie has been set
public function main(stage:Stage)
{
_stage = stage;
var _loader:URLLoader = new URLLoader();
var _request:URLRequest = new URLRequest(url + "?id=" + userInfo.id);
_request.method = URLRequestMethod.GET;
_loader.addEventListener(Event.COMPLETE, onLoadData);
_loader.load(_request);
_stage.addChild(stmBar);
stmBar.x = -50;
stmBar.y = 200;
}
public function MyClass(){
this.addEventListener(Event.ADDED_TO_STAGE, addedToStage);
}
private function addedToStage(e:Event):void {
this.removeEventListener(Event.ADDED_TO_STAGE, addedToStage);
//this code will run after you've added this object to the stage
//it is the equivalent of when timeline code runs
}
function onLoadData(e:Event):void {
var str:String = e.target.data;
var array:Array =str.split("-");
for(var i:int;i < array.length; i++)
output(i+1,array[i]);
}
public function output(field:Number,i:int):void
{
if (field == 5)
{
stmBar = new resourceBar(0, 0, i, "Stamina", 0x990000);
stmBar.x = -200;
stmBar.y = 50;
}
else if (field == 6)
{
tenBar = new resourceBar(0, 0, i, "Tenacity", 0xFF9900);
tenBar.x = 200;
tenBar.y = 50;
}
else if (field == 7)
{
potBar = new resourceBar(0, 0, i, "Potency", 0xCC3399);
potBar.x = -200;
potBar.y = 100;
}
else if (field == 8)
{
spdBar = new resourceBar(0, 0, i, "Speed", 0x00CC00);
spdBar.x = 200;
spdBar.y = 100;
}
else if (field == 9)
{
crtBar = new resourceBar(0, 0, i, "Crit", 0x009999);
crtBar.x = -200;
crtBar.y = 150;
}
else if (field == 10)
{
awrBar = new resourceBar(0, 0, i, "Awareness", 0x3399CC);
awrBar.x = 200;
awrBar.y = 150;
}
else if (field == 11)
{
resBar = new resourceBar(0, 0, i, "Resistance", 0x999999);
resBar.x = -200;
resBar.y = 200;
addEventListener(Event.ENTER_FRAME, onLoop);
}
function onLoop(e:Event):void
{
stmBar.change(1);
tenBar.change(1);
potBar.change(1);
spdBar.change(1);
crtBar.change(1);
awrBar.change(1);
resBar.change(1);
}
}
}
}
my problem is it won't add the children in the main function when I addchild of main. am I able to add a child with children inside it?
In class files, all code needs to be wrapped in a function. So where you have:
_loader = new URLLoader();
_request = new URLRequest(url + "?id=" + (STAGE.parent as MovieClip).userInfo.id);
_request.method = URLRequestMethod.GET;
_loader.addEventListener(Event.COMPLETE, onLoadData);
_loader.load(_request);
You need to place it in a function for the code to be valid. If you want that bit of code to run right away, then you can place it in a constructor (that is the function in class that runs when you instantiate with the new keyword, eg new main(). If main is your document class, then the constructor is the very first code to run in the application.
Constructors are public functions that have the exact name of your Class.
public function main(){
_loader = new URLLoader();
_request = new URLRequest(url + "?id=" + (STAGE.parent as MovieClip).userInfo.id);
_request.method = URLRequestMethod.GET;
_loader.addEventListener(Event.COMPLETE, onLoadData);
_loader.load(_request);
}
Something to keep in mind, is that in the constructor of display objects, the stage/parent/root keywords will NOT have any value, as those are populated once the display object has been added to the display. So, it's common to use this approach:
package MyClass extends Sprite {
public function MyClass(){
this.addEventListener(Event.ADDED_TO_STAGE, addedToStage);
}
private function addedToStage(e:Event):void {
this.removeEventListener(Event.ADDED_TO_STAGE, addedToStage);
//this code will run after you've added this object to the stage
//it is the equivalent of when timeline code runs
}
}
Also, a tip now that you are writing class files - follow the convention of making class names start with an Uppercase letter, and instances of classes start with lowercase letters.

Is it possible to make looped Movieclip clickable and Session data at the same time?

I am new to AS3, and i am trying to achieve the following situation.
First i receive the JSON data,sort them and put them into boxes . Each box has its set of data, e.g.Box1 (Name1,Location1,Zip1), Box2(Name2,Location2,Zip2) so on.
Boxes are put into another AS file for display, and will be put into a viewport slider.
Trying to make the boxes clickable, and when a box is clicked, it will go to next page and display the details of that specific "Listing".
1st thing is, how to make the movieclip box clickable when it is sitting inside another as file.
2nd thing is, how to pull the data from that box when it is clicked, as it is generated by the looped JSON data. (As i need to use the ID from the listing to parse it to the php to pull the details and display the full detail in the next as file.
Thanks for your time!
AS file where the boxes are generated.
package com.clark
{
import flash.display.MovieClip;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;
import flash.text.TextFormatAlign;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
public class SearchVectorTest extends MovieClip
{
public function SearchVectorTest(test:Vector.<searchVO1>)
{
super();
for (var j:int = 0; j < test.length; j++)
{
trace(test[j].nobed);
trace(test[j].zip);
trace(test[j].Location);
trace(test[j].price);
}
var len:int = test ? test.length : 0;
listings = new Vector.<Listing8>(len, true);
var currentY:int = 100;
for (var k:int = 0; k < test.length; k++)
{
var Bolder:Listing2 = new Listing2();
Bolder.x=20;
var bf:TextField = new TextField();
var bf1:TextField = new TextField();
var bf2:TextField = new TextField();
var bf3:TextField = new TextField();
bf3.width = 100;
bf.defaultTextFormat = new TextFormat("Arial", 12, 0, null, null, null, null, null, TextFormatAlign.CENTER);
bf.width = 100;
bf.autoSize = TextFieldAutoSize.CENTER;
bf1.width = 100;
bf1.autoSize = TextFieldAutoSize.CENTER;
bf2.autoSize = TextFieldAutoSize.CENTER;
bf3.autoSize = TextFieldAutoSize.CENTER;
bf3.width = 100;
bf1.y= bf.height+5;
bf.text = test[k].nobed;
bf1.text = test[k].zip;
bf2.text = test[k].Location;
bf3.text = test[k].price;
bf.x = (Bolder.height-bf.height)*.2
Bolder.addChild(bf);
Bolder.addChild(bf1);
Bolder.addChild(bf2);
Bolder.addChild(bf3);
Bolder.properties = test[k].nobed;
Bolder.properties = test[k].zip;
// position the object based on the accumulating variable.
Bolder.y = currentY;
addChild(Bolder);
Bolder.mouseChildren = false; // ignore children mouseEvents
Bolder.mouseEnabled = true; // enable mouse on the object - normally set to true by default
Bolder.useHandCursor = true; // add hand cursor on mouse over
Bolder.buttonMode = true;
listings[k] = Bolder;
currentY += Bolder.height + 10;
}
}
}
}
AS file where the VectTest file sits
package com.clark
{
import flash.display.*;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.display.Stage;
import fl.controls.Button;
public class sresultnologin extends MovieClip {
public var s1:Searchreult = new Searchreult ();
public function sresultnologin(){
addEventListener(Event.ADDED_TO_STAGE, onadded);
function onadded (event:Event):void{
s1.x=-10;
s1.y=10;
addChild(s1);
}
var s3:SearchVectorTest= new SearchVectorTest(new Vector.<searchVO1>);
addChild (s3);
s1.SRhome.addEventListener(MouseEvent.CLICK, fl_ClickToGoTol);
s1.ARsearch.addEventListener(MouseEvent.CLICK, fl_ClickToGosearch);
if( s3.listings.length > 0 )
{
// get the first listing in the listing array
var newListing:Listing8 = s3.listings[0];
newListing.addEventListener(MouseEvent.CLICK, gotoscener);
}
else
{
//
}
}
// private methods
private function fl_ClickToGoTol(event:MouseEvent):void
{
var s9:Account = new Account ();
removeChild(s1);
addChild(s9);
}
private function fl_ClickToGosearch(event:MouseEvent):void
{
var s9:searchVO1 = new searchVO1 ();
removeChild(s1);
addChild(s9);
}
}
}
Edit(Added in SearchVectorTest)
var len:int = test ? test.length : 0;
listings = new Vector.<Listing8>(len, true);
Edit(Added in sresultnologin)
if( s3.listings.length > 0 )
{
// get the first listing in the listing array
var newListing:Listing8 = s3.listings[0];
newListing.addEventListener(MouseEvent.CLICK, gotoscener);
}
else
{
//
}
One
The "other as file" (a class) must be instantiated, and (as a DisplayObject) must be added to the stage for it to become visible.
Consider the following stage layout:
root:MainTimeline ¬
0: background:Shape
1: listingWindow:Slider
And the sresultnologin (when instantiated) looks like this:
this:sresultnologin ¬
0: s3:SearchVectorTest ¬
0: Bolder:Listing2 ¬
0: bf:TextField
1: bf1:TextField
2: bf2:TextField
3: bf3:TextField
1: s1:Searchreult
All you need to do is addChild(sresultnologin) to the stage (or your Slider), and those child elements will appear.
To make it clickable, simply attach the listener to your object via object.addEventListener("mouseUp", listener). This can be done at any point: in the constructor of SearchVectorTest, or sresultnologin, or after it's been added to the stage when your "box is clicked" and the new listing appears. If you wanted to do that from the document code, it might look like this:
var newListing:Listing2 = listingWindow.getChildAt(0).getChildAt(0).getChildAt(0);
newListing.addEventListener("mouseUp", doStuff);
However, that's wholly dependent on DisplayList indexes (which could change wildly). A better solution may be to name these items and use getChildByName("string") instead. That too, however, could be perilous if you have non-unique names for each object. Consequently, if you're adding these new listings from inside one of your classes (such as sresultnologin), you could simply provide a property on the class which points to the current listing, and reference that from document code.
Two
JSON data is no different from any other object structure in AS3. If you want, you could store it as a property of the class, and reference the variable at the appointed time. If you want to store data specific to a particular listing on the particular object which represents it, try adding to Bolder in SearchVectorTest the following:
Bolder.properties = test[k];
Edit:
Remember that the variable name is not the same as the name property on an object. In other words...
var Bolder:Listing2 = new Listing2(); // variable is Bolder, of type Listing2
Bolder.name = "foo" // the name property on Bolder is now "foo"
getChildByName("Bolder") // this should fail since there is no object with that name
getChildByName("foo") // works.
This really isn't complicated as long as you're aware of the differences. Please run the script I gave you (under "Pathing to Objects") which shows you the hierarchy of your stage. After you have the output, it should be self-explanatory what pathing you need to use to reference your variables.

TypeError: Error #1009 in AS3 flash cs6

I have got this error while working on my flash:
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at Options()
This is my Options class:
package {
import flash.display.MovieClip;
import fl.managers.StyleManager;
import flash.text.TextFormat;
import fl.events.ComponentEvent;
import fl.events.*;
import flash.events.MouseEvent;
import fl.controls.*;
import flash.net.SharedObject;
import flash.events.Event;
public class Options extends MovieClip
{
//DECLARE CLASS VARIABLES//
//DECLARE COMPONENT VARIABLES
private var cComponentFmt:TextFormat;
//DECLARE SAVE DATA VARIABLES
private var cPlayerData:Object;
private var cSavedGameData:SharedObject;
//DECLARE SOUND VARIABLES
public function Options()
{
//created the SharedObject using the getLocal() function
cSavedGameData = SharedObject.getLocal("savedPlayerData");
//set component formats
setComponents();
//initialize player's data
setPlayerData();
//set default message display upon entering the setup page
msgDisplay.text = "Introduce yourself to the fellow minions!";
//add event listeners
nameBox.addEventListener(MouseEvent.CLICK, clearName);
nameBox.addEventListener(ComponentEvent.ENTER, setName);
}
private function setComponents():void
{
//set the TextFormat for the components
cComponentFmt = new TextFormat();
cComponentFmt.color = 0x000000; //black colour
cComponentFmt.font = "Comic Sans MS"; //set default "Comic Sans MS"
cComponentFmt.size = 16;
//apply the new TextFormat to ALL the components
StyleManager.setStyle("textFormat", cComponentFmt);
}
private function setName(evt:ComponentEvent):void
{
trace("Processing text input box..");
// player pressed the ENTER key
cPlayerData.pName = nameBox.text;
msgDisplay.text = "Welcome, " + cPlayerData.pName + "! \nEnjoy many hours of fun with us!";
saveData();
}
private function clearName(evt:MouseEvent):void
{
// player CLICKED in the nameBox
nameBox.text = "";
}
private function setPlayerData():void
{
//all variables that relate to the player
cPlayerData = new Object();
//options related variables
cPlayerData.pName = "Papoi";
cPlayerData.sndTrack = "none";
//game related variables
cPlayerData.pScore = 0;
//save the player's data
saveData();
}
private function saveData():void
{
//savedPlayerData = cPlayerData is the name=value pair
cSavedGameData.data.savedPlayerData = cPlayerData;
//force Flash to update the data
cSavedGameData.flush();
//reload the newly saved data
loadData();
}
private function loadData():void
{
//gets the data stored in the SharedObject
//this particular line not found in the options.as
cSavedGameData = SharedObject.getLocal("savedPlayerData","/",false);
//now stores the save data in the player object
cPlayerData = cSavedGameData.data.savedPlayerData;
}
}
}
Does anyone know why this particular error exists?
And also, I want to make the cPlayerData.pName to be "Papoi" if a name is not entered in the nameBox. How am I to make that happen? Cuz right now, I tried by setting the cPlayerData.pName to "Papoi" by default, but it doesn't work. Hmm..
Your problem is in the constructor function so maybe the component “msgDisplay” and/or the component “nameBox” are/is not initialized completely yet while you are trying to access one of its properties...
A good practice is to access your objects only when they are fully initialized, that can be done using the event “AddedToSatge” which will not be fired before all children’s are initialized..
Note: even if it is not the source of your problem, it is a good thing to do always because it will save you from other problems and bugs related to the same issue.
UPDATE:
The problem was in your loadData() function, because you have changed the localPath of your SharedObject inside that function body (it is not the same as used in saveData() function), then your loaded data will always be null, and that was what you see in the error message. you just need to delete that line from loadData function. see my updated code below.
package
{
import flash.display.MovieClip;
import fl.managers.StyleManager;
import flash.text.TextFormat;
import fl.events.ComponentEvent;
import fl.events.*;
import flash.events.MouseEvent;
import fl.controls.*;
import flash.net.SharedObject;
import flash.events.Event;
public class Options extends MovieClip
{
//DECLARE CLASS VARIABLES//
//DECLARE COMPONENT VARIABLES
private var cComponentFmt:TextFormat;
//DECLARE SAVE DATA VARIABLES
private var cPlayerData:Object;
private var cSavedGameData:SharedObject;
//DECLARE SOUND VARIABLES
public function Options()
{
if (stage)
{
init();
}
else
{
addEventListener(Event.ADDED_TO_STAGE, init);
}
}
public function init(e:Event = null):void
{
// it is important to remove it coz you don't need it anymore:
removeEventListener(Event.ADDED_TO_STAGE, init);
//created the SharedObject using the getLocal() function
cSavedGameData = SharedObject.getLocal("savedPlayerData");
//set component formats
setComponents();
//initialize player's data
setPlayerData();
//set default message display upon entering the setup page
msgDisplay.text = "Introduce yourself to the fellow minions!";
//add event listeners
nameBox.addEventListener(MouseEvent.CLICK, clearName);
nameBox.addEventListener(ComponentEvent.ENTER, setName);
}
private function setComponents():void
{
//set the TextFormat for the components
cComponentFmt = new TextFormat();
cComponentFmt.color = 0x000000;//black colour
cComponentFmt.font = "Comic Sans MS";//set default "Comic Sans MS"
cComponentFmt.size = 16;
//apply the new TextFormat to ALL the components
StyleManager.setStyle("textFormat", cComponentFmt);
}
private function setName(evt:ComponentEvent):void
{
trace("Processing text input box..");
// player pressed the ENTER key
// remove the whitespace from the beginning and end of the name:
var playerNameWithoutSpaces:String = trimWhitespace(nameBox.text);
// check if the user did not enter his name then default name is "Papoi":
if (playerNameWithoutSpaces == "")
{
cPlayerData.pName = "Papoi";
}
else
{
cPlayerData.pName = nameBox.text;
}
//// This will replace the default message :
//// msgDisplay.text = "Welcome, " + cPlayerData.pName + "! \nEnjoy many hours of fun with us!";
// This will add the welcome message to the default message :
msgDisplay.text += "\nWelcome, " + cPlayerData.pName + "! \nEnjoy many hours of fun with us!";
saveData();
}
private function clearName(evt:MouseEvent):void
{
// player CLICKED in the nameBox
nameBox.text = "";
}
private function setPlayerData():void
{
//all variables that relate to the player
cPlayerData = new Object();
//options related variables
cPlayerData.pName = "Papoi";
cPlayerData.sndTrack = "none";
//game related variables
cPlayerData.pScore = 0;
//save the player's data
saveData();
}
private function saveData():void
{
//savedPlayerData = cPlayerData is the name=value pair
cSavedGameData.data.savedPlayerData = cPlayerData;
//force Flash to update the data
cSavedGameData.flush();
//reload the newly saved data;
loadData();
}
private function loadData():void
{
//gets the data stored in the SharedObject
//this particular line not found in the options.as
//// delete the next line, no need to set it every time :
//// cSavedGameData = SharedObject.getLocal("savedPlayerData","/",false);
//now stores the save data in the player object
cPlayerData = cSavedGameData.data.savedPlayerData;
}
//────────────────────────────────────────────
private function trimWhitespace($string:String):String
{
if ($string == null)
{
return "";
}
return $string.replace(/^\s+|\s+$/g, "");
}
//────────────────────────────────────────────
}
}

Flash AS3 FileReference - Select and Upload Multiple Files one at a time

I currently have an swf that allows you to select and display a file and upload it to the server using FileReference. This works great but i need to be able to select and display multiple (up to 25 in some cases) and then upload them all at the end.
I know you can use the FileReferenceList to select multiple files at the same time in the dialog popup but my issue is that the user needs to select one at a time, do stuff to that image, then select another, do stuff and so on... then at the end when they press upload it upload them all onto the server.
Is it possible or is there a way so i can maybe add every new selected file into an array, then at the end it uploads all the files in the array either in one go or loops through each until all objects in the array are complete?
Can anyone help? I'll post the full code for my working single file upload below.
Please, please help, i'm limited with flash and have only been learning for 3-4 months and i've been stuck for over a week now :(
Lauren
as3 Code:
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.net.FileReference;
import flash.net.FileFilter;
import flash.utils.ByteArray;
import flash.events.MouseEvent;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.display.MovieClip;
import fl.controls.ProgressBarMode;
import flash.display.Bitmap;
import flash.display.BitmapData;
progressBar.visible=false;
UploadprogressBar.visible=false;
// Create FileReference.
var imageFile:FileReference;
// Create Loader to hold image content
var image_loader:Loader = new Loader();
var image_content:Sprite = new Sprite();
// Get Extension Function.
var imageExtension;
function getExtension($url:String):String {
var extension:String = $url.substring($url.lastIndexOf(".")+1, $url.length);
return extension;
}
// Random Number Function to create new filename on server.
function randomNum(low:Number=0, high:Number=1):Number {
return Math.floor(Math.random() * (1+high-low)) + low;
}
var myNumber:Number= randomNum(1000,9999);
var myString:String= String(myNumber);
var RandomNumbers = myString;
var imageFilePath = (RandomNumbers);
// Select Button Function.
select_btn.addEventListener(MouseEvent.CLICK, onselect_btnClicked);
function onselect_btnClicked(event:MouseEvent):void {
imageFile=new FileReference();
imageFile.addEventListener(Event.SELECT, onFileSelected);
var imageTypeFilter:FileFilter = new FileFilter("JPG/PNG Files","*.jpeg; *.jpg;*.gif;*.png");
imageFile.browse([imageTypeFilter]);
}
// File Selected Function.
function onFileSelected(event:Event):void {
imageFile.addEventListener(Event.COMPLETE, onFileLoaded);
imageFile.addEventListener(ProgressEvent.PROGRESS, onProgress);
var imageFileName = imageFile.name;
imageExtension = getExtension(imageFileName);
imageFile.load();
progressBar.visible=true;
progressBar.mode=ProgressBarMode.MANUAL;
progressBar.minimum=0;
progressBar.maximum=100;
UploadprogressBar.mode=ProgressBarMode.MANUAL;
UploadprogressBar.minimum=0;
UploadprogressBar.maximum=100;
}
// File Progress Function.
function onProgress(event:ProgressEvent):void {
var percentLoaded:Number=event.bytesLoaded/event.bytesTotal*100;
progressBar.setProgress(percentLoaded, 100);
}
// File Loaded Function.
function onFileLoaded(event:Event):void {
var fileReference:FileReference=event.target as FileReference;
var data:ByteArray=fileReference["data"];
var movieClipLoader:Loader=new Loader();
movieClipLoader.loadBytes(data);
movieClipLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onMovieClipLoaderComplete);
imageFile.removeEventListener(Event.COMPLETE, onFileLoaded);
imageFile.removeEventListener(ProgressEvent.PROGRESS, onProgress);
}
// Load Image onto Stage Function.
function onMovieClipLoaderComplete(event:Event):void {
var loadedContent:DisplayObject=event.target.content;
image_loader =event.target.loader as Loader;
var scaleWidth:Number=345/image_loader.width;
image_loader.scaleX=image_loader.scaleY=scaleWidth;
image_loader.height=200;
image_loader.scaleX=image_loader.scaleY;
image_loader.x=10;
image_loader.y=10;
image_content.buttonMode=true;
image_content.addChild(image_loader);
addChild(image_content);
}
// Upload Button Function.
upload_btn.addEventListener(MouseEvent.CLICK, onupload_btnClicked);
function onupload_btnClicked(event:MouseEvent):void {
var filename:String=imageFile.name;
var urlRequest:URLRequest = new URLRequest("http://www.xxxxx.com/xxxxx/file-reference.php");
var variables:URLVariables = new URLVariables();
urlRequest.method = URLRequestMethod.POST;
imageFile.addEventListener(ProgressEvent.PROGRESS, onUploadProgress);
imageFile.addEventListener(DataEvent.UPLOAD_COMPLETE_DATA,onUploadComplete);
variables.ID = (RandomNumbers);
urlRequest.data = variables;
imageFile.upload(urlRequest);
}
// File Upload Progress Function.
function onUploadProgress(event:ProgressEvent):void {
var percentLoaded:Number=event.bytesLoaded/event.bytesTotal*100;
UploadprogressBar.setProgress(percentLoaded, 100);
trace("loaded: "+percentLoaded+"%");
upload_status_txt.text='upload in progress...';
}
// Upload File Completed Function.
function onUploadComplete(event:Event):void {
upload_status_txt.text='upload complete';
imageFile.removeEventListener(ProgressEvent.PROGRESS, onProgress);
imageFile.removeEventListener(DataEvent.UPLOAD_COMPLETE_DATA,onUploadComplete);
UploadprogressBar.visible=false;
}
php Server Code:
<?php
function getExtension($str) {
$i = strrpos($str,".");
if (!$i) { return ""; }
$l = strlen($str) - $i;
$ext = substr($str,$i+1,$l);
return $ext;
}
$fileID = $_POST['ID'];
$filename = basename( $_FILES['Filedata']['name']);
$extension = getExtension($filename);
$extension = strtolower($extension);
$uploadID = $fileID.'.'.$extension;
if (move_uploaded_file($_FILES['Filedata']['tmp_name'], "images/".$uploadID))
{
echo "OK";
}
else
{
echo "ERROR";
}
?>
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/FileReference.html
"When you call the FileReferenceList.browse() method, which creates an array of FileReference objects."
You need to use FileReferenceList instead of FileReference.

How can I make this Flash code work in IE when it's cached?

I have a flash file here, when the flash plays, it works fine, but in IE and if the flash was already loaded once and is now cached, it freezes up. After digging super deep on the internet I was able to find out the following:
There are a bunch of known bugs in
flash 9 and 10, one of those being an
issue with the Event.COMPLETE not
being fired from the main stage when
loading from cache when it's embedded
WMODE = "transparent" I'm not sure if
that's your issue, but it's worth
looking into. I've heard of a few
workarounds to the problem. One of
them being, not listening for for
progress or complete events at all and
just using a timed loop like
ENTER_FRAME or TIMER to watch the
bytesLoaded/bytesTotal.
My WMODE is window, but this makes the most sense to me. The loadText never gets set which tells me its not entering swfProgressHandle function. However the problem is I only wrote half this flash (everything inside init) in conjunction with someone else, but that other person I cannot get in contact with anymore. I am fairly new to flash so really don't know how to take his loading code and make it only run off timer events instead of progress and complete events (as said in the above quote) so that it will work in IE when cached. Can anyone help me on this? Most of the code is fine, it's just the beginning where those progress and complete handlers are for loading stuff that appears to be causing the issue.
package
{
//---Imports---
import flash.display.*;
import fl.transitions.Tween;
import fl.transitions.TweenEvent;
import fl.transitions.easing.*;
import flash.events.Event;
import flash.events.*;
import flash.events.IOErrorEvent;
import flash.events.ProgressEvent;
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.text.TextField;
import flash.utils.Timer;
import flash.utils.*;
import flash.text.Font;
public class FohLoader extends Sprite
{
//create and start load bar
private var loadBar:Sprite = new Sprite();
private var loadText:TextField = new TextField();
private var loadBarBg:Graphics = loadBar.graphics;
//load XML data
private var xmlLoader:URLLoader = new URLLoader();
private var xmlData:XML = new XML();
private var _queue:Array; //holds data objects of items to be loaded
private var _index:int; //the current item in the _queue
private var _images:Array; //holds DisplayObjects of the loaded images
public function FohLoader()
{
_queue = new Array();
_images = new Array();
_index = 0;
//waits for the stage to be created
addEventListener(Event.ADDED_TO_STAGE, stageReadyHandle);
}
private function stageReadyHandle(e:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, stageReadyHandle);
loadBarBg.lineStyle();
loadBarBg.beginFill(0x5a96c5, 1);
loadBarBg.drawRect(0, 0, 5, 10);
loadBarBg.endFill();
loadBar.x = (stage.stageWidth - 500)/2;
loadBar.y = 30;
loadBar.width = 5;
loadBar.height = 10;
this.addChild(loadBar);
loadText.x = (stage.stageWidth - 0)/2;
loadText.y = 50;
this.addChild(loadText);
//I have no idea if this crap works
//but you would have to do something like this if you want to keep your project to one swf file.
this.loaderInfo.addEventListener(ProgressEvent.PROGRESS, swfProgressHandle);
}
private function swfProgressHandle(e:ProgressEvent):void
{
//assumes you want the loadbar to be 500px at 100%
var getPercent:Number = bytesLoaded / e.bytesTotal;
trace(bytes_loaded + " of " + bytes_total + " loaded");
loadBar.width = getPercent * 150; //changed 500 to 150
loadText.text = String(Math.round(getPercent * 30) + "%"); //changed 100 to 30
if (e.bytesLoaded / e.bytesTotal >= 1)
{
e.target.removeEventListener(ProgressEvent.PROGRESS, swfProgressHandle);
loadXml();
}
}
private function loadXml()
{
xmlLoader.addEventListener(Event.COMPLETE, ParseXML);
xmlLoader.load(new URLRequest("flash.xml"));
}
private function ParseXML(e:Event):void
{
e.target.removeEventListener(Event.COMPLETE, ParseXML);
flashInputs = new XML(e.target.data);
//declare all XMl variables, terrible way to do it though
var imageURLList:XMLList = flashInputs.image_area.image.image_url;
var firmCount:XMLList = flashInputs.count_area.total_firms;
var quoteMsg:XMLList = flashInputs.quote_area.quote.quote_text;
var quoteOwner:XMLList = flashInputs.quote_area.quote.quote_owner;
var imageURL:XMLList = flashInputs.image_area.image.image_url;
var imageText:XMLList = flashInputs.image_area.image.image_text;
var quoteMsg0:XML = quoteMsg[0];
var quoteMsg1:XML = quoteMsg[1];
var quoteMsg2:XML = quoteMsg[2];
var quoteMsg3:XML = quoteMsg[3];
var quoteMsg4:XML = quoteMsg[4];
var quoteMsg5:XML = quoteMsg[5];
var quoteMsg6:XML = quoteMsg[6];
var quoteOwner0:XML = quoteOwner[0];
var quoteOwner1:XML = quoteOwner[1];
var quoteOwner2:XML = quoteOwner[2];
var quoteOwner3:XML = quoteOwner[3];
var quoteOwner4:XML = quoteOwner[4];
var quoteOwner5:XML = quoteOwner[5];
var quoteOwner6:XML = quoteOwner[6];
var imageText0:XML = imageText[0];
var imageText1:XML = imageText[1];
var imageText2:XML = imageText[2];
var imageText3:XML = imageText[3];
var imageText4:XML = imageText[4];
var imageText5:XML = imageText[5];
var imageText6:XML = imageText[6];
var imageURL0:XML = imageURL[0];
var imageURL1:XML = imageURL[1];
var imageURL2:XML = imageURL[2];
var imageURL3:XML = imageURL[3];
var imageURL4:XML = imageURL[4];
var imageURL5:XML = imageURL[5];
var imageURL6:XML = imageURL[6];
//loops through the imageURL array and adds each item to the queue
for each(var img:XML in imageURL)
{
addItem(String(img));
}
//loads the first item in the queue
loadItem();
}
//creates a new loader for the item
//adds a data object holding the item path and loader into the queue
private function addItem(path:String):void
{
var loader:Loader = new Loader();
_queue.push({loader:loader, path:path});
}
private function loadItem():void
{
_queue[_index].loader.contentLoaderInfo.addEventListener(Event.COMPLETE, imgCompleteHandle);
_queue[_index].loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, IOErrorHandle);
_queue[_index].loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, imgProgressHandle);
_queue[_index].loader.load(new URLRequest(_queue[_index].path));
}
//checks the progress of each image, and increases the width of the load bar
private function imgProgressHandle(e:ProgressEvent):void
{
var perc:Number = e.bytesLoaded / e.bytesTotal;
//this line assumes you are loading 6 images, and want the loadbar to end up at 500px
//it also assumes the bar has already reached 30% (150px) from loading the swf
loadBar.width = 150 + (_index * (350 / 6)) + ((350 / 6) * perc);
//so the swf's 150 + (how many images have alrady loaded * the width each image needs to affect the bar) +
//(same thing * percent of current image loaded)
//sounds right, might have to mess with that.
}
//this just stops flash from outputting an error if the image fails to load
private function IOErrorHandle(e:IOErrorEvent):void
{
e.target.removeEventListener(Event.COMPLETE, imgCompleteHandle);
e.target.removeEventListener(IOErrorEvent.IO_ERROR, IOErrorHandle);
trace("Error handled, sir.");
trace("The problem was that, " + e);
}
private function imgCompleteHandle(e:Event):void
{
e.target.removeEventListener(Event.COMPLETE, imgCompleteHandle);
e.target.removeEventListener(ProgressEvent.PROGRESS, imgProgressHandle);
e.target.removeEventListener(IOErrorEvent.IO_ERROR, IOErrorHandle);
//adds the image to the _images array
_images.push(e.target.content);
//increments the load counter
_index++;
//checks to see if the queue is finished or not
if (_index < _queue.length)
{
trade("Not done loading, loading another item");
loadItem();
}
else
{
_index = 0;
_queue = [];
killLoadBar();
init();
}
}
private function killLoadBar()
{
this.removeChild(loadBar);
this.removeChild(loadText);
}
If you dont mind the flash loading every time and not using the cache you could just append a cache breaker to the swf url.
Any random thing will do.
Here's a example using swfobject (http://code.google.com/p/swfobject/)
<script type="text/javascript">
var flashvars = {};
var params = {};
var attributes = {};
swfobject.embedSWF("myContent.swf?rand="+Math.random(), "myContent", "300", "120", "9.0.0","expressInstall.swf", flashvars, params, attributes);
</script>
This should work around any IE cache bugs.
If you still get the error with this, then it's should not be cache related.
After taking a quick look at this, I can see what might be happening.
You listen for ADDED_TO_STAGE.
You handle ADDED_TO_STAGE and then start listening for PROGRESS.
You then set the loadText, and load the XML if progress is "done".
The problem here seems to be the "done" part and the progress handling. First, the
loaderInfo object has a COMPLETE event. Why not use it? (http://livedocs.adobe.com/flex/3/langref/flash/display/LoaderInfo.html)
Then you could skip the whole bytesLoaded/bytesTotal check.
Where I think the applicatation might be freezing is when the loaderInfo has cached resources and skips the "PROGRESS" step altogether. Then you would never get into the LoadXML code, and never, therefore, parse the xml.
You can install firebug in Firefox and check whether you're even attempting to load the XML file using the "net" tab. (or use a tool like filemon).