Why might browseForOpen fail to display File Dialog yet claim it is open if recalled? - actionscript-3

I am trying to open a file dialog with file.browseForOpen. Most of the time it works but on the very rare occasion (such as in meetings) the file browser simply does not appear and does not block (as a modal should).
If I press the button calling the code at this point then I get an error which states "there can only be one".
There are no sub-windows and I can't find to file dialog, even after minimizing the main window, yet the error insists that it is open. I wrote some code which disabled the button when the code above is called and then enables it on any of the events but when this error occurs the button is then permanently disabled.
There are another 10,000 lines of code, some which keep running even while the file browser is open. None of them seem related to the file browser so I moved the following code into a new project, to test, and could not replicate the bug.
var filter:FileFilter = new FileFilter("Image/Video", "*.jpg;*.png;*.mp4;");
var imagesFilter:FileFilter = new FileFilter("jpg/png", "*.jpg;*.png");
var docFilter:FileFilter = new FileFilter("mp4", "*.mp4;");
var filters:Array = [filter, imagesFilter, docFilter];
var fileBrowser:File = File.userDirectory;
fileBrowser.addEventListener(FileListEvent.SELECT_MULTIPLE, onFileSelected);
fileBrowser.addEventListener(Event.CANCEL, clean);
fileBrowser.addEventListener(IOErrorEvent.IO_ERROR, clean);
fileBrowser.browseForOpen("Select Slides", filters);
Does anyone know anything which could save me from a 'needle in a haystack' exhaustive search? Has anyone else ever experienced this same problem? I couldn't find any solutions when searching "File dialog opens but isn't visible" or more than 30 variations of that search including "File dialog doesn't open".
Lastly, is there a way to force the file dialog to close if I detect that the user is interacting with the main window whilst it should be blocked? Just as a bandage fix should the problem not be solved (breaks modal flow, I know, but modal flow is already broken at that point).
UPDATE:
After removing a class and replacing it with a less efficient urlMonitor the problem seems to have gone away.
If anyone can work out what went wrong then I will mark your answer as complete.
The class I removed seemed completely unrelated but I will show the code:
package reuse.Network
{
import flash.desktop.NativeApplication;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.IOErrorEvent;
import flash.events.StatusEvent;
import flash.events.TimerEvent;
import flash.net.URLLoader;
import flash.net.URLLoaderDataFormat;
import flash.net.URLRequest;
import flash.utils.Timer;
import air.net.URLMonitor;
[Event(name="networkStatusChanged", type="reuse.Network.CheckInternetEvent")]
public class NetStatusMonitor extends EventDispatcher
{
private var url:String;
private var urlMonitor:URLMonitor;
public function NetStatusMonitor(url:String = 'http://www.adobe.com')
{
super();
this.url = url;
}
protected function onNetwork_ChangeHandler(event:Event):void
{
checkWebsite(url, dispatchStatus);
}
/**
* Checks a specific website for connectivity.
* #param uri URI of the website to check for a response from
* #param result Function which accepts a bool as a response.
* #param idleTimeout How many milliseconds to wait before timing out
*/
public function checkWebsite(uri:String, result:Function, idleTimeout:Number = NaN):void
{
var timeout:Timer;
var request:URLRequest = new URLRequest(uri);
if(!isNaN(idleTimeout))
{
request.idleTimeout = idleTimeout;
timeout = new Timer(request.idleTimeout + 1000, 1);
timeout.addEventListener(TimerEvent.TIMER_COMPLETE, failed);
timeout.start();
}
var loader:URLLoader = new URLLoader();
loader.dataFormat = URLLoaderDataFormat.TEXT;
loader.addEventListener(Event.COMPLETE, complete);
loader.addEventListener(IOErrorEvent.IO_ERROR, failed);
loader.load(request);
function complete():void
{
result(true);
cleanup();
}
function failed(e:*):void
{
result(false);
cleanup();
}
function cleanup():void
{
if(timeout)
{
timeout.stop();
timeout.removeEventListener(TimerEvent.TIMER_COMPLETE, failed);
timeout = null;
}
loader.close();
loader.removeEventListener(Event.COMPLETE, complete);
loader.removeEventListener(IOErrorEvent.IO_ERROR, failed);
loader = null;
}
}
public function start():void
{
checkWebsite(url, dispatchStatus, 5000);
if(!NativeApplication.nativeApplication.hasEventListener(Event.NETWORK_CHANGE))
NativeApplication.nativeApplication.addEventListener(Event.NETWORK_CHANGE, onNetwork_ChangeHandler);
if(urlMonitor == null)
{
var request:URLRequest = new URLRequest(url);
urlMonitor = new URLMonitor(request);
urlMonitor.pollInterval = 30;
}
if(!urlMonitor.hasEventListener(StatusEvent.STATUS))
urlMonitor.addEventListener(StatusEvent.STATUS, onNetStatus_ChangeHandler);
if(!urlMonitor.running)
urlMonitor.start();
}
public function stop():void
{
if(urlMonitor)
{
if(urlMonitor.running)
urlMonitor.stop();
if(urlMonitor.hasEventListener(StatusEvent.STATUS))
urlMonitor.removeEventListener(StatusEvent.STATUS, onNetStatus_ChangeHandler);
urlMonitor = null;
}
}
private function onNetStatus_ChangeHandler(event:StatusEvent):void
{
dispatchStatus(urlMonitor.available);
}
private function dispatchStatus(status:Boolean):void
{
dispatchEvent(new CheckInternetEvent(CheckInternetEvent.NETWORK_STATUS_CHANGED, status));
}
}
}
Anyone familiar with Raja Jaganathan might recognize this class from Adobe Air - Check for internet connection

