views:

199

answers:

1

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);
     }
A: 

After taking a quick look at this, I can see what might be happening.

  1. You listen for ADDED_TO_STAGE.
  2. You handle ADDED_TO_STAGE and then start listening for PROGRESS.
  3. 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).

Glenn