Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Load XML images into FLASH as an Array

Status
Not open for further replies.

ShonGill

Programmer
May 20, 2008
44
US
I have the below ActionScript that works if I remove the loadXML and use an array that I define the image names in. I'm trying to load the image names from the XML file.

I think the problem is in parsing the XML. I can trace my photoXML anywhere in the script and it will output the entire contents of my XML file, however for some reason I cannot seem to get the file name out of the XML file into the array. So, the thumbnails are not loading into the movieclip. I'm I missing something?

XML File:
Code:
<root>
  <image>
    <IMG_ID>1</IMG_ID>
    <file>FileName0.jpg</file>
    <name>Micros Boarding</name>
    <brand>Micros</brand>
    <description>Just a quick description of file</desc>
    <img>image0.jpg</img>
    <thumb>image0_thumb.jpg</thumb>
  </image>
  <image>
    <IMG_ID>2</IMG_ID>
    <file>FileName1.jpg</file>
    <name>Indigo Star - Wave Surfing</name>
    <brand>Indigo Star</brand>
    <desc>Dude surfing on a huge wave!</desc>
    <img>image1.jpg</img>
    <thumb>image1_thumb.jpg</thumb>
  </image>
  <image>
    <IMG_ID>3</IMG_ID>
    <file>FileName2.jpg</file>
    <name>Micros More Boarding</name>
    <brand>Micros</brand>
    <desc>Skateboarding in empty swimming pool.</desc>
    <img>image2.jpg</img>
    <thumb>image2_thumb.jpg</thumb>
  </image>
</root]

Actionscript:
Code:
var photoXML:XML = new XML();
photoXML.ignoreWhite = true;
photoXML.load("MY XML LOCATION");
photoXML.onLoad = loadXML;

currentHolder = 0; 
theDepth = 1000; 
_global.imageLoaded = false;
_global.selectedImage = 0;

this.createEmptyMovieClip("img0_mc", theDepth++ + 10000); 
this.createEmptyMovieClip("img1_mc", theDepth++ + 10000);

function loadXML (loaded) {
	if (loaded) {
		var xmlParse:XmlNode = photoXML.firstChild;
		var thumb_arr:Array = new Array();
		total = xmlParse.childNodes.length;
		for (i = 0; i < total; i++) {
			thumb_arr[i] = xmlParse.childNodes[i].childNodes[6].firstChild.nodeValue;
			this.createEmptyMovieClip("thumb" + i + "_mc", theDepth++);
			this.createEmptyMovieClip("thumb" + i + "_tmp_mc", theDepth++);	
			this["thumb" + i + "_mc"]._x = 6;	
			this["thumb" + i + "_mc"]._y = 10 + 108 * i;	
			this["thumb" + i + "_mc"].loadMovie("IMAGE FOLDER LOCATION" + thumb_arr[i]);
			
			this["thumb" + i + "_tmp_mc"].no = i;	
			this["thumb" + i + "_tmp_mc"].onEnterFrame = function()	{
				var l = this._parent["thumb" + this.no + "_mc"].getBytesLoaded();
				var t = this._parent["thumb" + this.no + "_mc"].getBytesTotal();
				if ((l >= t) && (t > 1) && (this._parent["thumb" + this.no + "_mc"]._width > 1))  {
					this._parent["thumb" + this.no + "_mc"].num = this.no;
					this._parent["thumb" + this.no + "_mc"].onPress = function()  {
						if ((_global.selectedImage != this.num) && (_global.imageLoaded))  {
							loadImage(this.num);
						}
					};
					delete this.onEnterFrame;
					this.removeMovieClip();
				}
			};
			
		};
	}
};

Dishon Gillis
Dominion Enterprises Company
 
There are few syntax errors but more importantly you have a typical AS2 scope issue.

Syntax errors are:
[ul]
[li]Your XML is not well formed[/li]
[li][tt]XMLNode[/tt], not [tt]XmlNode[/tt][/li]
[li][tt]var total:Number[/tt], not [tt]total[/tt][/li]
[/ul]

Here is a couple of solutions to address the scope issue:
#1
Code:
function loadXML (loaded):Void {
   if (loaded) {
      var xmlParse:XMLNode = XML(this).firstChild;
      var thumb_arr:Array = new Array();
      var total:Number = xmlParse.childNodes.length;
      for (var i:Number = 0; i < total; i++) {
            thumb_arr[i] = xmlParse.childNodes[i].childNodes[6].firstChild.nodeValue;

            ...etc

      }
   }
}
#2
Code:
import mx.utils.Delegate; 

...

