/    Sign up×
Community /Pin to ProfileBookmark

Image event handlers not behaving as expected.

Dear all,

I’m building a slide show script and wanted to make it as automated as possible. To that effect I wanted to see if I could dynamically detect the number of files in the ‘gallery images’ folder so that the site owner only has to worry about adding new images to it, and not editing web pages or scripts each time. To do this I thought I could use a basic image preloading technique in a loop to count the number of images that actually exist, and then set that total as a variable that can then be used by the rest of the script. However, the event handlers (onload, onerror) seem to fire regardless of whether a file really exists or not, and in my test version I’m constantly having to artificially cap the loop so that it doesn’t run on ad-infinitum – defeating the entire point of the exercise.

My code is as follows:

[CODE]function doCount(URL) {
var y = 1;
Loop:
for (var x = 1; (x == y) && (y < 6); x++) {
tester = new Image();
tester.onload = y++;
tester.onerror = break Loop;
tester.src = URL + x + “.gif”;
}
return (x – 1);
}

var totalImages = doCount(*folder path*);[/CODE]

The behaviour of the event handlers has really stumped me TBH – the files don’t seem to be corrupted as they will load if added directly to a HTML image tag, and the same thing happens with other images I’ve tested with as well – and can only put it down to me either confusing how the event handlers actually work, or that they are just not supported in modern browsers as I’d expected (IE7, Firefox, Opera, etc). Does anyone have any ideas?

Thanks in advance – any help will be greatly appreciated.

to post a comment
JavaScript

11 Comments(s)

Copy linkTweet thisAlerts:
@KorJan 11.2007 — It is not very clear to me which is your problem, but I'll try an approach.

Usually, if no other pre-set handler in an event, an anonymous is to be used:

[I]element[/I].onevent=[B]function(){[/B]....[I]code, functions, and so on...[/I] ....[B]}[/B]
Copy linkTweet thisAlerts:
@robodanauthorJan 11.2007 — Sorry, I tried to be as descriptive as possible but I guess not as much as I'd thought.

The issue is with the event handlers executing on 'every' run of the loop, regardless of whether an image with that name actually exists or not. I've been testing the script with a bunch of alert() calls and 'all' of them always fire, necessitating the artificial cap in the for loop (the 'y < 6' bit). Essentially it is as if the event handlers don't actually exist and whatever code they refer to is being run automatically every time the loop goes through a cycle - not what I was expecting at all!

By the way, I've tried using the method you describe as well and that doesn't seem to make any difference either. TBH I haven't a clue what's going on! ?
Copy linkTweet thisAlerts:
@robodanauthorJan 12.2007 — Ok, so I've managed to do it, but with a couple of provisos.

After a bit more testing I now think that my problem was with the image not loading in time for the loop to actually register the effect of the particular event handler (the event handler was only being triggered 'after' the loop had completed). As a result I've changed the code so that the event handler actually does work as the trigger for the next loop cycle, controlling the counting process in the way I originally wanted it to do.

Anyway, here's my new code:

[CODE]var x = 1;

function doCount() {
var tester = new Image();
tester.onload = function() {
x++;
doCount();
}
tester.src = "../../assets/galleryImages/centre/" + x + ".jpg";
}

doCount(); [COLOR="Gray"]// Run the count on page load so that 'x' is calculated before anything else is done.
// The accumulated value of 'x' can then be called by the other functions when needed,
// as in:[/COLOR]

function play() {
alert("Total images in folder = " + (x - 1));
}[/CODE]

I guess you could call this solution rather rough and ready, and I'll have to do some further testing to see it server loading times make a real difference when there are lots of images in the folder, but all-in-all I'm happy.

Thanks again for the pointer Kor. ? -> ?
Copy linkTweet thisAlerts:
@KorJan 12.2007 — Still a little bit confusing for me, but I guess you are about a well known issue.

Inside a loop which circles through a collection of elements, if you need to "stick" the dynamic index, you need to "attach" it to the object, as a property, otherwise it's value will be always the last index (the lenght-1) because always the loop ends before any other later events. Later, using a closure of that element, that property can be returned / used.

<i>
</i>var allImg = document.getElementsByTagName('img');// the collection of all the images
for(var i=0;i&lt;allImg.length;i++){
allImg[i].[COLOR="Blue"]ind[/COLOR]=i; //a custom new property attached to the element
allImg.onclick=function(){alert('I am number '+this.[COLOR="Blue"]ind[/COLOR]+' in the image collection')}
}


