PDA

View Full Version : preload image question (yes Willy, i did my research first :)


canadianjameson
07-24-2004, 06:08 PM
I have an intro page which consists of a multi-rollover image map (type thing). the issue is that some people who will be viewing the page will be on slower modems (56k for sure, if not 28.8... long story, old people).

anyways, i found a very concise preloader script through a search of this forum and through one of willy's posts... and i just have a question regarding how it works.


<script type="text/javascript">
//<![CDATA[
// Specify images to preload here:
var preload = new Array('EnlishOff.gif','EnglishOn.gif','EnterOff.gif','EnterOn.gif','EntrerOff.gif','EntrerOn.gif','F renchOff.gif','FrenchOn.gif');

var loader = new Array();
for(var i = 0; i < preload.length; i++){
loader[i] = new Image();
loader[i].src = preload[i];
}
//]]>
</script>


The images in BOLD are the ones that the user first see's (and that should load first). what i want to occur is that once the images in bold are loaded, the other images in the array start downloading to the user so that when they do an onMouseOver and cause the images to change, there's isn't a visual delay whilst the image downloads (as it would have already done so).

so how do i set which images load first, and then which ones load in the background?

would it suffice to just place them in order of download preference in the array? like so:


<script type="text/javascript">
//<![CDATA[
// Specify images to preload here:
var preload = new Array('EnlishOff.gif','EnterOff.gif','FrenchOff.gif','EnglishOn.gif','EnterOn.gif','EntrerOff.gif',' EntrerOn.gif','FrenchOn.gif');

var loader = new Array();
for(var i = 0; i < preload.length; i++){
loader[i] = new Image();
loader[i].src = preload[i];
}
//]]>
</script>


anyways, lemme know what would work best

Willy Duitt
07-24-2004, 07:47 PM
Yes, if you place the images in the preload array in the order they are needed on the page, they will be preloaded in that order....

However, I do not preload images per se....
I favor postloading....

postloading uses a function which is called on body onload which allows the page to load before the script is run and then starts preloading the images which will be needed for the mouseovers or image slides...

The advantage of this is that the initial loading of the page is not stalled while all of those images are preloaded. Calling the postload function on body onload allows the page to load normally before it starts using system resources to load images that are not necassarily needed from the onset. And as such, your orginal off images for your mouseovers could be removed from the postload/preload array because they would already be cached by the initial page load...

The disadvantage of postloading is that if a user jumps immediately to one of the mouseover links as soon as the page loads, there may be a slight lag in the first rollover if the script which is run onload has not yet had the time to preload the images. But this should not be that much of an issue if the rollover images are of reasonable byte size...

The use of either method over the other must be weighed by each individual webmaster. Fast initial page loads or almost, nearly, hopefully quarenteed fully functional mouseovers the very first time. (there's always the possibility that the images will fail to preload for one reason or another)....

.....Willy

canadianjameson
07-25-2004, 12:24 AM
hmmm, dat dere postLoad looks kinda purdy :D

actually thats precisely what i'm looking for. do you have a functional script you can launch my way? the images are all between 4k and 11k, so that lag you spoke of wouldn't really be a huge issue (hopefully).

anyways, toss the little beauty my way if you can :D (i assume i don't just literally change the word preload to postload... do i?)

Willy Duitt
07-25-2004, 02:09 AM
Here's the postLoad routine from a three image rollover script of mine. The images are consecutively numbered (IE: home1.gif, home2.gif, home3.gif) and the script looks for the className to postload only those images without declaring any images in the script. And the function only fires once regardless of how many times the page is refreshed or used on other pages throughout the site the script is used on....


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script type="text/javascript">
//<![CDATA[
function postLoad(){
for(var i=0; i<document.images.length; i++){
var image = document.images[i];
if(image.className.match(/menu/gi)){
if(!window.name.match(/preLoad.complete/gi)){
for(var j=2; j<=3; j++){
var preLoad = [];
preLoad[j] = new Image();
preLoad[j].src = image.src.replace(/\d(?=\.)/,j);
document.getElementById('test').innerHTML += '<br>'+preLoad[j].src;
}
}
}
} window.name = 'preLoad.complete';
}
//]]>
</script>
</head>
<body onload="postLoad()">

<div id="test">THESE IMAGES HAVE BEEN PRELOADED:</div>


<div class="navbar">
<ul class="navlist">
<li><a href="home.html"><img class="menu" src="../images/home1.gif"></a>
<li><a href="rosters.html"><img class="menu" src="../images/rosters1.gif"></a>
<li><a href="rules.html"><img class="menu" src="../images/rules1.gif"></a>
<li><a href="contact.html"><img class="menu" src="../images/contact1.gif"></a>
<li><a href="draft.html"><img class="menu" src="../images/draft1.gif"></a>
<li><a href="trades.html"><img class="menu" src="../images/trades1.gif"></a>
</ul>
</div>


If you only have two images in your rollover,
remove the var j for loop and replace j with 2 on this line:
preLoad[j].src = image.src.replace(/\d(?=\.)/,j);

.....Willy

canadianjameson
07-25-2004, 05:03 AM
when you say two images, you mean per area that gets rolled-over, or on the entire page? I ask because my rollover is a whopping... 7 image rollover mammoth :p does that mean i put j=7 ?

or wait, i only give the class to the images that don't immediately appear, right (?)... so that means 4 images.

as well, if i were to use this script in conjunction with that fade in script we're going on about in another thread... would i want to preload the fade-in images?

awesome script btw :)

hehe, people who turn of javascript are now officially BANNED from my page :) (is there a way to detect that btw?)

