Passing an additional argument to the event.COMPLETE function

I add multiple tabs to the scene and each tab loads its own SWF file. I have an array keeping track of the tabs, but you need to know when each swf it belongs to is loaded. I'm not sure how to do this.

Tabs are managed by XML, so there can be any number of tabs -

for (var j = 0; j < _xmlTabs.length(); j++) {
    arrTabs[j] = new Tab(j,_xmlTabs[j].attribute("icon"),_xmlTabs[j]);
    addChildAt(arrTabs[j],0);

    mRequest = new URLRequest(_xmlTabs[j].attribute("swf"));  
    mLoader = new Loader();
    addChild(mLoader);
    mLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onTabComplete);
    mLoader.load(mRequest);
}

      

So let's say there are 5 tabs loaded and each one loads its own swf and "onTabComplete ()" is run 5 times. Even though each tab is created in order, onTabComplete may not start in order as the swfs will be of different sizes. So how do I bind each tab to the onTabComplete function? Each instance of a tab element has a "position" property that you can get.

+2


source to share


8 answers


Extend the Loader class with a custom class, add the new property you want and then you can refer to it like

e.currentTarget.loader.newproperty



in event handler

+3


source


A modified version of thehiatus answer , which I think should get around the value j, which is a common problem:

function buildHandleComplete(i:int):Function {
  return function(event:Event):void {
    onTabComplete(event, i);
  };
}

for (var j:int = 0; j < _xmlTabs.length(); j++) {
    arrTabs[j] = new Tab(j,_xmlTabs[j].attribute("icon"),_xmlTabs[j]);
    addChildAt(arrTabs[j],0);

    mRequest = new URLRequest(_xmlTabs[j].attribute("swf"));  
    mLoader = new Loader();
    addChild(mLoader);
    var handleComplete:Function = buildHandleComplete(j);
    mLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, handleComplete);
    mLoader.load(mRequest);
}

      



Using a function that takes the index value as an argument and creates a listener using what you end up with with each closure referencing a different variable instead of all referencing the j value.

+1


source


I'm not familiar with the Tab class, but does Tab extend DisplayObjectContainer? you could just do:

arrTabs[j].addChild(mLoader);  

      

and then in the call to the event handler:

e.currentTarget.parent.position

      

to get the indicator that the tab is loaded on and then process it, maybe maybe?

0


source


Why not identify them with their URLs?

private function onTabComplete(e:Event):void
{
  var loaderInfo:LoaderInfo = LoaderInfo(e.target);
  trace(loaderInfo.url);

  //btw, loaderInfo.content is the tab that you are looking for.

  var url:String = loaderInfo.url;
  var tabIndex:Number;
  for(var j:Number = 0; j < _xmlTabs.length(); j++)
  {
    if(url == String(_xmlTabs[j].attribute("swf")))
    {
      tabIndex = j;
      break;
    }
  }
  //tabIndex now contains the required "j"
}

      

EDIT: If the tabs are loading the same SWF (same urls).

Even if it works, you should consider redesigning.

private function onTabComplete(e:Event):void
{
  int total:Number = _xmlTabs.length();
  var loader:Loader = LoaderInfo(e.target).loader;
  var p:DisplayObjectContainer = loader.parent;
  if(p.numChildren != total * 2)
  {
    trace("other children present : this method won't work");
    return;
  }

  var ldrIndex:Number = p.getChildIndex(loader);
  var tabIndex:Number = ldrIndex - total;
  var matchingTab:Tab = arrTabs[tabIndex];
  //enjoy
}

      

0


source


AS3 also supports anonymous functions, so you can do something like this:

addChild(mLoader);
var handleComplete:Function = function(event:Event):void {
    onTabComplete(event, j);
};
mLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, handleComplete);
mLoader.load(mRequest);

      

0


source


in my experience you would like to customize the download queue. loading them one at a time will prevent multiple potential mistakes

private var j:int = 0; // currentTab number

private function loadNextTab():void{

   arrTabs[j] = new Tab(j,_xmlTabs[j].attribute("icon"),_xmlTabs[j]);
   addChildAt(arrTabs[j],0);

   mRequest = new URLRequest(_xmlTabs[j].attribute("swf"));  
   mLoader = new Loader();
   addChild(mLoader);
   mLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onTabComplete);
   mLoader.load(mRequest);
}
private function onTabComplete():void{
   _xmlTabs[j].attribute("position")
   //Anything else you want to do to instantiate the object.

   currentTab++
   loadNextTab();
}

      

which doesn't answer your question about passing variables,

it responds with what I suggest you do with the code.

Passing Variables:

one common method is "Custom Events"

http://flexcomps.wordpress.com/2008/04/29/dispatching-custom-events-in-as3-with-data-or-object/

create a class that extends Event and then add a data object to Event. Any data you want to include must then be sent to the data object.

some other methods include:

anonymous functions, as thehiatus explains

 //errors inside anonymous functions are harder to debug.

      

and nested functions

private function startLoad():void{
   var j:int = 0;

   //load request calling LoadComplete

   funciton LoadComplete(e:Event){
      //has access to j
      //errors inside nested functions are harder to debug.
   }

      

}

but these methods won't work well with your for loop. the data you want to access is available by index, but your for-loop pushes through the index before anyone finishes downloading. The download queue is the way to find your current question.

good luck.

0


source


here's a quick fix! you can use Dictionary object.

var d:Dictionary=new Dictionary;
for (var j = 0; j < _xmlTabs.length(); j++) {
    arrTabs[j] = new Tab(j,_xmlTabs[j].attribute("icon"),_xmlTabs[j]);
    addChildAt(arrTabs[j],0);

    mRequest = new URLRequest(_xmlTabs[j].attribute("swf"));  
    mLoader = new Loader();
    //associate a tab with his loader...
    d[mLoader]=arrTabs[j];
    //
    addChild(mLoader);
    mLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onTabComplete);
    mLoader.load(mRequest);
}
//
function onTabComplete(e:Event):void{
    trace("your tab TAB >",d[e.target]);
}

      

0


source


Bind each bootloader to a tab (the tab has a link to the bootloader) and then use the .target member from the event to complete the download, then loop through your tabs to find the tab associated with that bootloader.

You will probably have to create your own tab class if you haven't given it proper bootloader link binding already.

I made a similar example of loading external resources and tracking their progress.

0


source







All Articles