I posted this as a bug to Adobe and the following note was added to it:
Alex Rekish
11:06:11 PM GMT+00:00 Apr 12, 2016
I have seen this problem and found workaround. You need remove
listeners, force cancel and null pervious file object that you you for
browseForOpen method.
previousBrowseFile.removeEventListener(Event.SELECT,
fileSelected); previousBrowseFile.removeEventListener(Event.CANCEL,
fileCancelled); previousBrowseFile.cancel(); previousBrowseFile= null;

Related

AS3: Reusing URLLoader, URLRequest, and URLVariables instances

My Flash project uses URLLoader.load a lot to load content from a web server and post to a php page. Should I reuse my URLLoader, URLRequest, and URLVariables instances, or should I create new ones each time? If I should create new ones each time, do the old ones need to be disposed of somehow?
You should most certainly never ever ever reuse any instances related to external operations and you should thoroughly dispose of them the very moment you don't need them. The overhead of Garbage Collector (GC) working on these objects is literally nothing next to the nightmare mess you might get into once your external operations collide via sharing the same operational instances.
URLVariables and URLRequest do not need any special treatment, just set null to any variables referencing them and ensure that method, where they were assigned to local variables, do not produce any function closures. Well, set URLRequest.data to null to break this reference.
URLLoader, on the other hand, needs to be pushed around a bit:
If URLLoader.data is a ByteArray, then you should ByteArray.clear() it (unless you need it).
Set the URLLoader.data to null.
Initially subscribe all error handlers with weak references (fifth argument of addEventListener set to true) and don't unsubscribe them. Weak keys won't affect the GCs judgement while keeping the subscriptions might save you from occasional Unhandled Error Event case.
Certainly do unsubscribe all non-error handlers.
In all the handlers, first check if Event.target is a valid URLLoader instance to avoid handling an event from a dead/disposed URLLoader.
Call URLLoader.close() just in case. Yes, after all of above is done.
Below is the class I use to load things in a simple way. It is built on the same principles I listed above. It allows loading text/binary data and also provides some proof against unstable network: you can set the repeatCount argument to higher values to provide fail-safe loading if you know that requests tend to fail sometimes.
Usage:
// Load binary data over unstable network.
DataFiles.load("data.dat", onData, true, 10);
// Load XML file as text over a stable network or from the local storage.
DataFiles.load("setup.xml", onSetup);
function onData(source:ByteArray):void
{
if (!source)
{
// Loading failed. Error case.
}
else
{
// File is loaded normally.
}
}
function onSetup(source:String):void
{
try
{
var aSetup:XML = new XML(source);
// Process loaded XML normally.
}
catch (fail:Error)
{
// The source is either null or an invalid XML string.
// Loading is failed, basically. Error case.
}
}
Implementation:
package simplify
{
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.net.URLLoaderDataFormat;
public class DataFiles
{
static private var list:Vector.<DataFiles> = new Vector.<DataFiles>;
static public function load(url:String, handler:Function, binary:Boolean = false, repeatCount:int = 1):void
{
var aLoader:DataFiles = new DataFiles;
aLoader.url = url;
aLoader.binary = binary;
aLoader.handler = handler;
aLoader.repeatCount = repeatCount;
list.push(aLoader);
aLoader.start();
}
private var url:String;
private var binary:Boolean;
private var handler:Function;
private var loader:URLLoader;
private var repeatCount:int;
private function start():void
{
loader = new URLLoader;
if (binary) loader.dataFormat = URLLoaderDataFormat.BINARY;
loader.addEventListener(Event.COMPLETE, onComplete);
loader.addEventListener(IOErrorEvent.IO_ERROR, onError, false, 0, true);
loader.load(new URLRequest(url));
}
private function destroyLoader():void
{
if (!loader) return;
loader.removeEventListener(Event.COMPLETE, onComplete);
var aDead:Loader = loader;
loader = null;
aDead.data = null;
aDead.close();
}
private function onComplete(e:Event):void
{
if (e.target != loader) return;
var aResult:* = loader.data;
var aHandler:Function = handler;
destroy();
destroyLoader();
aHandler(aResult);
}
private function onError(e:IOErrorEvent):void
{
if (e.target != loader) return;
destroyLoader();
repeatCount--;
if (repeatCount >= 0)
{
start();
}
else
{
var aHandler:Function = handler;
destroy();
aHandler(null);
}
}
private function destroy():void
{
var anIndex:int = list.indexOf(this);
if (anIndex > -1) list.splice(anIndex, 1);
handler = null;
url = null;
}
}
}

