views:

2715

answers:

5

This is a question specifically about creating a custom Loader class as a followup to http://stackoverflow.com/questions/758322/how-do-i-modify-existing-as3-events-so-that-i-can-pass-data. If this wasn't the right way to go about this, let me know.

I have a custom Loader class and a custom LoaderInfo class. What I can't figure out is how to have the Loader class use the custom LoaderInfo class as it's contentLoaderInfo property.

package com.display {
    import flash.display.Loader;

    import com.display.CustomLoaderInfo;

    public class CustomLoader extends Loader {
     public var customData:*;

     public function CustomLoader(passedData: *= null) {
      customData = passedData;
     }
    }
}

^ Have to do something in there to make it have the new CustomLoaderInfo

package com.display {
    import flash.display.LoaderInfo; 
    import flash.events.Event;

    import com.events.CustomEvent;

    public class CustomLoaderInfo extends LoaderInfo {
     public var customData:*;

     public function CustomLoaderInfo(passedData: *= null) {
      customData = passedData;
     }  

     override public function dispatchEvent(event:Event):Boolean {
      var customEvent:CustomEvent = new CustomEvent(event.type, customData, event.bubbles, event.cancelable);
      return super.dispatchEvent(customEvent);
     }
    }
}

^ That might work, but since I can't get CustomLoader to use it, I don't know yet.

A: 

You would have to override the function where the loaderinfo instance is created, and that might be in a private function. In the new function you could then instanciate your custom loaderInfo class instead, but you would also have to do anything else that the overwritten method does. You might run into some security sandbox problems with loadinfo as well. Overwriting a function like this is usually only posible when the function written with this in mind.

Alternatively you could use the prototype chain (read here) to change the loaderInfo class at runtime. But I wouldn't recommend it. It's not good practice in my opinion.

If you get this to work you still have the problem that your custom event will not work with any event that has properties not inheritet from the Event class (like the ProgressEvent that has progress related properties).

I would say you properly should look for another solution. In the question you link to you talk about sending movieclip with your event. Have you thought about reaching the other way? When you recieve the event, you get a reference to the object that dispatched it (Event.target). Can you not use that reference to get the movieclip?

Perhaps you could explain your problem in more detail (maybe in a new question so you still keep this open), I am sure there is a better / easier way to solve it.

Lillemanden
+3  A: 

I don't know how it fits into what you're doing, but you could not bother making an extended LoaderInfo at all. Loader.contentLoaderInfo has a property called loader that will return the Loader (or in this case CustomLoader) that was used. In theory you can just do this with the CustomLoader class that you have:


var loader: CustomLoader = new CustomLoader("Extra Data");
loader.load(new URLRequest("file.swf"));
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loaderComplete);

function loaderComplete(event: Event) : void
{
    var customData:* = (event.target.loader as CustomLoader).customData;
    trace(customData); // Extra Data
}
Bryan Grezeszak
A: 

I needed something like this because I wanted to carry an index with the info ... ie - have something like event.target.index available after an event is triggered .. anyway i designed a class that contained the loader and the loader info... heres the class

public class LoaderBox extends Sprite {

   public static var PROGRESS:String = "progress"
   public static var COMPLETE:String = "complete"

   public var id:int
   public var index:int
   public var loader:Loader
   public var info:LoaderInfo
   public var isOpen:Boolean
   //
   public var percent:Number = -1

   public function load(path:String,idx:int=-1,nm:String=null){
       loader  = new Loader()
    if (nm != null){
        name = nm
    }
    index = idx
       var req:URLRequest = new URLRequest(path)
       info = loader.contentLoaderInfo
    info.addEventListener(Event.COMPLETE,complete)
    info.addEventListener(ProgressEvent.PROGRESS,progress)
    isOpen = true
    loader.load(req) 
    }
    private function complete(e:Event):void{
    isOpen = false
    dispatchEvent(new Event(LoaderBox.COMPLETE))
    }
    private function progress(e:ProgressEvent):void{
    if (e.target.bytesTotal>0){ 
       percent = Math.floor(e.target.bytesLoaded/e.target.bytesTotal * 100)
    }
    dispatchEvent(new Event(LoaderBox.PROGRESS))
    }

}

A: 

A potential issue with the flagged answer: if contentLoaderInfo spits out a IOError, you can't access the .loader property to access your custom loader class.

What I did is the following: * in my custom loader class, create the following method:

    public function requestError(event:Event):void {
        dispatchEvent(event);           
    }

when adding a listener to contentLoaderInfo for the IOerror, point to the custom loader class's method:

_loaderCls.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, _loaderCls.requestError);

Then, add the same listener to your loader class and make it call any method you need. At that point, the event.target would be that of your custom loader class and you can add any extra info you need to that class:

_loaderCls.addEventListener(IOErrorEvent.IO_ERROR, requestError);
Khuffie
A: 

or you can do a better thing to pass data into the Loader class:


package com.display
{
    import flash.display.Loader;

    public class Loader extends flash.display.Loader
    {
        private var _obj:Object;

        public function Loader():void
        {
            super();
        }

        public function get obj():Object
        {
            return _obj;
        }

        public function set obj(o:Object):void
        {
            _obj = o;
        }
    }

}