function loadXML (loaded):Void {
   if (loaded) {
      var xmlParse:XMLNode = photoXML.firstChild;
      var thumb_arr:Array = new Array();
      var total:Number = xmlParse.childNodes.length;
      for (var i:Number = 0; i < total; i++) {
            thumb_arr[i] = xmlParse.childNodes[i].childNodes[6].firstChild.nodeValue;

            ...etc

      }
   }
}
The REAL solution though, is to move to AS3. AS3 is so much easier - no scope issues whatsoever, and there's no need to parse XML like AS2 :)

Kenneth Kawamoto
 
Thank you for your help. I would like to move to AS3... eventually.

I will try this and let you know when I'm in front of it. One question, do you see me running into problems with the following script? This is the function that should be called from the first script. The thing is the scripts will be on seperate frames.

I considered using _global for my functions... Is this a good idea?

Code:
currentHolder = 0; 
theDepth = 1000;

function loadImage(num)  {
	_global.imageLoaded = false;
	this["img" + currentHolder + "_mc"]._x = -2;
	this["img" + currentHolder + "_mc"]._y = -1;
	this.createEmptyMovieClip("img0_tmp_mc", theDepth++);
	this.createEmptyMovieClip("img1_tmp_mc", theDepth++);
	this["img" + currentHolder + "_mc"].loadMovie(image_arr[num] + ".jpg");
	this["img" + currentHolder + "_tmp_mc"].onEnterFrame = function()  {	
		if (this._parent["img" + currentHolder + "_mc"]._width > 1)  {		
			this._parent["img" + currentHolder + "_mc"]._alpha = 1;
			this._parent["img" + currentHolder + "_mc"]._y = 50;
			_global.imageLoaded = true;
			_global.selectedImage = num;
			delete this.onEnterFrame;
			this.removeMovieClip();
		}
	};
	this["img" + ((currentHolder + 1) % 2) + "_tmp_mc"].onEnterFrame = function()  {	
		if (_global.imageLoaded)  {		
			if (this._parent["img" + currentHolder + "_mc"]._alpha < 100)		{							this._parent["img" + currentHolder + "_mc"]._alpha += 5;
			this._parent["img" + ((currentHolder + 1) % 2) + "_mc"]._alpha -= 20;
		} else {
			this._parent["img" + currentHolder + "_mc"]._alpha = 100;
			this._parent["img" + ((currentHolder + 1) % 2) + "_mc"]._alpha = 0;
			currentHolder = (currentHolder + 1) % 2;
			delete this.onEnterFrame;
			this.removeMovieClip();
  	  	  }	
		}
	};
	loadImage(_global.selectedImage);
}

Dishon Gillis
Dominion Enterprises Company
 
You should put all your scripts in one place. (Better still, put in external Class files.)

That said, yes you can call a function in a separate frame.

One problem is you are saying you are calling this from loadXML(). My solution #1 cannot call this function since this function is not in the scope of the XML object (unless as you said making this function _global, which is to me just a lazy coding and totally misuse of _global - but then again who cares in AS2 ;) However you can call this normally if you use my solution #2 with Delegate, since loadXML() is in the _root scope unlike the solution #1.

The other problem is that looking at your code, looks like this function runs infinitely.

Kenneth Kawamoto
 
Ok. So, your saying if I fix my syntax problems and place my code in one place and just change the scope of my "createEmptyMovieClip..." that the code should work. Or, if I use this mx.utils.Delegate that I will not have to change my scope because this function would still be called.

I have animations in frames above the function I'm trying to call. Will I lose their functionality by placing this loadImage actionscript? I really don't want to lose those, and I can't even begin to recreate them using AS2 or AS3.

Eventually, I'm going to code the whole thing in conventional AS3, class file and centralized actionscript. Like you are suggesting!

Dishon Gillis
Dominion Enterprises Company
 
Ok. Cool. I can't wait to try this out!

: )



Dishon Gillis
Dominion Enterprises Company
 
Oops I forgot to include the all important bit for the solution #2 ;)
Code:
photoXML.onLoad = Delegate.create(this, loadXML);

This worked! Thank you Kenneth.

I'm having trouble with loading the image now. I think I'm still having scope issues, and I have the loadImage function in a seperate frame like I was telling you before.

Because there is a MovieClip instance between the 'Thumbs' and the 'Loaded Image', I'm tryingt o find a way to convert the Glow Filter used into an ActionScript and apply it to a newly created Empty Movie Clip. Then I can put all the code in one place like you were suggesting before.

Any suggestions before I go about this? Would you look at the code I have so far? I really appreciate any help.

Dishon Gillis
Dominion Enterprises Company
 
I am trying to get that part working still. In my SWF clicking on the thumbnail does nothing, so there is some problem in the loadImage script, or perhaps it's not even being called.

