Denoteone
Denoteone

Reputation: 4055

Reuse eventlistener for different loaders Flash - AS3

I want to reuse my loadImage function that is passed a url and a string value and it loads an image into a movie clip.

I have multiple images that I want to load into different movieClips. I thought I could just pass a variable with my addEventListener(Event.COMPLETE, but it only works the first time I load an image below is my code and below that is my error:

AS3

    //CALL loadImage  FUNCTION PASS URL TO LOCAL IMAGE AND UNIQUE NUMBER FOR EVENTLISTENER


loadImage('\\assets\\' + rootPath + '\\images\\bg.jpg',"1");
loadImage('\\assets\\' + rootPath + '\\images\\english.png',"2");
loadImage('\\assets\\' + rootPath + '\\images\\spanish.png',"3");

var imageLoader:Loader;

function loadImage(url:String,inc:String):void {
    trace(inc);
imageLoader = new Loader();
imageLoader.load(new URLRequest(url));
imageLoader.contentLoaderInfo.addEventListener(Event.COMPLETE,
    function(e:Event) : void { imageLoaded(inc) });

}

function imageLoaded(counter:String):void {
    trace(counter);
if (counter == "1"){

    trace("Background");
background.addChild(imageLoader);
}else if (counter == "2"){

    trace("english");

englishMC.addChild(imageLoader);
}else if (counter == "3"){

    trace("Spanish");

spanishMC.addChild(imageLoader);
}
}

error:

TypeError: Error #2007: Parameter listener must be non-null.
    at flash.events::EventDispatcher/addEventListener()
    at Function/<anonymous>()
    at EndCap_fla::MainTimeline/processXML()
    at flash.events::EventDispatcher/dispatchEventFunction()
    at flash.events::EventDispatcher/dispatchEvent()
    at flash.net::URLLoader/onComplete()

I know I could just have seperate functions for each image loaded but if possible I would like to be able to reuse the loadImage function

Upvotes: 0

Views: 598

Answers (3)

user1837285
user1837285

Reputation:

(It looks like you fixed that Error #2007 as CapelliC pointed it out.)

To reuse loadImage(), it has to be independent from anything outside it. Your current loadImage() needs imageLoader, which you should declare inside the function instead.

imageLoaded() is depending on it too, but since it goes in event listener, you should get the imageLoader by doing .addChild(e.currentTarget.loader) instead of .addChild(imageLoader).

That scope confusion is what's making you loose the two other loaded images (beware the closures!), because imageLoader is being overrided by a new instance of itself on every function call.

Also, you can easily pass any variable with your addEventListener() after a small change in imageLoaded(). That's how you should do it all:

loadImage("\\assets\\" + rootPath + "\\images\\bg.jpg", "1");
loadImage("\\assets\\" + rootPath + "\\images\\english.png", "2");
loadImage("\\assets\\" + rootPath + "\\images\\spanish.png", "3");

function loadImage(url:String, inc:String):void {
  trace(inc);
  var imageLoader:Loader = new Loader();
  imageLoader.load(new URLRequest(url));
  imageLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, imageLoaded(inc));
}

function imageLoaded(counter:String):Function {
  return function(e:Event):void {
    trace(counter);
    if (counter == "1") {
      trace("Background");
      background.addChild(e.currentTarget.loader);
    } else if (counter == "2") {
      trace("english");
      englishMC.addChild(e.currentTarget.loader);
    } else if (counter == "3") {
      trace("Spanish");
      spanishMC.addChild(e.currentTarget.loader);
    }
    //e.currentTarget.removeEventListener(Event.COMPLETE, arguments.callee);
  }
}

Now you can reuse both loadImage() and imageLoaded().

Upvotes: 0

Cristi Mihai
Cristi Mihai

Reputation: 2565

The problem is you are overriding the same imageLoader on each load, so basically everytime the imageLoaded is called, you will use the last image.

In your case, I would create a new class to handle the loading of an image into a specified container, something around these lines:

class ResourceLoader {
    private var target: Container;
    private var loader: Loader;

    function ResourceLoader(target:Container, image: String) {
        loader = ...
        loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);
    }

    function onComplete(e: Event):void {
        target.addChild(loader);
    }
}

and use it like this:

new ResourceLoader(background, '\\assets\\' + rootPath + '\\images\\bg.jpg');

(Haven't tested the code, might have some typos)

Upvotes: 1

CapelliC
CapelliC

Reputation: 60014

You should write the event handler inline, to pass your counter:

function loadImage(url:String,inc:String):void {
imageLoader = new Loader();
imageLoader.load(new URLRequest(url));
imageLoader.contentLoaderInfo.addEventListener(Event.COMPLETE,
    function(e:Event) : void { imageLoaded(inc) });
}

Upvotes: 1

Related Questions