PDA

View Full Version : :: Ultimate Fade-in slideshow - empty first image in IE8



west05
10-08-2009, 01:00 PM
1) Script Title: :: Ultimate Fade-in slideshow (v2.1)

2) Script URL (on DD): http://www.dynamicdrive.com/dynamicindex14/fadeinslideshow.htm

3) Describe problem: In IE8 the first image does not show unless the page is refreshed (ctrl F5). If you go to another page and then back again randomly the first image will show. Click the next button it moves to image 2 and if you go back the first image is there. It works in every other browser but IE8.

Any help greatly appreciated


http://www.braycottages.com/test/christmas.htm and click on photo gallery

jscheuer1
10-08-2009, 04:08 PM
Works OK here in IE 8 on both the demo page on Dynamic Drive and on the gallery page from the page you link to. It did seem to take a little more time perhaps to load up the first image than might other browsers, but it did. You may always optimize your images to decrease the time required for this.

Are you sure your IE 8 is up to date? Are you allowing it to pick the display mode which it feels best suits the page, or do you have it set to display in IE 7 or quirks mode? My IE 8 chose to use IE 8 Standards and, as I say worked fine. You can use a meta tag to force IE 8 Standards mode:


<meta http-equiv="X-UA-Compatible" content="IE=8">

If you do, it should be the very first meta tag on your page.

west05
10-08-2009, 05:16 PM
Hi

Thanks for the reply. It's not just my IE8, It's the same for my client and also on other machines i've tested it on. I have already optimised the images as much as I can.

Added the meta tag, didn't make any difference

jscheuer1
10-08-2009, 05:33 PM
Do you have the same problem on the demo page on Dynamic Drive?

jscheuer1
10-08-2009, 05:40 PM
Wait a minute, I'm having the opposite problem from what you describe. If you navigate away and then use the back button, then you need to refresh. But this is not happening on the Dynamic Drive Demo, just your page. You may want to turn persist on, but this is just a fudge, there must be some underlying problem.

west05
10-08-2009, 05:52 PM
No the demo page is fine which is really stange. I just can't spot anything wrong.

west05
10-08-2009, 06:01 PM
I've spent about 3 hours on this so far, put it in a table, out of a table, in and out of divs, changed doc type, content type, disabled caching.......the list goes on :(

Thanks for your help on this

ddadmin
10-08-2009, 06:53 PM
Hmm this is a strange one. The script by design will start the slideshow when the first image has fully loaded. From the look of your page, it seems IE doesn't always signal when that happens, despite the fact that the script contains code that should have accounted for that bug. What happens if inside the .js file, you replace the following:


if ($curimage.get(0).complete){ //accounf for IE not firing image.onload
$loadingimg.hide()
slideshow.paginateinit($)
slideshow.showslide(setting.curimage)
}
else{ //initialize slideshow when first image has fully loaded
$loadingimg.hide()
slideshow.paginateinit($)
$curimage.bind('load', function(){slideshow.showslide(setting.curimage)})
}


with just:


$loadingimg.hide()
slideshow.paginateinit($)
slideshow.showslide(setting.curimage)

west05
10-08-2009, 07:56 PM
Yes it seems to work with that code. Obviously no fade on the first image but I can live with that :)

Thanks

jscheuer1
10-09-2009, 01:42 AM
DD, I find it odd that you appear to think IE 8 doesn't fire onload of images. Do you?

I've tried this various ways (hard coding to the tag, hard coding to injected HTML, etc. without being able to find IE 8 lacking, here's one fairly obtuse method, IE 8 still fires the event:


<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript">
jQuery.noConflict();
jQuery(function($){
var i = new Image();
$(i).bind('load', function(){alert('loaded, width: ' + this.width);}).attr('src', 'http://i26.tinypic.com/11l7ls0.jpg');
});
</script>
</head>
<body>
<div id="test">

</div>
</body>
</html>

ddadmin
10-09-2009, 05:45 AM
I had read IE7 has a bug with the onload event not always firing for images, which is why I had also included a check for images.complete, which apparently is fired consistently in IE. Now, I'm not sure if the same bug still exists in IE8, but the way the OP's page was behaving seems to indicate an issue with both methods not always firing in IE for images. I'm still not certain if that is in fact what's going on here...

jscheuer1
10-09-2009, 08:26 AM
if ($curimage.get(0).complete){ //accounf for IE not firing image.onload
$loadingimg.hide()
slideshow.paginateinit($)
slideshow.showslide(setting.curimage)
}
else{ //initialize slideshow when first image has fully loaded
$loadingimg.hide()
slideshow.paginateinit($)
$curimage.bind('load', function(){slideshow.showslide(setting.curimage)})
}