I would never have though I would have to do this Delegate.create. What is it doing? and will it work with the loadImage function?

Dishon Gillis
Dominion Enterprises Company
 
So I should do something like this...

Code:
trace(photoXML)

photoXML is pulled from anywhere in my timeline.

This is what I have so far...

Code:
currentHolder = 0; 
theDepth = 1000;

function loadImage(numba)  {
	_global.imageLoaded = false;
	trace(photoXML);
	var img_mclListener:Object = new Object();
	img_mclListener.onLoadInit = functions(this["img" + currentholder + "_mc"]:MovieClip) {
		this["img" + currentholder + "_mc"]._x = -2;
		this["img" + currentholder + "_mc"]._y = -1;
	};

	this.createEmptyMovieClip("img0_tmp_mc", theDepth++);
	this.createEmptyMovieClip("img1_tmp_mc", theDepth++);

	var img_mcl:MovieClipLoader = new MovieClipLoader();
	this.img_mcl.addListener(img_mclListener);
	this.img_mcl.loadClip("../PHOTOTEST/" + image_arr[numba], this["img" + currentHolder + "_mc"]);
	this["img" + currentHolder + "_tmp_mc"].onEnterFrame = function()  {	
		if (this._parent["img" + currentHolder + "_mc"]._width > 1)  {		
			this._parent["img" + currentHolder + "_mc"]._alpha = 1;
			this._parent["img" + currentHolder + "_mc"]._y = 50;
			_global.imageLoaded = true;
			_global.selectedImage = num;
			delete this.onEnterFrame;
			this.removeMovieClip();
		}
	};
	this["img" + ((currentHolder + 1) % 2) + "_tmp_mc"].onEnterFrame = function()  {	
		if (_global.imageLoaded)  {		
			if (this._parent["img" + currentHolder + "_mc"]._alpha < 100)		{							this._parent["img" + currentHolder + "_mc"]._alpha += 5;
			this._parent["img" + ((currentHolder + 1) % 2) + "_mc"]._alpha -= 20;
		} else {
			this._parent["img" + currentHolder + "_mc"]._alpha = 100;
			this._parent["img" + ((currentHolder + 1) % 2) + "_mc"]._alpha = 0;
			currentHolder = (currentHolder + 1) % 2;
			delete this.onEnterFrame;
			this.removeMovieClip();
  	  	  }	
		}
	};
	loadImage(_global.selectedImage);
}

I had to place the contents of " i " into a different container to keep the same image reference throughout the entire movie. I think there may be some problems occurring in doing that, but I haven't found any yet. Remember this script is placed on the frame where I'm loading the large image Photo Gallery image to.

Do you see anything I did wrong?

Dishon Gillis
Dominion Enterprises Company
 
I'm getting the trace, but only after I removed this conditional:

Code:
if ((_global.selectedImage != this.num) && (_global.imageLoaded))

now it just keeps looping through the XML. I traced every line one-by-one until I found that the output for my loadImage function is returning all of the records in the XML several times, instead of returning only one (just the current record / thumbnail that is receiving the onPress).

the wierd thing is that when the thumbnails are loaded, there's only one thumb image loaded into it's own MovieClip container (so it's working just fine). it should be recognizing each thumbnail clicked, as an individual MovieClip.

It's actually, going back through the loop, like I was saaying and returning every image for this.num

I think the problem is with one of these, either:

Code:
loadImage(this.num);

is not getting a single output for the thumbnail that is clicked.


or, in my loadImage function:

Code:
this.img_mcl.loadClip("../PHOTOTEST/" + image_arr[num], this["img" + currentHolder + "_mc"]);

because image_arr:Array is a seperate array.


I'm ready to just start the whole thing over again.

Dishon Gillis
Dominion Enterprises Company
 
it returns the iterated output. let me explain it... I get a countdown starting from the total number of records in the XML file, less one (0 based total count).

it does this for the total number of records in the XML file. it does not seem to be pulling the assigned number for that thumbnail which called the "onPress".

the lines of code seem to output just fine up to that point. here is the code I'm modelling after. and I'm adding XML into the array.



Dishon Gillis
Dominion Enterprises Company
 
actually... i get

2
1
0
2
1
0
2
1
0

and a message... something like. looped 256 times.

I'm not in front of it right now. But it refers to 256 and that it seems it will be an infinite search.

Dishon Gillis
Dominion Enterprises Company
 
here's the verbage:

256 levels of recursion were exceeded in one action list.
This is probably an infinite loop.
Further execution of actions has been disabled in this movie.

Dishon Gillis
Dominion Enterprises Company
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top