Forum Moderators: open

Message Too Old, No Replies

Slideshow image preloading (timing) problem

Problem: Slideshow code does not work on initial page load

         

Merganser

6:37 pm on Oct 11, 2009 (gmt 0)

10+ Year Member



I have cobled together a slideshow script. The intent is to display a default image (with HTML) and then if the users browser is java enabled, replace the static image with the slideshow. The problem is that it does not work on initial page load but then works flawlessly upon refreshing of the webpage. I had thought this was an image preloading issue but, I believe I am properly preloading the images. Nonetheless, if the cache is cleared, it does not work (slideshow area is blank w/ no images), if the page is refreshed, it does. After many hours of troubleshooting I have concluded some effect is taking place that I am not savy enough to identify. Any help would be VERY much appreciated. Code is listed below:

The HTML:

<div id="home_slideshow">
<center>
<img src="_PicToShowIfNoJava.gif">
</center>
<script type="text/javascript">
window.onload = RunSlideShow;
</script>
</div>

The javascript:
I include the startFading(), setOpacity(), and FadeInNextImage() functions below for completeness but these all seem to work fine (upon page refresh anyway).

function RunSlideShow()
{

var SlideShowHeight = 180;
var SlideShowWidth = 240;
var imageTimeout = 2000; // milliseconds

// Specify Images to be included in Slideshow
var images = new Array(
'/Pic1.gif',
'/Pic2.gif',
'/Pic3.gif',
'/Pic4.gif',
'/Pic5.gif'
);

//Specify full path, needed due to dynamic nature of http:// vs. https://
var site = window.location.protocol + '//' + window.location.hostname;
var ImagesToLoad = images.length;
var nextImage = 1;

// Preload images (while default image is being displayed)
var ResizedImage = new Array();
for(var i=0; i<images.length; i++) {
ResizedImage[i] = new Image();
ResizedImage[i].onLoad=ImageLoaded(); //Will call function once for each image
ResizedImage[i].src = site.concat(images[i]);
var OriginalPictureHeight = ResizedImage[i].height;
var OriginalPictureWidth = ResizedImage[i].width;
var HeightScaleFactor = SlideShowHeight / OriginalPictureHeight;
var WidthScaleFactor = SlideShowWidth / OriginalPictureWidth;
if ((HeightScaleFactor >= 1) && (WidthScaleFactor >= 1)){
// Image is smaller that screen, maintain original image size
var NewPictureHeight = OriginalPictureHeight;
var NewPictureWidth = OriginalPictureWidth;
var OffsetLeft = (SlideShowWidth-OriginalPictureWidth)/2;
var OffsetTop = (SlideShowHeight-OriginalPictureHeight)/2;
}else{
// Image is larger than screen, shrink image to fit screen
if (HeightScaleFactor <= WidthScaleFactor){
var NewPictureHeight = OriginalPictureHeight * HeightScaleFactor;
var NewPictureWidth = OriginalPictureWidth * HeightScaleFactor;
var OffsetLeft = (SlideShowWidth-NewPictureWidth)/2;
var OffsetTop = 0;
}else{
var NewPictureHeight = OriginalPictureHeight * WidthScaleFactor;
var NewPictureWidth = OriginalPictureWidth * WidthScaleFactor;
var OffsetLeft = 0;
var OffsetTop = (SlideShowHeight-NewPictureHeight)/2;
}
}
ResizedImage[i].style.position = 'absolute';
ResizedImage[i].style.visibility = 'hidden';
ResizedImage[i].style.height = NewPictureHeight;
ResizedImage[i].style.width = NewPictureWidth;
ResizedImage[i].style.marginLeft = OffsetLeft + 'px';
ResizedImage[i].style.marginTop = OffsetTop + 'px';
ResizedImage[i].style.backgroundColor = '#FFFFFF';
}

function ImageLoaded(){
ImagesToLoad--;
if (ImagesToLoad == 0){
// All Images now preloaded, start Slideshow
// Get DIV Element, eliminate children, set slideshow display dimensions
var el = document.getElementById('home_slideshow');
while (el.firstChild) { el.removeChild(el.firstChild); }
el.style.height = SlideShowHeight + 'px';
el.style.width = SlideShowWidth + 'px';
// Add images to show (all hidden initially)
for(var i=0; i<images.length; i++) {
el.appendChild(ResizedImage[i]);
}
// Show first image
el.firstChild.style.visibility = 'visible';
el.firstChild.style.zIndex = 1;
// Start Slideshow fading
window.setTimeout(startFading, imageTimeout);
}
}

function startFading() {
var el = document.getElementById('home_slideshow').childNodes[nextImage];
setOpacity(el, 0);
el.style.visibility = 'visible';
el.style.zIndex = 2;
FadeInNextImage(el, 0);
nextImage = (nextImage < images.length-1) ? nextImage + 1 : 0;
}

function setOpacity(el, opacity) {
// Specify opacity for different browsers
opacity /= 100;
// FireFox
el.style.MozOpacity = opacity;
// Internet Explorer
el.style.filter = "alpha(opacity=" + (opacity*100) + ")";
// Everything Else
el.style.opacity = opacity;
}

function FadeInNextImage(el, currentOpacity) {
var prevEL = el.previousSibling ? el.previousSibling : el.parentNode.lastChild;
currentOpacity = currentOpacity + 5;
if (currentOpacity <= 100) {
setOpacity(el, currentOpacity);
setOpacity(prevEL, 100-currentOpacity);
window.setTimeout(function() { FadeInNextImage(el, currentOpacity); }, 50);
}else{
setOpacity(el, 100);
el.style.zIndex = 1;
setOpacity(prevEL, 0);
prevEL.style.visibility = 'hidden';
window.setTimeout(startFading, imageTimeout);
}
}

}