I think I get it. If you are relying upon the complete property of the image, you need to keep looping back somehow and checking for it again if it isn't true yet. But you really shouldn't have to because if the image isn't complete yet, the onload event will fire in IE once it is. It is only if the image is already complete before the onload event is assigned that IE will not fire the onload event (it already fired before it was assigned). Is there a way to assign the src attribute to the image after it is assigned the onload event?

If I've got that much more or less right, in IE 8 I've seen cases where syntax like:


$curimage.bind('load', function(){slideshow.showslide(setting.curimage)})

where there is a defined variable (slideshow in this case) within a function that will fire later (like a timeOut, Interval, or in this case load event), and that variable represents the 'this' of an instance of a constructor that has a prototypical function (showslide here), well sometimes IE 8 just doesn't make the connection when the time comes. But this in my experience only happens rarely, most of the time it does work, failing with an error for the 'missing' function when it does fail.

There's that and the fact that the OP has these meta tags for the page:


<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="-1" />

which would tend to make the images' complete status and/or load event perhaps ambiguous on reload or hitting the back button to get to the page.

I'm not sure what the resolution is, but I would try getting rid of those meta tags, clearing the browser's cache and testing then. Also, as I mentioned, I'm concerned about when the src attribute is assigned to the image in relation to when the onload event was bound to it (I'll look at the script itself). It obviously isn't a problem on the demo page here on DD though. There may be no resolution other than a bug fix to IE 8 itself because I don't think there is any way to avoid using slideshow.showslide() within the image onload function, or something like it to loop back to check for complete if it wasn't encountered the first time, though with no error, this (losing track of the instance) is probably not the problem.

jscheuer1
10-09-2009, 01:52 PM
OK, I've found a different, perhaps better approach to this loading business. Before I go into that though, I cannot yet set up a demo of the original problem in this thread, so I've no idea if this would solve that.

Now, the different method. I'm not sure why you do this:


var $curimage=setting.$gallerylayers.html(fullhtml).find('img').hide().eq(setting.curimage) //prefill both layers with entire slideshow content, hide all images, and return current image


so soon in the code, only to add the onload event so much later, so I moved it down to that area, so you would have:


var $curimage=setting.$gallerylayers.html(fullhtml).find('img').hide().eq(setting.curimage) //prefill both layers with entire slideshow content, hide all images, and return current image
if ($curimage.get(0).complete){ //accounf for IE not firing image.onload
$loadingimg.hide()
slideshow.paginateinit($)
slideshow.showslide(setting.curimage)
}
else{ //initialize slideshow when first image has fully loaded
$loadingimg.hide()
slideshow.paginateinit($)
$curimage.bind('load', function(){slideshow.showslide(setting.curimage)})
}


In keeping with what I said about adding the src attribute after the onload event of the image, I changed all of that to:


var $curimage = setting.$gallerylayers.html(fullhtml).find('img').hide().eq(setting.curimage); //prefill both layers with entire slideshow content, hide all images, and return current image
var tempSrc = $curimage.attr('src');
$curimage.attr('src', '').bind('load', function(){$loadingimg.hide();slideshow.paginateinit($);slideshow.showslide(setting.curimage)}).attr('src', tempSrc);


Ideally I think the images (empty images) should be added and then the load event, then their src attributes, but this is just as good, just a little less methodical, it removes the src after storing it, adds the event, then restores the src. The onload event must fire.

Demo:

http://home.comcast.net/~jscheuer1/side/ufade_2/alt_load.htm

west05
10-09-2009, 09:26 PM
Hi

I'm afraid the alternative load code doesn't work :( although I do now see the loader :)

It seems to work the first time you go to the page and Ctrl F5 sometimes.

http://www.braycottages.com/test/gallery-christmas.htm

I have also removed


<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="-1" />

Added the above just to see if it made any difference, it didn't.

west05
10-09-2009, 09:32 PM
Now I was just playing and added back in


<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="-1" />

And it really makes no difference, the images don't reload. The tags are being ignored. Could this be a hosting issue?

Edit: Not the hosting - http://www.rapturedesign.co.uk/bray/gallery-christmas.htm - was a long shot

ddadmin
10-10-2009, 12:12 AM
I think I get it. If you are relying upon the complete property of the image, you need to keep looping back somehow and checking for it again if it isn't true yet. But you really shouldn't have to because if the image isn't complete yet, the onload event will fire in IE once it is. It is only if the image is already complete before the onload event is assigned that IE will not fire the onload event (it already fired before it was assigned).


In a nutshell, yes, and the code I am using should take into account all of this already:


