Forum Moderators: open

Message Too Old, No Replies

Loop variable problem.

         

catcherintherye51

10:00 pm on Jun 13, 2006 (gmt 0)

10+ Year Member



Can anyone tell me what's wrong with this script? This loads the thumbnails into SlideShowPro via XML, but I'm having a problem with the loadImageNumber link. I can hardcode loadImageNumber(3) and it will load thumbnail #3 for EVERY thumbnail, but for some reason it's not accepting the variable data from "this.picNo = Number(i);"

for (i=0; i<numimages; i++) {
this.picHolder = this.firstChild.childNodes[i];
this.thumbHolder = image_tn.createEmptyMovieClip("thumbnail"+i, i);
this.thumbHolder._y = i*spacing;
this.picNo = Number(i);
this.thumbLoader = this.thumbHolder.createEmptyMovieClip("thumbnail_image", 0);
this.thumbLoader.loadMovie(this.picHolder.attributes.tn);
this.thumbHolder.onRelease = function() {
ssp.loadImageNumber(picNo);
}
};

I don't think you need to know that much about SlideShowPro to answer this question, just need to know how I can get the loop numbers in place of picNo (eg. ssp.loadImageNumber(1, 2, 3, etc...));

Any help would be great. Thanks!

texmex

10:44 pm on Jun 13, 2006 (gmt 0)

10+ Year Member



should it perhaps be:
ssp.loadImageNumber(this.picNo);

catcherintherye51

1:35 am on Jun 14, 2006 (gmt 0)

10+ Year Member



I tried that... still didn't work.

Thanks, though!

kaled

9:11 am on Jun 14, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



At first glance, the code seems to be meaningless. What is the point of repeatedly assigning an event handler within a loop?

However, assuming the concept is right, picNo must be declared elsewhere as a global variable. You should assign to that in the loop rather than this.picNo. Also, i is already a number, there is no need to use a typecast for this assignment.

Kaled.

catcherintherye51

2:43 pm on Jun 14, 2006 (gmt 0)

10+ Year Member



Thanks... I'll give that a shot. How do I define picNo as a global variable? (Yes, I'm pretty new to this!)