Is this what you were talking about?
Copy linkTweet thisAlerts:
@robodanauthorJan 12.2007 — If I'm correct that would read through the web page and make a list of the images listed on it, right? If so, no that's not what I'm after. ?

I wanted to set up the slide show so that I wouldn't need to supply a list of images 'anywhere' (most scripts I've seen require an array of image paths or, at the very least, a variable declared to say how many images exist in the specified folder). Instead, when initially run the script would try and load images from the specified folder and when it could no longer load the next file - because the event handler throws an exception - the script would be able to use that final figure as the total number of images in the folder. That's what I meant when I was talking about making the whole thing dynamic/automated - the slide show would automatically accommodate however many images happen to be in the folder without having to be explicitly told so before being run.

Anyway, the code above seems to do the job I want so I'll use that for the time being as I work on the rest of the script.
Copy linkTweet thisAlerts:
@KorJan 12.2007 — aha, I see. I usually do not use javascript to check if a file exists or not in a folder. I guess that a server-side solution is much more indicated.
Copy linkTweet thisAlerts:
@robodanauthorJan 12.2007 — Unfortunately on this occasion I don't have that luxury. Thanks for the help though.
Copy linkTweet thisAlerts:
@robodanauthorFeb 04.2007 — Ok, I know this is a touch old now but I'm giving it a bump because I've just hit a snag testing the above code with Opera (9).

Basically [i]something[/i] is wrong and my code is causing Opera to go into a flat spin whenever the host page loads. After taking the code apart and running it in bits I am sure the problem is with the image event handlers. I guess my question is, does anyone know if Opera has 'issues' with image event handlers and/or is there a best practice way of using them to avoid the memory leakage I'm now discovering.

Alternatively, is there a way of checking if someone is using Opera and then isolating my code from them (i.e., displaying a notice saying the page won't work with that browser).

Opera is far from the main browser I am developing the site for but I hate loose ends and this is really frustrating me (my work on the site is complete apart from this little thing). Any help will be greatly appreciated.
Copy linkTweet thisAlerts:
@konithomimoFeb 04.2007 — well, if it was me I would create each image, and check if the image width is not 0, since an image with widht 0 would not show up, so we can say that it does not exist (since if there is no such image with the specified URL, the browser will give the image you ahve created a width of 0). Then add the real images to an array, and keep track of that number. If you need to load the images then they have already been created, and are stored in the array, so you wont have to wait for them to load if there are a lot of them. The following code does just that:

var myimages = new Array();
var totalimages = 0;

function doCount() {
var URL = "whateveryouwant"
var im;
var y = 0;
for (var x = 1; x&lt;20; x++) {
im = document.createElement('img');
im.src = URL + x + ".gif";
if(im.width!=0){
myimages[y]=im;
y++;
}
}
totalimages = y;
return true;
}


The loop I used only goes up to 20, and will work even if some images are there and some arent. For example, if you have pic1.gif, pic2.gif, and pic3.gif, then those will be added to the array, without any probelms arising do to that fact that there isnt a pic3.gif
Copy linkTweet thisAlerts:
@robodanauthorFeb 04.2007 — Brilliant! Great idea to use the image width instead of an event handler like I was trying to do, this is a lot tidier and the result works like a charm. Furthermore, Opera likes it as well! ? Thank you for your help konithomimo.
Copy linkTweet thisAlerts:
@konithomimoFeb 04.2007 — No problem
×

Success!

Help @robodan spread the word by sharing this article on Twitter...

Tweet This
Sign in
Forgot password?
Sign in with TwitchSign in with GithubCreate Account
about: ({
version: 0.1.9 BETA 5.18,
whats_new: community page,
up_next: more Davinci•003 tasks,
coming_soon: events calendar,
social: @webDeveloperHQ
});

legal: ({
terms: of use,
privacy: policy
});
changelog: (
version: 0.1.9,
notes: added community page

version: 0.1.8,
notes: added Davinci•003

version: 0.1.7,
notes: upvote answers to bounties

version: 0.1.6,
notes: article editor refresh
)...
recent_tips: (
tipper: @AriseFacilitySolutions09,
tipped: article
amount: 1000 SATS,

tipper: @Yussuf4331,
tipped: article
amount: 1000 SATS,

tipper: @darkwebsites540,
tipped: article
amount: 10 SATS,
)...