if ($curimage.get(0).complete){ //accounf for IE not firing image.onload
$loadingimg.hide()
slideshow.paginateinit($)
slideshow.showslide(setting.curimage)
}
else{ //initialize slideshow when first image has fully loaded
$loadingimg.hide()
slideshow.paginateinit($)
$curimage.bind('load', function(){slideshow.showslide(setting.curimage)})
}

My understanding of the image onload bug in IE is that when a page loads and the image is being retrieved from cache whereby it is already fully loaded, onload for the image will not fire (even though it should still). In that case checking for the "complete" property will catch those instances. In other words, the logic above should catch everything already.

Now like John I also have a hard time replicating the issue, so we're just throwing things out there to see what may or may not help. What happens west05 if you use the original .js file, but comment out the following two lines (new code in red):


var $curimage=setting.$gallerylayers.html(fullhtml).find('img').hide().eq(setting.curimage) //prefill both layers with entire slideshow content, hide all images, and return current image
if ($curimage.get(0).complete){ //accounf for IE not firing image.onload
$loadingimg.hide()
slideshow.paginateinit($)
slideshow.showslide(setting.curimage)
}
//else{ //initialize slideshow when first image has fully loaded
$loadingimg.hide()
slideshow.paginateinit($)
$curimage.bind('load', function(){slideshow.showslide(setting.curimage)})
//}

jscheuer1
10-10-2009, 12:13 AM
west05, I was really just more seeking ways to improve the loading sequence in general than to solve your particular issue, though that may eventually be a byproduct. As such my remarks were directed more toward ddadmin.

I'm also interested in your issue for its own sake. Thanks for checking on the meta tags, and for your report about the loading image. I had set up my demo with and without them (meta tags), they made no difference (my current demo still has them). In order to resolve your issue I will have to duplicate the problem first. I've tried the obvious (to me) with no success at duplicating the issue. I guess the next step (unless something just strikes me) will be making a mock up of your page using the original version of the script. When I have time I will probably do that after checking over your page's code a bit more with an eye to anything that might raise a flag for me.

west05
10-10-2009, 10:53 AM
Hi DD

It's the same, still only works on first load/refresh i'm afraid. And no loader now,

http://www.braycottages.com/test/gallery-christmas.htm

jscheuer1
10-10-2009, 11:25 AM
@west05,

This looks somewhat promising. Go back to using the actual script but use this for your configuration:


var mygallery1=new fadeSlideShow({
wrapperid: "fadeshow1", //ID of blank DIV on page to house Slideshow
dimensions: [516, 316], //width/height of gallery in pixels. Should reflect dimensions of largest image
imagearray: [
["images/gallery/christmas1.jpg"],
["images/gallery/christmas2.jpg"],
["images/gallery/christmas3.jpg"],
["images/gallery/christmas4.jpg"] //no trailing comma after very last image element!
],
displaymode: {type:'manual', pause:2500, cycles:0, wraparound:true},
persist: false, //remember last viewed slide and recall within same session?
fadeduration: 500, //transition duration (milliseconds)
descreveal: "ondemand",
togglerid: "fadeshow1toggler",
oninit: function(){this.navigate(0);}
})


And, I'm not sure why, but when I made a mock up of your page here locally and IE 8 denied this behavior (from your stylesheet) due to security:


img, div { behavior: url(iepngfix.htc) }


the page worked fine. In theory that should have no effect, but in practice could. So I would try removing that. If that takes care of it, we can add that back in a way that only IE 6 and less (the only browsers that need it) will even see it.

@DD,

As regards my previous post, I know that what you have should pretty much catch the various eventualities, I'm just thinking that having an actual onload event fire in all cases might be better. Even in other browsers adding the event after adding the src should not fire if the image loads before the event is added. And, as I say, other browsers don't observe the complete property of images in what I would consider a proper manner:


var i = new Image();
alert(i.complete);

alerts true here in Chrome and Firefox. It should be false in my opinion, as there is no image loaded yet.

west05
10-10-2009, 12:06 PM
Hi John

Adding this hax fixed it with the original code. You still don't get the loader though.


oninit: function(){this.navigate(0);}


Thanks

jscheuer1
10-10-2009, 12:13 PM
Hi John

Adding this hax fixed it with the original code. You still don't get the loader though.


oninit: function(){this.navigate(0);}


Thanks

Great, and as we may have cross posted while I was editing my previous post, have you also tried:


And, I'm not sure why, but when I made a mock up of your page here locally and IE 8 denied this behavior (from your stylesheet) due to security:


img, div { behavior: url(iepngfix.htc) }

the page worked fine. In theory that should have no effect, but in practice could. So I would try removing that. If that takes care of it, we can add that back in a way that only IE 6 and less (the only browsers that need it) will even see it.

Added Later:

If the oninit thing works with the original script, it will work with my modification which you said brought back the loader in IE 8