What this script does is create thumbnails from an XML file that lists the image locations, and aligns the thumbnails vertically next to the main image. When you click on a thumbnail the main image changes. (It's basically feeding a program called SlideShowPro the info via the ssp.loadImageNumber(picNo); command.)

Everything works fine, except the link. As long as I can get the picNo assigned a number it will work great.

Thanks a lot for your help!

kaled

3:52 pm on Jun 14, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Global variables are declared using the var statement (just like local ones). Any variable that is declared outside a function is global. Some people declare all globals at the top of a script, but provided they are declared above the point of first usage, the precise position is unimportant.

I still have doubts about the concept of assigning an event handler this way - it doesn't make any sense to me. But what I've suggested might work.

Kaled.

john_k

4:19 pm on Jun 14, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Try this

this.thumbHolder.onRelease = new Function('ssp.loadImageNumber('+i+');');

Fotiman

5:21 pm on Jun 14, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Perhaps the Yahoo UI Library [com1.devnet.scd.yahoo.com] might be of help. Specifically, the Event Utility [com1.devnet.scd.yahoo.com]. It's usage is explained on that site, but applying it to your code would look like this:


<script type="text/javascript" src="yahoo.js"></script>
<script type="text/javascript" src="event.js"></script>
<script type="text/javascript">
for (i=0; i<numimages; i++) {
this.picHolder = this.firstChild.childNodes[i];
this.thumbHolder = image_tn.createEmptyMovieClip("thumbnail"+i, i);
this.thumbHolder._y = i*spacing;
this.thumbLoader = this.thumbHolder.createEmptyMovieClip("thumbnail_image", 0);
this.thumbLoader.loadMovie(this.picHolder.attributes.tn);
YAHOO.util.Event.addListener( this.thumbHolder, "release", function(){ssp.loadImageNumber(i);} );
}
</script>

I *think* that would work for you.
Hope that helps.

john_k

5:33 pm on Jun 14, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



The variable i needs to be evaluated during the loop. It won't exist when the onrelease handler is called. And if you replace that with a global variable, then EVERY thumbnail will be set to pass the identical value.

visionmonster

6:15 pm on Jun 14, 2006 (gmt 0)

10+ Year Member



scoping in javascript is pretty tricky.

Daniel Brockman wrote a pretty good article on it [brockman.se...]

I'm guessing you would just need to add this js to enable binding in your script:
/* binding */
Function.prototype.bindEventListener = function (object) {
var method = this;var preappliedArguments = withoutFirst(arguments);
return function (event) {return method.apply(object, cons(event ¦¦ window.event, preappliedArguments));};
}
Function.prototype.bind = function(object){
var method = this;var preappliedArguments = withoutFirst(arguments);
return function(){return method.apply(object,concat(preappliedArguments,arguments));};
}
function concat(){
var result = [];for (var i=0;i<arguments.length;i++)for (var j=0;j<arguments[i].length;j++)result.push(arguments[i][j]);
return result;
}
function withoutFirst(sequence){
result = [];for (var i=1;i<sequence.length;i++)result.push(sequence[i]);
return result;
}
function cons(element, sequence) {
return concat([element], sequence);
}
/* /binding */

you should then be able to replace this:
this.thumbHolder.onRelease = function() {
ssp.loadImageNumber(picNo);
}
with this:
this.thumbHolder.onrelease = ssp.loadImage.bind(this,picNo);

and magically picNo should be associated with the thumbHolder object that fired the event.

if you can get the yahoo utils to work, i'd recommend that method as it has a number of other nice features build into it.

john_k

7:00 pm on Jun 14, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I am pretty sure that the OP doesn't want the variable bound to the event handler. What they need is the incremented value of i to be written as a literal argument.

So the first thumbnail image will have this as its onrelease function:
ssp.loadImageNumber(0);

And the second thumbnail will have this as its onrelease function:
ssp.loadImageNumber(1);

If you bind the variable, or pass the variable like this:
ssp.loadImageNumber(picNo);

Then the links for all of the thumbnails are effectively the same. Whatever the value of picNo (if it exists) happens to be will apply to every thumbnail.

Also since the function is being fired by a link, doing this code:
ssp.loadImageNumber(this.picNo);
will not work - because when it fires, this will evaluate to the link itself, which does not have a picNo property.

catcherintherye51

7:08 pm on Jun 14, 2006 (gmt 0)

10+ Year Member



Thanks everyone! I'll try the suggestions, and post whatever worked for me.

jshanman

7:19 pm on Jun 14, 2006 (gmt 0)

10+ Year Member



Why not:

this.thumbHolder.picNo = i;
this.thumbHolder.onRelease = function() {
ssp.loadImageNumber(this.picNo);
}

If that doesn't work, then I'd need to see the whole function / caller code.
- JS

catcherintherye51

7:23 pm on Jun 14, 2006 (gmt 0)

10+ Year Member



The code above worked perfectly - And I thought I tried every combination possible!

Thanks a lot for everyone's help. Here's the code that finally worked:

myPhoto = new XML();
myPhoto.ignoreWhite = true;
myPhoto.onLoad = function(success) {
//portfolioTag = this.firstChild;
numimages = this.firstChild.childNodes.length;
spacing = 40;
for (i=0; i<numimages; i++) {
this.picHolder = this.firstChild.childNodes[i];
this.thumbHolder = image_tn.createEmptyMovieClip("thumbnail"+i, i);
this.thumbHolder._y = i*spacing;
this.thumbHolder.picNo=i;
this.thumbLoader = this.thumbHolder.createEmptyMovieClip("thumbnail_image", 0);
this.thumbLoader.loadMovie(this.picHolder.attributes.tn);
this.thumbHolder.onRelease = function() {
ssp.loadImageNumber(this.picNo);
}
};
};
myPhoto.load("xmlphoto.xml");

jshanman

9:58 pm on Jun 14, 2006 (gmt 0)

10+ Year Member



And I thought I tried every combination possible!

That's my favorite way to debug too :)

- JS

catcherintherye51

4:49 pm on Jun 15, 2006 (gmt 0)

10+ Year Member



OK... One final feature:

Here's the code that creates the thumbnails

myPhoto = new XML();
myPhoto.ignoreWhite = true;
myPhoto.onLoad = function(success) {
//portfolioTag = this.firstChild;
numimages = this.firstChild.childNodes.length;
spacing = 40;
for (i=0; i<numimages; i++) {
this.picHolder = this.firstChild.childNodes[i];
this.thumbHolder = image_tn.createEmptyMovieClip("thumbnail"+i, i);
this.thumbHolder._y = i*spacing;
this.thumbHolder.picNo=i;
this.thumbLoader = this.thumbHolder.createEmptyMovieClip("thumbnail_image", 0);
this.thumbLoader.loadMovie(this.picHolder.attributes.tn);
this.thumbHolder.onRelease = function() {
ssp.loadImageNumber(this.picNo);
}
};
};
myPhoto.load("xmlphoto.xml");

And here's the XML file

<?xml version="1.0" encoding="UTF-8"?>
<gallery>
<img src="images/Villa_Penasco1.jpg" tn="thumbnails/Villa_Penasco1.jpg"/>
<img src="images/Villa_Penasco7.jpg" tn="thumbnails/Villa_Penasco7.jpg"/>
<img src="images/Villa_Penasco3.jpg" tn="thumbnails/Villa_Penasco3.jpg"/>
<img src="images/Villa_Penasco4.jpg" tn="thumbnails/Villa_Penasco4.jpg"/>
<img src="images/Villa_Penasco5.jpg" tn="thumbnails/Villa_Penasco5.jpg"/>
<img src="images/Villa_Penasco6.jpg" tn="thumbnails/Villa_Penasco6.jpg"/>
<img src="images/Villa_Penasco7.jpg" tn="thumbnails/Villa_Penasco7.jpg"/>
<img src="images/Villa_Penasco8.jpg" tn="thumbnails/Villa_Penasco8.jpg"/>
<img src="images/Villa_Penasco9.jpg" tn="thumbnails/Villa_Penasco9.jpg"/>
<img src="images/Villa_Penasco10.jpg" tn="thumbnails/Villa_Penasco10.jpg"/>
<img src="images/Villa_Penasco11.jpg" tn="thumbnails/Villa_Penasco11.jpg"/>
<img src="images/Villa_Penasco12.jpg" tn="thumbnails/Villa_Penasco12.jpg"/>
<img src="images/Villa_Penasco13.jpg" tn="thumbnails/Villa_Penasco13.jpg"/>
<img src="images/Villa_Penasco14.jpg" tn="thumbnails/Villa_Penasco14.jpg"/>
</gallery>

Now I want to add a dynamic title field so I have a title for the "album."

If I change the XML file to this

<?xml version="1.0" encoding="UTF-8"?>
<gallery>
<album title="Villa Penasco">
<img src="images/Villa_Penasco1.jpg" tn="thumbnails/Villa_Penasco1.jpg"/>
<img src="images/Villa_Penasco7.jpg" tn="thumbnails/Villa_Penasco7.jpg"/>
<img src="images/Villa_Penasco3.jpg" tn="thumbnails/Villa_Penasco3.jpg"/>
<img src="images/Villa_Penasco4.jpg" tn="thumbnails/Villa_Penasco4.jpg"/>
<img src="images/Villa_Penasco5.jpg" tn="thumbnails/Villa_Penasco5.jpg"/>
<img src="images/Villa_Penasco6.jpg" tn="thumbnails/Villa_Penasco6.jpg"/>
<img src="images/Villa_Penasco7.jpg" tn="thumbnails/Villa_Penasco7.jpg"/>
<img src="images/Villa_Penasco8.jpg" tn="thumbnails/Villa_Penasco8.jpg"/>
<img src="images/Villa_Penasco9.jpg" tn="thumbnails/Villa_Penasco9.jpg"/>
<img src="images/Villa_Penasco10.jpg" tn="thumbnails/Villa_Penasco10.jpg"/>
<img src="images/Villa_Penasco11.jpg" tn="thumbnails/Villa_Penasco11.jpg"/>
<img src="images/Villa_Penasco12.jpg" tn="thumbnails/Villa_Penasco12.jpg"/>
<img src="images/Villa_Penasco13.jpg" tn="thumbnails/Villa_Penasco13.jpg"/>
<img src="images/Villa_Penasco14.jpg" tn="thumbnails/Villa_Penasco14.jpg"/>
</album>
</gallery>

The javascript mistakes the <album title="Villa Penasco"> for an image, and doesn't show any of the thumbnails.

Question: How can I get the javascript loop to skip <album title="Villa Penasco"> but read the rest of the images? I think it has something to do with which childNode it starts at, correct?

Any help will be deeply appreciated!

catcherintherye51

5:18 pm on Jun 15, 2006 (gmt 0)

10+ Year Member



Answered my own question...

myPhoto = new XML();
myPhoto.ignoreWhite = true;
myPhoto.onLoad = function(success) {
//portfolioTag = this.firstChild;
numimages = this.firstChild.childNodes[0].childNodes.length;
spacing = 40;
for (i=0; i<numimages; i++) {
this.picHolder = this.firstChild.childNodes[0].childNodes[i];
this.thumbHolder = image_tn.createEmptyMovieClip("thumbnail"+i, i);
this.thumbHolder._y = i*spacing;
this.thumbHolder.picNo=i;
this.thumbLoader = this.thumbHolder.createEmptyMovieClip("thumbnail_image", 0);
this.thumbLoader.loadMovie(this.picHolder.attributes.tn);
this.thumbHolder.onRelease = function() {
ssp.loadImageNumber(this.picNo);
}
};
};
myPhoto.load("xmlphoto.xml");

jshanman

5:39 pm on Jun 15, 2006 (gmt 0)

10+ Year Member



Just add another level (or two to support multiple galleries) of looping...

numgalleries = this.childNodes.length;
this.galleryHolder = this.childNodes;

for (g=0; g<numgalleries; g++) {
numalbums = this.childNodes[g].childNodes.length;
this.galleryHolder[g].albumHolder = this.childNodes[g].childNodes;

for (a=0; a<numalbums; a++) {
numimages = this.childNodes[g].childNodes[a].length;
this.galleryHolder[g].albumHolder[a] = this.childNodes[g].childNodes[a].childNodes;

for (i=0; i<numimages; i++) {
this.galleryHolder[g].albumHolder[a] = this.childNodes[g].childNodes[a].childNodes[i]picHolder = this.childNodes[g].childNodes[a].childNodes[i];
}//end images
}//end albums
}//end galleries

This allows you to support an XML file that contains galleries of albums of images.

- JS