I have a Flash Builder 4 project that's hooked up to a Flash Professional CS5 FLA.
I do NOT use MXML, and all code is handled directly in Flash Builder. (Flash itself is used simply for the library, and its easier for our artists to use)
Everything's been going along without a hitch, everything runs off of dynamically generated XML from the site the SWF is embedded to. But up until now I've had the XML path hardcoded in the actionscript. I wish simply to not make it so.
I have followed minimum 45 tutorials on getting FlashVars into FB4/As3, and quite simply nothing seems to be working.
Old school < embed > method, using < object > method, and even using swfObject method, simply I cannot seem to access these flashvar properties.
here's the html that i currently have now:
<script>
var flashvars = {
xml: "/mapsystem/xml"
}; // yes that is definitely the correct path, its the same value as when it was hardcoded
$(function() {
swfobject.embedSWF("/flash/map.swf", "map", "960", "885", "10.0.0", "expressInstall.swf", flashvars);
});
</script>
<div id="map">
swfObject Aint Working
</div>
Heres the actionscript (this is in my Document class, first thing)
package
{
import flash.display.LoaderInfo;
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.Event;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import src.GlobalStage;
import src.Map;
import src.Styles;
public class map extends GlobalStage
{
public var xmlDoc = "map.xml";
public function map()
{
var test:TextField = new TextField();
test.x = 50;
test.y = 50;
test.autoSize = TextFieldAutoSize.LEFT;
test.text = "XML Doc: ";
this.addChild(test);
var test2:TextField = new TextField();
test2.x = 50;
test2.y = 80;
test2.multiline = true;
test2.border = true;
test2.autoSize = TextFieldAutoSize.LEFT;
test2.text = "Parameters: \n";
test2.appendText("Total Parameters: ");
this.addChild(test2);
var _params:Object;
if ( this.loaderInfo.parameters.length != null ) {
_params = this.loaderInfo.parameters;
} else {
// run alt code to init
}
for(var pItem:String in _params) {
test2.appendText("Name: " + pItem + " :: " + _params[pItem] + "\n" );
}
if(_params['xml'] != null) xmlDoc = _params['xml'];
test.appendText(xmlDoc);
var map:Map = new Map(xmlDoc);
Now, when i run this on my local test, nothing shows up as per expected, but when it comes to being on the site itself, with a passed flashvar, the xmlDoc remains "map.xml", my counter tells me there are 0 parameters, and of course nothing shows up in my list of parameters.
I have spent 8 hours trying to get this to work, quite frankly I'm losing hair and sleep over this.
loaderInfo.parameters is an Object, and so the condition in this if statement is never likely to be true (unless your flashVars had a param named 'length'):
if (this.loaderInfo.parameters.length != null) {
So instead of checking if the length is not null, just check if the parameters are not null:
if (loaderInfo.parameters) {
loaderInfo.parameters is an object, and it is never null. What you must do is check for your flashvar's existence like this:
if (loaderInfo.parameters.xml)
{
var xmlPath:String = loaderInfo.parameters.xml
// start using xml
}
else
// run alt code to init
}
Related
I have a MovieClip in Library , which I am loading dynamically through addChild method.
The problem I am facing is :--
I have a Main Class which runs with several other classes and several FLA's.
Main Class calls a sub class function which in return calls the code in a frame of a FLA which loads this object from Library.
This object is not present in all FLA's, thats where I am getting stuck, getting Compile time error.
Tried checking through this but failed :(
var classExist:Boolean = isClassExists("CTRL_ALARM");
function isClassExists(className:String, domain:ApplicationDomain = null):Boolean
{
var res:Boolean;
if(domain)
{
res = domain.hasDefinition(className);
}
else
{
// res = getDefinitionByName(className);
//or the same
res = ApplicationDomain.currentDomain.hasDefinition(className);
}
trace(res);
return res;
}
Is there any way I can duplicate objects on Stage in as3, or how can I restrict an object from being compiled if it is not present in Library?
Try the following. If all of your SWFs are in the same sandbox, it might just work:
import flash.utils.getDefinitionByName;
var AlarmClass:Class = getDefinitionByName("CTRL_ALARM");
var anAlarm:DisplayObject = new AlarmClass;
Then, to make it work even with sandbox restrictions, you may seek for the definition you want through the loaded SWFs:
// This should contain Loader objects with your loaded SWFs.
var aList:Array;
for each (aLoader:Loader in aList)
{
// Get reference to loaded app domain.
var aDomain:ApplicationDomain = aLoader.contentLoaderInfo.applicationDomain;
// Check if such a class is in that SWF.
if (aDomain.hasDefinition("CTRL_ALARM"))
{
var AlarmClass:Class = aDomain.getDefinition("CTRL_ALARM");
var anAlarm:DisplayObject = new AlarmClass;
break;
}
}
I'm using the following function to add some images from the library to the stage.
function AddImage(image_name:String):void {
if(image_count == 4) return;
// change the following line so it uses "image_name"
var defaultImage:added_1 = new added_1(100, 100);
var tmpImage:Bitmap = new Bitmap(defaultImage);
tmpImage.x = 124.5 + (108.5 * image_count);
tmpImage.y = 1511.9;
addChild(tmpImage);
image_count++;
}
What I'd like to be able to do is pass the image name as a string parameter to the function but can't seem to figure out how to do this.
Can someone help me out?
What you want to do is get the Class Definition via using getDefinitionByName so that you can create an instance, the following code is how you do that :
// you'll need to add this import to use getDefinitionByName
import flash.utils.getDefinitionByName;
function AddImage(image_name:String):void {
if(image_count == 4) return;
// this next line gets the class definition of the image_name
var imageClass:Class = getDefinitionByName(image_name) as Class;
// this is how you create an instance of that class
var defaultImage:BitmapData = new imageClass(100, 100);
var tmpImage:Bitmap = new Bitmap(defaultImage);
tmpImage.x = 124.5 + (108.5 * image_count);
tmpImage.y = 1511.9;
addChild(tmpImage);
image_count++;
}
The changes are the import :
import flash.utils.getDefinitionByName;
and these two lines :
var imageClass:Class = getDefinitionByName(image_name) as Class;
var defaultImage:BitmapData = new imageClass(100, 100);
Note ---
Also wanted to mention that in certain cases you might run into an issue if you are compiling with Flex as opposed to the Flash IDE, where you get the following error :
ReferenceError: Error #1065: Variable <YourImageClassName> is not defined.
The way to handle that situations is by declaring a variable in your class variable declarations for the compiler, so it recognizes that symbol.
So if your two images class names were image_1 and image_2, in your class declarations you would do something like :
private var forCompiler1:image_1;
private var forCompiler2:image_2;
If you have a ton of images, that might be a pain, but that's the only way I've found to get the compiler to recognize them. :/ haha
I've completely run out of ideas on this. It follows, and is part of my previous question:
embedding a font in a swf using as3
I just don't seem to be able to get the flash.text.engine to use my embedded font. NB the font has to be loaded into the application (as embedded in swf) after the user has chosen the two languages (for translation to and from). There seems to be a little info implying that it is now necessary to use the fontswf application which is in the sdk. I have tried this and produced loadable swf files but I can't find any info on how these are then loaded (i.e. the getDefinition and registerFont bits below don't work as there are no classes in these swf) and applied to text.engine objects. The source for the embedding is in my answer to my question above. This is a test as3 which demonstrates how it doesn't work!
package
{
import flash.display.Loader;
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.Event;
import flash.text.engine.ElementFormat;
import flash.text.engine.FontDescription;
import flash.text.engine.TextBlock;
import flash.text.engine.TextLine;
import flash.text.engine.TextElement;
import flash.net.URLRequest;
import flash.text.Font;
public class Main extends Sprite
{
private var loader:Loader;
private var tl:TextLine;
public function Main():void
{
loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE,fontLoaded);
loader.load(new URLRequest("EnglishF.swf"));
}
private function fontLoaded(evt:Event):void {
var FontClass:Class
FontClass = evt.target.applicationDomain.getDefinition("EnglishF") as Class;
try {
Font.registerFont(FontClass.myFont);
trace("successfully loaded " + FontClass);
// gives 'successfully loaded EnglishF'
} catch (err:Error) {}
var fontList:Array = Font.enumerateFonts();
for (var i:int = 0; i < fontList.length; i++) {
trace(fontList[i].fontName, fontList[i].fontType);
// gives 'EnglishF embeddedCFF'
}
var block:TextBlock = new TextBlock();
var font:FontDescription = new FontDescription("EnglishF");
var formt:ElementFormat = new ElementFormat(font, 30);
trace(FontDescription.isFontCompatible("EnglishF","normal","normal"), formt.fontDescription.fontName);
// gives 'true EnglishF'
formt.color = 0x882233;
var span:TextElement = new TextElement("Hello World. This is certainly NOT in the Font provided!", formt);
block.content = span;
tl = block.createTextLine();
tl.x = 10;
tl.y = tl.ascent + 10;
addChild(tl);
}
}
}
Am I doing anything wrong, or is this impossible?
Hopefully this will help. Under this line:
var font:FontDescription = new FontDescription("EnglishF");
add the following line:
font.fontLookup = FontLookup.EMBEDDED_CFF;
This will let the text framework know that you're using a CFF font (used in the new text framework), instead of a regular embedded font (used in TextFields).
Hope this helps.
Jordan
We are making a system that has a main swf for the application, and loads separate tools from separate swfs -- there will be versioning issues in the future since the separate swfs are coming from a cms (especially now since we're still developing, but also in the future when other developers might create an incompatible tool). I'm trying hard to prevent them as much as possible but I'd really like to be able to display a message to the user of the system when an incompatible swf is loaded.
This would mean that we need to catch that VerifyError or at least determine the loading failed for some reason - I've got no idea how to handle that at the moment. I suspect it might be possible using 10.1 and the uncaughtError system, but we are currently targeting flash player 10. Does anyone have a good idea? (we are already handling IOErrorEvent.IO_ERROR)
UPDATE: I've built a solution that scans the bytecode before importing, looks like that will work. I'll post the solution later.
The best way to do this is by using one of the libraries bhups suggested. I used senocular's for the next example.
Also, because the senocular's library provides only basic operations for the parsed SWF you may need the SWF Format Spec (adobe.com/devnet/swf/pdf/swf_file_format_spec_v10.pdf) to get the info you want out of the loaded SWF.
The next example lists all the class names from a loaded SWF:
package swf
{
import flash.events.Event;
import flash.net.URLRequest;
import flash.net.URLStream;
import flash.utils.ByteArray;
import flash.utils.Endian;
import swf.SWFReader;
public class GetSWFInfo
{
private var swfInfo:SWFReader;
public function GetSWFInfo()
{
var urlRequest:URLRequest = new URLRequest("theswf.swf");
var loader:URLStream = new URLStream();
loader.load(urlRequest);
loader.addEventListener(Event.COMPLETE, onComplete);
}
public function onComplete(e:Event):void {
var recivedByteArray :ByteArray = new ByteArray();
URLStream(e.currentTarget).readBytes(recivedByteArray);
//create a new instance of SWFReader
swfInfo = new SWFReader();
//readTag it's a callback function that will be called when a tag is read during the SWF parse process.
//read more on tags in the SWF specification document
swfInfo.tagCallback = readTag;
//start parsing
swfInfo.parse(recivedByteArray);
}
public function readTag(tag:uint, bytes:ByteArray):void {
//76 it's the tag type for SymbolClass tag
//read more in the SWF specification document
if (76 == tag) {
var classesArray:Array = new Array();
var symbolsNumber:uint = 0;
var currentId:uint = 0;
bytes.endian = Endian.LITTLE_ENDIAN;
//read the symbols Number
//again read more in the SWF specification document
symbolsNumber = bytes.readShort();
bytes.position = 4;
while (true) {
var i:uint = bytes.position;
//every string name ends with a null byte
//again read more in the SWF specification document
while(bytes[i] != 0) i++;
var readAmount:uint = i - bytes.position;
classesArray.push(bytes.readUTFBytes(readAmount));
//the last ID is always the base class Id, and it's 0
currentId=bytes.readUnsignedShort();
bytes.position++;
if (currentId==0) {
break;
}
}
//this two should be equal
trace(classesArray.length + 1);//the number of elements in the classesArray
trace(symbolsNumber);//the number of classes retrived from the SWF
//list the names
var name:String;
for each (name in classesArray) {
trace(name);
}
//now you have an array with all the class names that you can use to compare
}
}
}
}
I did misunderstand what you are trying to do.
Well, actually, I guess there is no handler for verify error and to detect it, you have to fight with byte-codes.
By the way, I have and idea which is not the very answer for your question but may helps you.
a 3rd party swf is depending on a class that should be in my swf -- if that class is missing I get the VerifyError.
From this point, I can advice that if you link the 'missing class' into your swf and load the 3rd party swf into ApplicationDomain.currentDomain or new ApplicationDomain(ApplicationDomain.currentDomain), you can avoid the 'Verify Error'.
(This is because the flash player will find the diffinition of the missing class in the parent swf.)
Here is my sample code which loads a swf with verify error(http://teionclub.com/test/xml/main.swf).
Avoiding VerifyError - wonderfl build flash online
I think there is a way to workaround this issue.
load the swf using a URLLoader or
URLStream into a ByteArray.
Use any open source library for parsing SWF binary like this or
this.
check if it verifies that the whole byte array represents valid
SWF file.
If above test succeeds then load this ByteArray into loader using
loadBytes method.
Else show user that this is not working.
Disclaimer: A binary file can be a valid SWF still might not be render-able, but with this you can discard all the invalid SWFs or any other formats whose extension are changed to swf.
I've worked with that kind of application in the past but I think it would be better to fix the SWF loaded rather than handling VerifyError. VeriyError indicates that the SWF loaded is corrupted or malformed.
And it's natural that the SWF itself is malformed rather than that the SWF is corrupted during the transfer. I guess you are trying to load png or other format named ".swf" or the SWF is generated by some software other than Flex compiler or Flash such as swfmill(In the latter case, there would be a bug in that software).
To finally answer my own question, this is the utility class I've been using to detect possible errors. I load the SWF as a bytearray and scan the contents before loading it as an actual MovieClip.
As you can see my code heavily depends on the com.segfaultlabs.swfutils package
Important: I've stopped using this method of preventing errors, opting for the more manual approach of checking the files by actually trying to load them and see if they work. This is because the utility is not complete, and my current knowledge of the ABC format is not good enough to make sure I can develop a check that will always be correct.
Posting my code here as starting point for others who want to take a stab at it :-)
package nl.ijsfontein.utils
{
import com.segfaultlabs.swfutils.ABC.ABCCPool;
import com.segfaultlabs.swfutils.ABC.ABCClass;
import com.segfaultlabs.swfutils.ABC.ABCInstance;
import com.segfaultlabs.swfutils.ABC.ABCMethodInfo;
import com.segfaultlabs.swfutils.ABC.ABCMultiname;
import com.segfaultlabs.swfutils.ABC.ABCParser;
import com.segfaultlabs.swfutils.ABC.ABCTraitConstSlot;
import com.segfaultlabs.swfutils.ABC.ABCTraitsInfo;
import com.segfaultlabs.swfutils.ABC.ABCinfo;
import com.segfaultlabs.swfutils.SWFDataInput;
import com.segfaultlabs.swfutils.SWFFile;
import flash.system.ApplicationDomain;
import flash.utils.ByteArray;
/**
* utility to see which classes a swf uses, but doesn't contain itself
* - this can be used to detect possible VerifyErrors before they happen.
*/
public class SwfDependencyUtil
{
public function SwfDependencyUtil()
{
}
// return null if ok, or name of needed class if external depencendy
private static function resolveSuper(abc:ABCinfo, superClass:String):String
{
//if (superClass.indexOf("flash.") == 0 || superClass.indexOf("*") == 0 || superClass.indexOf("Object") == 0)
if (superClass.indexOf("*") == 0)
{
trace(' super: ' + superClass + " (ignore)");
}
else
{
var superClassClass:ABCClass = null;
for each ( var c:ABCClass in abc.classes )
{
if (c.name == superClass)
{
superClassClass = c;
}
}
if (superClassClass)
{
trace(' super: ' + superClass + " (resolved internally)");
return resolveSuper(abc, superClassClass.iref.base);
}
else
{
trace(' super: ' + superClass + " (NOTFOUND)");
return superClass;
}
}
return null;
}
/*
* checks: classes, superclasses, static variables, member variables
* TODO: function arguments
* won't check: method bodies
*
* TODO: refactor to multiple methods
*/
public static function getDependencies(swfBytes:ByteArray):Array /* of String */
{
var result:Array = [];
swfBytes.position = 0;
var swfr:SWFFile = new SWFFile(swfBytes);
var arr:Array;
if ( swfr.compressed )
{
swfr.dataInput = swfr.uncompress();
swfr.readHeader();
};
arr = swfr.parseTags();
if ( arr[82] != null )
{
var abc:ABCinfo = new ABCinfo();
var cpool:ABCCPool = new ABCCPool();
var abcparse:ABCParser = new ABCParser();
abcparse.readMethodBytes = true;
abcparse.readExceptions = false;
for ( var j:int = 0; j < arr[82].length; j += 1 )
{
swfr.dataInstance.position = arr[82][j].position;
try
{
abcparse.parse( swfr.dataInput as SWFDataInput, abc, cpool, new FakeLogger() );
for each ( var c:ABCClass in abc.classes )
{
trace('class:', c.name);
var superClass:String = c.iref.base;
var dependency:String = resolveSuper(abc, superClass);
if (dependency)
{
result.push(dependency);
}
for each (var mn:ABCMultiname in c.iref.interfaces)
{
var interfaceName:String = mn.nsset[0] != "" ? mn.nsset[0] + "::" + mn.name : mn.name;
var interfaceDependency:String = resolveSuper(abc, interfaceName);
if (interfaceDependency)
{
result.push(interfaceDependency);
}
}
for each (var ti:ABCTraitsInfo in c.traits)
{
if (ti is ABCTraitConstSlot)
{
var constName:String
if (QName(ABCTraitConstSlot(ti).type).uri)
{
constName = QName(ABCTraitConstSlot(ti).type).uri + "::" + QName(ABCTraitConstSlot(ti).type).localName
}
else
{
constName = QName(ABCTraitConstSlot(ti).type).localName
}
var constDependency:String = resolveSuper(abc, constName);
if (constDependency)
{
result.push(constDependency);
}
}
else if (ti is ABCMethodInfo)
{
trace('method', ABCMethodInfo(ti).name);
} else
{
trace(ti);
}
// trace(ti.type.localName);
}
// const (static?) members: c.traits
}
for each ( var i:ABCInstance in abc.instances )
{
// trace(i);
for each (var instanceTi:ABCTraitsInfo in i.traits)
{
if (instanceTi is ABCTraitConstSlot)
{
trace('instance:', createClassNameFromQname(ABCTraitConstSlot(instanceTi).type));
var csdep:String = resolveSuper(abc, createClassNameFromQname(ABCTraitConstSlot(instanceTi).type));
if (csdep)
{
result.push(csdep);
}
}
else if (instanceTi is ABCMethodInfo)
{
}
else
{
trace('unexpected trait type');
}
}
}
abc.dispose();
}
catch ( e:Error )
{
trace( " Error ",e.getStackTrace() );
};
};
cpool.dispose();
}
else
{
trace("No DoABC block... ;(");
}
return result;
}
private static function createClassNameFromQname(qn:QName):String
{
var result:String
if (qn.uri)
{
result = qn.uri + "::" + qn.localName
}
else
{
result = qn.localName
}
return result;
}
public static function getUnsatisfiedDependencies(swfBytes:ByteArray):Array /* of String */
{
var result:Array = [];
var dependencies:Array = SwfDependencyUtil.getDependencies(swfBytes)
for each (var dependency:String in dependencies)
{
if (ApplicationDomain.currentDomain.hasDefinition(dependency))
{
trace('ok: ', dependency);
}
else
{
trace('ERROR: unsatisfied dependency: ', dependency);
result.push(dependency);
}
}
return result;
}
}
}
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).