MikeFoster
07-28-2004, 06:12 PM
I also have always favored post-loading, but I didn't have a cool phrase for it. Willy has solved that problem. PostLoad is a perfect description for this technique! Great! :)

Skyzyx
07-28-2004, 06:54 PM
Personally, I prefer these (http://wellstyled.com/css-nopreload-rollovers.html) two (http://superfluousbanter.org/archives/000187.php) no-need-to-preload methods using CSS instead of JavaScript.

canadianjameson
08-03-2004, 10:03 PM
If you only have two images in your rollover,
remove the var j for loop and replace j with 2 on this line:
preLoad[j].src = image.src.replace(/\d(?=\.)/,j);

.....Willy


unfortunantly i'm using a script which doesnt explicitely declare the images in the body, but rather in th head. i think this is effecting the functionality of the postload script. i say that because the images i need postloaded i cant give a class to, as they are declared in the head script as previously stated.

have a look and tell me what can be done, if anything :)

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"><head>
<title>Enviromark Inc. - Please Select Your Preferred Language</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta http-equiv="Page-Exit" content="blendtrans(duration=1.75)">

<script language="JavaScript1.2">
<!--
top.window.moveTo(0,0);
if (document.all) {
top.window.resizeTo(screen.availWidth,screen.availHeight);
}
else if (document.layers||document.getElementById) {
if (top.window.outerHeight<screen.availHeight||top.window.outerWidth<screen.availWidth){
top.window.outerHeight = screen.availHeight;
top.window.outerWidth = screen.availWidth;
}
}
//-->
</script>

<script>
<!--
allow_default = true;

function show_images(n){

switch(n){
case 1 :
if(allow_default){
document.EnterOffSW.src = "img/EnterOn.gif";
document.EnglishOffSW.src = "img/EnglishOn.gif";
document.FrenchOffSW.src = "img/FrenchOn.gif";
}
break

case 2:
document.EnterOffSW.src = "img/EnterOff.gif";
document.EnglishOffSW.src = "img/EnglishOff.gif";
document.FrenchOffSW.src = "img/FrenchOff.gif";
break

case 3:
document.EnterOffSW.src = "img/EnterOn.gif";
break

case 4:
allow_default = false;
document.EnterOffSW.src = "img/EntrerOn.gif";
document.EnglishOffSW.src = "img/EnglishOn.gif";
document.FrenchOffSW.src = "img/FrenchOn.gif";
break

default:"";

}

}
// -->
</script>

<script type="text/javascript">
//<![CDATA[
function postLoad(){
for(var i=0; i<document.images.length; i++){
var image = document.images[i];
if(image.className.match(/menu/gi)){
if(!window.name.match(/preLoad.complete/gi)){
for(var j=2; j<=3; j++){
var preLoad = [];
preLoad[j] = new Image();
preLoad[j].src = image.src.replace(/\d(?=\.)/,j);
document.getElementById('test').innerHTML += '<br>'+preLoad[j].src;
}
}
}
} window.name = 'preLoad.complete';
}
//]]>
</script>
</head>

<style type="text/css">
#middle {
position:absolute;
left:50%;
top:58%;
width:210px;
height:202px;
margin-left:-105px;
margin-top:-101px;
}

.aboveMiddle {
position:absolute;
left:50%;
top:25%;
width:320px;
height:132px;
margin-left:-160px;
margin-top:-100px;
}
</style>
</head>

<body onload="postLoad()">

<div id="test">THESE IMAGES HAVE BEEN PRELOADED:</div>

<script type=text/javascript>
function newWin(urlLoc) {
_winName = "popupSelect";
_info = "toolbar=no"; // yes|no
_info += ",location=no"; // yes|no
_info += ",directories=no";// yes|no
_info += ",status=no"; // yes|no
_info += ",menubar=no"; // yes|no
_info += ",scrollbars=no";// yes|no
_info += ",resizable=yes"; // yes|no
_info += ",dependent"; // close the parent, close the popup, omit if you want otherwise
_info += ",height=155";
_info += ",width=425";
_info += ",left=355";
_info += ",top=100";
DispWin=window.open(urlLoc,_winName,_info);
}
</script>

<table id="middle" class="menu" cellpadding="0" cellspacing="0" onmouseover="show_images(1)" onmouseout="show_images(2)">
<tbody>
<tr><td colspan="2"><img name="EnterOffSW" src="img/EnterOff.gif" alt=""></td></tr>
<tr><td onmouseover="show_images(3)"><img name="EnglishOffSW" src="img/EnglishOff.gif" alt="" onClick="location='english/index.html'" style="cursor:hand"></td>
<td onmouseover="show_images(4)" onmouseout="allow_default=true"><img name="FrenchOffSW" src="img/FrenchOff.gif" alt="" onClick="javascript:newWin('bientot.htm')" style="cursor:pointer"></a></td>
</tr>
</tbody>
</table>
<img class="aboveMiddle" src="img/EnviromarkLogo.jpg" width="320" height="132" /></p>
</body>
</html>