daveVk

11:49 pm on Oct 11, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



for(var i=0; i<images.length; i++) {
ResizedImage[i] = new Image();
ResizedImage[i].onLoad=ImageLoaded(); //Will call function once for each image
ResizedImage[i].src = site.concat(images[i]);
... block of code ...
}

The block of code indicated refers to properties of ResizedImage[i] prior to image load, should be moved to within ImageLoaded ?

Merganser

12:39 am on Oct 12, 2009 (gmt 0)

10+ Year Member



You know, I started it that way (and just now put it back that way to double check). It still does not display on initial load and then runs flawlessly upon browser refresh. One additional side effect is also produced with your recommended structure - the last picture does not show. I remember now I had fixed this by structuring it the way I posted, although admittedly not knowing why. Perhaps non display of the last pic is related. Your comment does make since to me though so I think I will leave it as you suggest and work on fixing the cause of the last pic not displaying for now. If you have further suggestions on making it work on initial load I would be glad to hear them.

Merganser

2:58 am on Oct 12, 2009 (gmt 0)

10+ Year Member



OK, I got the last pic to display by switching the order of these 2 lines:

ResizedImage[i].onLoad=ImageLoaded();
ResizedImage[i].src = site.concat(images[i]);

Thus, the new order is:

ResizedImage[i].src = site.concat(images[i]);
ResizedImage[i].onLoad=ImageLoaded();

So, I am now using the structure suggested by daveVk but I am also right back were I was to start. The slideshow script runs flawlessly upon browser refresh but the slideshow does not display at all on initial load. Any help is greatly appreciated.

daveVk

10:41 pm on Oct 12, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



The penny droped

try

ResizedImage[i].onload=ImageLoaded;
ResizedImage[i].src = site.concat(images[i]);

Note

onLoad => onload ( case sensitive )
ImageLoaded() => ImageLoaded ( we don't what ImageLoaded executed and result assigned to onload/onLoad )

Merganser

2:22 am on Oct 13, 2009 (gmt 0)

10+ Year Member



Unbelievable! Well, I definitely know I never would have figured that out. Your suggestion worked. Since my last post I have been inserting alert() statements to follow various variables and their values throughout execution. I had noticed that even though I successfully assigned new height and width properties to ResizedImage[i], and appended the resized image as a child to el, once I retrieved the image to fade using:

el = document.getElementById('home_slideshow').childNodes[nextImage];

the height and width were both 0 (only on initial load). Technically, everything else worked - it was fading images with 0 height and width. I was troubling with what to do about that. Your solution is completely off kilter from where I was heading. Only problem is that I really do not understand what just happened and how this fixed it. Not sure what "The penny dropped" means. I am happy enough but if you are willing to explain I would appreciate it. Thank you very much.

daveVk

3:17 am on Oct 13, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



ResizedImage[i].onLoad=ImageLoaded();

This statement will execute ImageLoaded ( not waiting for image to load ), if it happens to return a value (none in this case ) it will be stored in ResizedImage[i].onLoad

Result, ImageLoaded executed prior to image load, ResizedImage[i].onLoad=NULL.

ResizedImage[i].onload=ImageLoaded;

This statement does not execute ImageLoaded, just sets ResizedImage[i].onload to a value refering to ImageLoaded. So when the image (ResizedImage[i]) loads ResizedImage[i].onload ALIAS ImageLoaded is executed.

Merganser

3:59 am on Oct 13, 2009 (gmt 0)

10+ Year Member



OK - Thanks for your help.

rocknbil

7:16 pm on Oct 13, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



This may help too. Change it to this.

window.onload = function() { RunSlideShow(); };

daveVk

1:31 am on Oct 14, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



rocknbil ? - what do you see as the advantage of

window.onload = function() { RunSlideShow(); };

over

window.onload = RunSlideShow;

rocknbil

4:50 pm on Oct 14, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Whenever I try this

window.onload = someFunction;

it usually fails, while this

window.onload = function() {
someFunction();
someFunction2(); //etc
};

always works. Unfortunately, I've forgotten the why, sorry. :-( That's why I said "may" help.