ActionScript 3.0 sound not working

So having trouble making sound on keyboard press
I have the imports:
import flash.net.URLRequest;
import flash.media.Sound;
I have the variables
private var soundDownRequest:URLRequest = new URLRequest ("SoundDown.mp3");
private var downSound:Sound = new Sound (soundDownRequest);
and the event listener
private function keyDownHandler(evt:KeyboardEvent):void
{
if (evt.keyCode == 40)//ascii for down arrow
{
downSound.play();
}
}
The sound folder is in the same folder as the .as, its also in the library of the fla, yet it still doesn't work. Any idea why?
Thank you.
Update:
I got the sound to work but not using the external method I was trying to do above.
Had to do it internally.
so you need:
import flash.media.SoundChannel;
-Then you need to make sure your sound file is in your fla library.
once its in the library
-Right click > properties
-Select the Action Script Tab
-Check "export for action script"
-Give the class a name in accordance to the sound
-press ok
add this variable (your will be different):
private var downSound:TheDownSound = new TheDownSound();
downsound is the selected name of the variable, and TheDownSound is the name of the class (the one made earlier for the sound file)
then add this to where you want the sound to play:
var myDownSound:SoundChannel = downSound.play();
Do this if you cant get it working externally like me.
for a better explanation watch this guys youtube video:
https://www.youtube.com/watch?v=SZpwppe7yGs
Your code is working perfectly ok if you put your .mp3 file in the same folder as the output .swf, not near the class .as source file (because its the swf file loading the sound, so the path must be relative to it)
public class ASEntryPoint extends Sprite {
private var soundDownRequest:URLRequest = new URLRequest ("click.mp3");
private var downSound:Sound = new Sound (soundDownRequest);
public function ASEntryPoint() {
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
}
private function keyDownHandler(evt:KeyboardEvent):void{
if (evt.keyCode == 40) {
downSound.play();
}
}
}
You need to load the external file, which is asynchronous operation. Then you track the loading event and if it all goes normally you can play your loaded sound.
import flash.events.SecurityErrorEvent;
import flash.events.IOErrorEvent;
import flash.events.Event;
import flash.net.URLRequest;
import flash.media.Sound;
import flash.media.SoundChannel;
// Keep the sound loader from being garbage collected.
var soundLoader:Sound;
function loadSound(url:String):void
{
var aRequest:URLRequest = new URLRequest(url);
soundLoader = new Sound();
// Handle the normal loading.
soundLoader.addEventListener(Event.COMPLETE, onLoaded);
// Handle the error cases.
soundLoader.addEventListener(IOErrorEvent.IO_ERROR, onError, false, 0, true);
soundLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onError, false, 0, true);
soundLoader.load(aRequest);
}
var audioChannel:SoundChannel;
function onLoaded(e:Event):void
{
// Sound is available here for playback.
audioChannel = soundLoader.play();
}
function onError(e:Event):void
{
trace(e);
}
You can also handle your sound as a streaming audio, but I worked with that years ago in AS2 so I cannot help here. Still, internet suggests a link: http://help.adobe.com/en_US/ActionScript/3.0_ProgrammingAS3/WS5b3ccc516d4fbf351e63e3d118a9b90204-7d22.html

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, "");
}
//────────────────────────────────────────────
}
}