oh, i realised that where i put the class="menu" wont work, but i didnt know where else to put it given the circumstances.

Willy Duitt
08-03-2004, 10:19 PM
The images are consecutively numbered (IE: home1.gif, home2.gif, home3.gif) and the script looks for the className to postload only those images without declaring any images in the script.

My script uses sets of consecutively numbered images...
Thus home1 is swapped with home2 and then again with home3 repeating this for each set of images which was placed in the array by looking for all images with the className of menu


Your images are not consecutively numbered.....
img/EnterOff.gif, img/EnglishOn.gif, img/FrenchOff.gif...


You will need to use some other generic preload routine which uses an array of images...

.....Willy

canadianjameson
08-03-2004, 10:30 PM
could i just change my filenames to make them consecutively numbered? i have no issue doing that

canadianjameson
08-04-2004, 06:33 PM
k, tried it and it just got messy.

here's my thought: how hard would i be to modify your postload script to accept and array of images instead of using the for loop? might make it a little more flexible.

i tried to combine the preload script i first posted and your postload script. i dont think it works as such but i think it may only be syntax related at this point. lemme know :D


<script type="text/javascript">
//<![CDATA[
function postLoad(){
{
var image = new Array('EnlishOff.gif','EnglishOn.gif','EnterOff.gif','EnterOn.gif','EntrerOff.gif','EntrerOn.gif','F renchOff.gif','FrenchOn.gif');

if(!window.name.match(/preLoad.complete/gi)){

var loader = new array();
for(var i = 0; i < preload.length; i++){

loader[i] = new Image();
loader[i].src = image[i].replace(/\d(?=\.)/,j);
document.getElementById('test').innerHTML += '<br>'+loader[i].src;
}
}
}
} window.name = 'preLoad.complete';
}
//]]>
</script>
</head>
<body onload="postLoad()">

<div id="test">THESE IMAGES HAVE BEEN POST-LOADED:</div>


hehe, well Willy... i actually tried amalgamating code this time. It appears i am moving up in the world :)

canadianjameson
08-06-2004, 04:52 AM
Any comments Willy?

Willy Duitt
08-06-2004, 05:31 PM
Any comments Willy?

About what?

If you do not want to use simularly named and consecutively numbered images... Use an array like you have started too and any number of generic preload scripts can easily do this and be adapted to postloading by simply placing the preload routine in a function and call the function on body.onload....

I would think your latest script example should work but this highlighted in red is not needed since you are not using any numbered images....
loader[i].src = image[i].replace(/\d(?=\.)/,j);

Remove that... All it does is look for a number which immediately precedes a dot (.) and replaces it with the value of the incrementer (j).....

.....Willy

canadianjameson
08-11-2004, 08:48 PM
sorry for the delay.

i've played around with the script willy, and i still cant get it to work... let alone list what was postloaded in the <div id="test">

here's what i've got so far. tell me where i'm going wrong


<script type="text/javascript">
//<![CDATA[
function postLoad(){
{
if(!window.name.match(/preLoad.complete/gi)){

var images = new Array('EnglishOn.gif','EnterOn.gif','EntrerOn.gif','FrenchOn.gif');
var loader = new array();
for(var i = 0; i < images.length; i++){

loader[i] = new Image();
loader[i].src = images[i];
document.getElementById('test').innerHTML += '<br>'+loader[i].src;
}
}
}
} window.name = 'preLoad.complete';
}
//]]>
</script>

<body onload="postLoad()">

<div id="test">THESE IMAGES HAVE BEEN POST-LOADED:</div>



i got a syntax error, and an error saying that an object was expected in the body onload line.... not that i put too much stock in the accuracy of I.E's error reporting...

Willy Duitt
08-11-2004, 09:23 PM
You have an opening bracket for the function in the wrong place on line two (I always place this bracket on the same line as the function)....

You also have two additional closing brackets. There should only be three. One for the function, one for the conditional and one for the loop....


<script type="text/javascript">
//<![CDATA[
function postLoad(){
if(!window.name.match(/preLoad.complete/gi)){
var images = new Array('EnglishOn.gif',
'EnterOn.gif',
'EntrerOn.gif',
'FrenchOn.gif');

var loader = new Array();
for(var i=0; i<images.length; i++){
loader[i] = new Image();
loader[i].src = images[i];
document.getElementById('test').innerHTML += '<br>'+loader[i].src;
} window.name = 'preLoad.complete';
}
}
//]]>
</script>

<body onload="postLoad()">
<div id="test">THESE IMAGES HAVE BEEN POST-LOADED:</div>


.....Willy

canadianjameson
08-11-2004, 10:25 PM
willy, you're awesomE.

Jeez man, i can't beleive i amalgamated the code relatively successfully. wow.

thanks for the alignment in the array, it'll help

SWEET!