Debugging a release only flash issue

I've got an Adobe Flash 10 program that freezes in certain cases, however only when running under a release version of the flash player. With the debug version, the application works fine.
What are the best approaches to debugging such issues? I considered installing the release player on my computer and trying to set some kind of non-graphical method of output up (I guess there's some way to write a log file or similar?), however I see no way to have both the release and debug versions installed anyway :( .
EDIT: Ok I managed to replace my version of flash player with the release version, and no freeze...so what I know so far is:
Flash: Debug Release
Vista 32: works works
XP PRO 32: works* freeze
I gave them the debug players I had to test this
Hmm, seeming less and less like an error in my code and more like a bug in the player (10.0.45.2 in all cases)... At the very least id like to see the callstack at the point it freezes. Is there some way to do that without requiring them to install various bits and pieces, e.g. by letting flash write out a log.txt or something with a "trace" like function I can insert in the code in question?
EDIT2: I just gave the swf to another person with XP 32bit, same results :(
EDIT3:
Ok, through extensive use of flash.external.ExternalInterface.call("alert", "..."); I managed to find the exact line causing the problem (I also improved exception handling code so rather than freeze it told me there was an "unhandled" exception). The problem now is what on earth is flashes problem with this with the release player on some machines...
particles.push(p);
Which causes a TypeError #1034 on said platforms. Particles is a Vector.<Particle>, p is a Particle. I tested with getQualifiedClassName and got:
getQualifiedClassName(p) = ::Particle
getQualifiedClassName(particles) = __AS3__.vec::Vector.<::Particle>
Any ideas why this is a problem and what to do to make it work?
EDIT4:
Ok I seem to have solved this. The Particle class is just a simple internal class located after the package {...} in the action script file using it. I moved this into its own file (particle.as) and made it a proper public class in my package, and problem solved.
Maybe its a flash bug or maybe I missed the memo about not using internal classes in vectors or something, although if that's the case I would have expected something or other (either at compile time or with debug runtimes) to disallow it explicitly, e.g. some error on the "private var particles:Vector.<Particle>;" line. If I get a chance I guess I'll take a look at contacting the Adobe flash team concerning this or something.
Thanks for help giving debugging tips which I guess is more along the original questions lines :)
This is a long shot, but are the Particles the objects that you are clicking? If so then catching the event in the wrong phase of bubbling, and pushing event.target (assuming it to be a Particle) could cause that problem.
Whatever the problem, I have something that should help you debug. A class that creates a pseudo trace window in your SWF, much nicer than extinterfacing to javascript. I've forgotten who wrote it, but I feel like it's Senocular. I use it any time I need to get traces back from end users.
Just drop it in the default package for your project, call stage.addChild(new Output());, and then to trace call Output.trace("A message");
package {
import flash.display.Shape;
import flash.display.Sprite;
import flash.display.Stage;
import flash.display.GradientType;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Matrix;
import flash.text.TextField;
import flash.text.TextFieldType;
import flash.text.TextFormat;
import flash.text.TextFormatAlign;
import flash.text.TextFieldAutoSize;
/**
* Creates a pseudo Output panel in a publish
* swf for displaying trace statements.
* For the output panel to capture trace
* statements, you must use Output.trace()
* and add an instance to the stage:
* stage.addChild(new Output());
*
*/
public class Output extends Sprite {
private var output_txt:TextField;
private var titleBar:Sprite;
private static var instance:Output;
private static var autoExpand:Boolean = false;
private static var maxLength:int = 1000;
public function Output(outputHeight:uint = 400){
if (instance && instance.parent){
instance.parent.removeChild(this);
}
instance = this;
addChild(newOutputField(outputHeight));
addChild(newTitleBar());
addEventListener(Event.ADDED, added);
addEventListener(Event.REMOVED, removed);
}
// public methods
public static function trace(str:*):void {
if (!instance) return;
instance.output_txt.appendText(str+"\n");
if (instance.output_txt.length > maxLength) {
instance.output_txt.text = instance.output_txt.text.slice(-maxLength);
}
instance.output_txt.scrollV = instance.output_txt.maxScrollV;
if (autoExpand && !instance.output_txt.visible) instance.toggleCollapse();
}
public static function clear():void {
if (!instance) return;
instance.output_txt.text = "";
}
private function newOutputField(outputHeight:uint):TextField {
output_txt = new TextField();
//output_txt.type = TextFieldType.INPUT;
output_txt.border = true;
output_txt.borderColor = 0;
output_txt.background = true;
output_txt.backgroundColor = 0xFFFFFF;
output_txt.height = outputHeight;
var format:TextFormat = output_txt.getTextFormat();
format.font = "_sans";
output_txt.setTextFormat(format);
output_txt.defaultTextFormat = format;
return output_txt;
}
private function newTitleBar():Sprite {
var barGraphics:Shape = new Shape();
barGraphics.name = "bar";
var colors:Array = new Array(0xE0E0F0, 0xB0C0D0, 0xE0E0F0);
var alphas:Array = new Array(1, 1, 1);
var ratios:Array = new Array(0, 50, 255);
var gradientMatrix:Matrix = new Matrix();
gradientMatrix.createGradientBox(18, 18, Math.PI/2, 0, 0);
barGraphics.graphics.lineStyle(0);
barGraphics.graphics.beginGradientFill(GradientType.LINEAR, colors, alphas, ratios, gradientMatrix);
barGraphics.graphics.drawRect(0, 0, 18, 18);
var barLabel:TextField = new TextField();
barLabel.autoSize = TextFieldAutoSize.LEFT;
barLabel.selectable = false;
barLabel.text = "Output";
var format:TextFormat = barLabel.getTextFormat();
format.font = "_sans";
barLabel.setTextFormat(format);
titleBar = new Sprite();
titleBar.addChild(barGraphics);
titleBar.addChild(barLabel);
return titleBar;
}
// Event handlers
private function added(evt:Event):void {
stage.addEventListener(Event.RESIZE, fitToStage);
titleBar.addEventListener(MouseEvent.CLICK, toggleCollapse);
fitToStage();
toggleCollapse();
}
private function removed(evt:Event):void {
stage.removeEventListener(Event.RESIZE, fitToStage);
titleBar.removeEventListener(MouseEvent.CLICK, toggleCollapse);
}
private function toggleCollapse(evt:Event = null):void {
if (!instance) return;
output_txt.visible = !output_txt.visible;
fitToStage(evt);
}
private function fitToStage(evt:Event = null):void {
if (!stage) return;
output_txt.width = stage.stageWidth;
output_txt.y = stage.stageHeight - output_txt.height;
titleBar.y = (output_txt.visible) ? output_txt.y - titleBar.height : stage.stageHeight - titleBar.height;
titleBar.getChildByName("bar").width = stage.stageWidth;
}
}
}
Judging by when the freeze occurs, try to pinpoint some possibilities for what the offending code may be, and use De MonsterDebugger to check variables etc.
EDIT:
I'm pretty certain that the actual call stack is only available to you in the debug versions of the Flash Player / AIR. Still, it may be useful in the debug player to trace the stack from within the handler for the button to see if anything is out of place:
var err:Error = new Error(“An Error”);
trace(err.getStackTrace());
FYI the getStackTrace method is only available in the debug player, so there is no way to write it to a log.txt in production.

Loading and Returning Text Data with ActionScript 3 (URLLoader)

I'm trying to do something exceedingly simple: write a function that reads text from a text file and returns the text in a string using AS3.
The Function
public function readData(path:String):String
{
var dataSet:String;
var urlRequest:URLRequest = new URLRequest(path);
var urlLoader:URLLoader = new URLLoader();
urlLoader.dataFormat = URLLoaderDataFormat.TEXT;
urlLoader.addEventListener(Event.COMPLETE, urlLoader_complete);
urlLoader.load(urlRequest);
function urlLoader_complete(evt:Event):void {
dataSet = urlLoader.data;
trace(dataSet)
}
trace(dataSet);
return dataSet;
}
Calling the Function
var dataString:String = aq.readData("http://example.com/data.txt");
trace(dataString);
This code returns a null string when I run it. Why?
EDIT:
Ok, I now see that this doesn't work because urlLoader is acting asynchronously. I'm writing a program that reads in a data file and acts on it. Does this mean that I need to write the rest of my program inside function urlLoader_complete? Or should I pause the program until urlLoader is finished?
In Flash and Flex, all network I/O is asynchronous. It has to be this way in order to avoid blocking your browser.
As a result, it is not possible to write a readData() function that directly returns the result of a network read operation. You will have to pass a callback function to the readData() function. When readData() has finished reading the data, it can call the callback function.
For example:
/**
* Asynchronous function to read data as a string. When the data has been read,
* the callback function is called with the result.
*
* #param path the URL to read
* #param callback the function that is called with the result; should take
* one string argument.
*/
public function readData(path:String, callback:Function):void
{
var dataSet:String;
var urlRequest:URLRequest = new URLRequest(path);
var urlLoader:URLLoader = new URLLoader();
urlLoader.dataFormat = URLLoaderDataFormat.TEXT;
urlLoader.addEventListener(Event.COMPLETE, urlLoader_complete);
urlLoader.load(urlRequest);
function urlLoader_complete(evt:Event):void {
dataSet = urlLoader.data;
trace(dataSet);
callback(dataSet);
}
}
Here is how you might call that function from Flex:
<mx:Label id="mylabel" />
<mx:Button click="readData('http://www.google.com/',
function(s:String):void {mylabel.text = s})" />
Its been 3 years ago since this question arose with you, but since I stumbled on this problem a few hours ago, and managed to get it to work and thought why not share it. There might be better alternatives already, but hey I just started coding Actionscript so no blames :)
First build a Preloader class with a filecounter. There will be a numFiles parameter in the constructor which holds the total number of files to be loaded. Every time when the complete method is called, 1 to the filecounter will be added and a statement will be checking if all files are loaded. when the numFiles is equal to the counter call the start() method of the calling class.
*Preloader.as *
package
{
import flash.display.Loader;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.net.URLLoader;
import flash.net.URLRequest;
public class Preloader
{
public var urlLoader:URLLoader;
public var response:Array = new Array();
public var callingClass:Object;
public var numFiles:uint;
private var counter:uint;
public function Preloader(callingClass:Object, numfiles:uint)
{
this.callingClass = callingClass;
this.numFiles = numFiles;
}
public function load(name:String):void
{
var request:URLRequest = new URLRequest(name);
urlLoader = new URLLoader();
urlLoader.addEventListener(Event.COMPLETE, onLoad);
urlLoader.load(request);
}
public function onLoad(event:Event):void
{
response[counter] = event.currentTarget.data;
if(numFiles == counter) {
callingClass.start();
} else {
counter++;
}
}
}
}
The constructor method in the calling class will have to call all the preload files and the start method will be the replacement of your constructor stuff. note that when the preloader loads it need the reference to its calling class and the total number of "to be loaded" files:
package
{
import flash.display.MovieClip;
import misc.Preloader;
public class Path extends MovieClip
{
public var preloader:Preloader = new Preloader(this, 3); //pass this class and the total number of files
public function Controller()
{
preloader.loadJSON('file1.js');
preloader.loadJSON('file2.js');
preloader.loadJSON('file3.js');
}
public function start():void
{
trace(preloader.response[0]); //Get first file contents
}
}
}