Jump to content
xisto Community
SystemWisdom

Image Preloader With Progress Bar Status Pure Client-Side JavaScript tested in 4 Browsers

Recommended Posts

Tutorial: Image Preloader with Progress Bar, by Rob J. Secord, B.Sc. (SystemWisdom)

 

 

Description:

A Tutorial for a Client-Side Image Preloader with Dynamic Real-Time Progress Bar Indicator written in JavaScript!

Tested to work with 4 Major Internet Browsers: Firefox, MSIE, Netscape, Opera

 

(Complete sample solution provided at end of tutorial, just put it on your web-server, add your images and go!)

 

 

Intended Audience:

Beginner to Intermediate Web Developers.

 

Although this tutorial will cover some advanced aspects of JavaScript, I will try to explain it all as thoroughly as possible. At the same time, I will keep the functionality basic and leave room for you to expand on it as you see fit.

 

Assumed knowledge:

-- OOP Concepts such as Classes

-- Arrays, Loops

-- JavaScript Basics

-- Working with *.js files

 

 

Background:

Many websites rely on Images for the Graphical User Interface (GUI) of their Web Applications. This is great for visual appeal, but when the site consists of mostly images (both large and small) to make up the entire layout, then your visitors download time ends up taking longer. And as all of us should already know, no one likes to wait too long for a site to load without at least a visual indication of its progress.

On average, people with broadband connections will wait up to 10 seconds for a site to load -- which isn't very much time at all!

 

Another problem while the site is loading for the visitor, is that they see the site slowly take shape, as single images are downloaded individually and fitted into the screen so as to form the layout. It would be much more appealing if the site were to load all at once, images and text loaded and in place all ready to go!

 

The solution? An Image Preloader with Progress Bar Status!

 

Great! But how?

 

 

Theory:

Utilizing the Document Object Model (DOM) of HTML with the power of JavaScript, we can access all of our sites images as Objects, giving us access to the Events fired by the Image Objects.

 

On top of that, when we load an Image in JavaScript via the DOM, we point to the location of the Image via a Uniform Resource Locator (URL) just as we would with regular HTML <IMG> tags. This means that the Image gets loaded into the memory of the visitors computer. Now, when we call for an image in our main page like <img src="img/blah.gif">, the relative Image URL is already loaded, and thus the Image gets displayed immediately.

 

Now as I mentioned before, when we load an Image via JavaScript and the DOM, we have access to the Events of that Image Object, and to name a few of those events we have:

 

OnLoad()

OnError()

OnAbort()

 

Pretty straight-forward really; when the Image is completely loaded the OnLoad() event gets called. If an error occurs while loading the Image the OnError() event gets called. And lastly, if the user (visitor) leaves the page (or closes browser) the OnAbort() event gets called.

 

In this tutorial we will only need to deal with the OnLoad() event, however, the other events could be of great use, and should be simple enough for you to implement on your own after reading this tutorial. (I will leave a basic code structure for the extra events in the sample at the end of this tutorial, but I will not be explaining them in great detail. That could be left open for discussion!)

 

The main purpose of implementing the OnLoad() event is to keep track of our loaded images so we can display a Real-Time Progress Bar to our users. The idea here is to keep a counter of how many images have been loaded, so we know our progress. (Hint: You could also track how many Images fail to load via the OnError() event!)

 

Finally, we have to display that progress on the screen, which can be solved with the use of Span Tags and CSS! In this tutorial I will simply lay out 10 boxes (via Span Tags) each with a Grey BackGround Style, and as the progress increases, I will change the style of each consecutive box to a Blue BackGround, giving a visual appearance of a Progress Bar!

 

I hope you were able to follow along thus far, we are going to tackle the actual code next! :D

 

 

Implementation:

All right! We are going to start on the last section of this tutorial where we actually get to build something! (If you feel daunted by the length of this tutorial at this point, know that the longest section lies yet ahead! Fear not, brave reader!)

 

Now, I am going to take you through 3 stages in building our Image Preloader with Progress Bar:

 

1) Writing the Preloader class in JavaScript -- This is the core of our preloader, and where most of the theory from above takes place;

2) Writing the Progress Bar Page -- This is a simple HTML page used soley to display the Progress Bar to our visitors;

3) Putting it all together -- This is where we will implement the Preloader Class into our Progress Bar Page to make it all work!

 

Due to the 'intertwined' nature of the code, it will be difficult to explain, and you may benefit from reading parts of this section more than once after having read it all. Try to remember any parts that confuse you, and come back to it later, after reading more of the tutorial.

 

 

 

Writing the Preloader class in JavaScript:

We start off by making a new file called 'ipreload.js'. This will be our Image Preloader Class File which will contain a single class declaration. If you have never worked with Classes in JavaScript before, they may seem odd at first. This is due to the fact that JavaScript (ECMAScript) lacks full support for user-defined class types. :D But fret not, my friend! I shall explain them anyway! :D

 

(Note: If you already understand classes in JS, you may safely skip the following quoted section)

Classes in JavaScript are declared using the 'function' keyword. Weird? This is because the declaration is used as both the Declaration and the Constructor. All of your member variables to be used in your class should be declared within this Declaration/Constructor using the keyword 'this' followed immedialtely by a dot and then the variable name.  Assignment operations may also take place within the statement.  A full example thus far:

function MyClass(){    this.MyVariable = 0;}

Now, to add methods (or member functions) to the class gets weirder with the involvment of the 'prototype' keyword, as in:

MyClass.prototype.MyFunction = function(){    // Access to the member variable:    this.MyVariable = 1;}

There you go, a working Class in JavaScript with 1 Member Variable, and 1 Member Function!

Now to instantiate an object of that class is as simple as calling the Constructor function with the 'new' keyword, and assigning its value to a variable, as in:

var MyObject = new MyClass();// Call the member function:MyObject.MyFunction();

I hope you were able understood that, please mind my briefness as this is not a tutorial on Classes in JavaScript (that could be an entire tutorial of its own!)

 


Okay, moving on.. Now that we understand classes in JavaScript, we will begin with our 'ImagePreload' Class. I will first show you the completed class and then I will explain how it works, this way you will have reference to what I am writing about.

 

File = ipreload.js:

<!--function ImagePreload( p_aImages, p_pfnPercent, p_pfnFinished ){       // Call-back functions    this.m_pfnPercent = p_pfnPercent;    this.m_pfnFinished = p_pfnFinished;    // Class Member Vars    this.m_nLoaded = 0;    this.m_nProcessed = 0;    this.m_aImages = new Array;    this.m_nICount = p_aImages.length;    // Preload Array of Images    for( var i = 0; i < p_aImages.length; i++ )        this.Preload( p_aImages[i] );}ImagePreload.prototype.Preload = function( p_oImage ){       var oImage = new Image;    this.m_aImages.push( oImage );    oImage.onload = ImagePreload.prototype.OnLoad;    oImage.oImagePreload = this;  // Give the Image Object a Reference to our Class..    oImage.bLoaded = false;       // Custom value added to track state    oImage.source = p_oImage;     // Original Source Path to Image (for later use)    oImage.src = p_oImage;        // Image Object Source Path }ImagePreload.prototype.OnComplete = function(){       this.m_nProcessed++;    if ( this.m_nProcessed == this.m_nICount )        this.m_pfnFinished();    else        this.m_pfnPercent( Math.round( (this.m_nProcessed / this.m_nICount) * 10 ) );}ImagePreload.prototype.OnLoad = function(){       // 'this' pointer points to oImage Object because this function was previously assigned    // as an event-handler for the oImage Object.    this.bLoaded = true;    this.oImagePreload.m_nLoaded++;	// Access our Class with the Reference assigned previously..    this.oImagePreload.OnComplete();}//-->

Okay, we have a class called 'ImagePreload' whose constuctor takes 3 parameters, namely p_aImages, p_pfnPercent and p_pfnFinished respectively.

The first parameter 'p_aImages' is an Array of Strings which holds the URL of all of the images we want to Preload. We will build this array outside of this class later on, and pass it into the class when we instantiate an object of the class.

The second and third parameters are actually Functions (or more precisely, Function Pointers) that we want our class to have access to without being part of the class itself. We will deal more with these later.

 

Now looking into the Constructor function for our class we will see that the last two parameters are being assigned to Member Variables of the class, so that they are stored locally and are available for the class to call as functions later on. They are commented as "Call-Back functions", and that is exactly what they are: They "Call-Back" to the code that "Called" our Class' Constructor/Member Functions. More over, they can be considered Events that are raised by our class. I will elaborate on this further later in this tutorial. Moving on..

 

Next you will see some more Member Variables being declared within the class, namely: m_nLoaded, m_nProcessed, m_aImages and m_nICount. I will try to explain them each briefly, yet adequately each in a single paragraph of their own;

 

Since our class will keep a counter for all of the Images it loads, we will need a Member Variable to hold that counter, starting at 0. The 'm_nLoaded' Member Variable serves this purpose. After each successfully loaded image, 'm_nLoaded' will be incremented by 1.

 

Our class will also keep a counter for the number of Processed Images (meaning the images that our Progress Bar has accounted for) to calculate the Overall Progress. The 'm_nProcessed' Member Variable serves this purpose. This should be unaffected by Image Load Failures from the OnError() events (Be sure to note that if you plan to add error handling to this class).

 

Our class will also be storing the Image Objects in Memory on the visitors machine, so that they are considered "Preloaded", and we will do this by creating an Array, and adding the Image Objects to the Array as the images are loaded. The 'm_aImages' Member Variable serves this purpose. Note that this Member variable starts with 'm_' unlike the parameter with the same name, which starts with 'p_'.

 

Finally, our class will need to know the total number of images it is preloading in order to compute a progress, and yes, the 'm_nICount' Member Variable serves this purpose! We can get this value from the Arrays 'length' property, which returns the number of elements in the array.

 

Okay, so that should explain most of the Constructor function to you, and now we will look at the last part of the code in the constructor function.. Hopefully, you've kept up with me and the reference code above, if not here is the part I am refering to next:

    // Preload Array of Images    for( var i = 0; i < p_aImages.length; i++ )        this.Preload( p_aImages[i] );

This is a basic FOR loop which we will use to walk through the Array of Image URLs that were passed into the function as the First Parameter. We will then pass each individual URL string to our class' Preload() Member Function which handles the actual "Preloading" of each Image Object.

As you can see by now, as soon as you Instantiate the ImagePreload Object passing it the Array of Image URLs, the preload process will start immediately, and within seconds (hopefully) all of your Images will be preloaded!

 

But wait! What about the progress bar?!

Since the ImagePreload class will be taking care of loading all of those images, how will the Progress Bar know what's going on?

 

This is solved by those two "Call-Back" functions I mentioned earlier. Since the Progress Bar itself will be completely seperate code with a seperate responsibility, it will have two functions of its own. One function will update the Progress Bar Display, and the other function will redirect to the main page of your site when the preloading is done!

 

Now, as I mentioned earlier, the two "Call-Back" functions were assigned to Member Variables which means that any function in our class can now call either of those two functions whenever it needs to. Basically, we will use them as Events, so that everytime an image is loaded, the progress is calculated and the Event (Call-Back Function) is called, sending back the current progress! Now since those functions actually belong to (and are coded in) the Progress Bar, then they will get called and Instantly Update the Progress or Redirect the Page Accordingly!

 

Hopefully that made sense to you, either way, I shall explain it in more detail.

In reference to the code above, we should now be looking at the Preload() function declared as:

ImagePreload.prototype.Preload = function( p_oImage )

Recall that this function is executed in the FOR loop in the Constructor of our Class, and is being passed a URL string of the Image to Preload. Looking into the function we notice the first two statements, the first line just instantiates an Image Object (which is part of JavaScript) and the second line adds that Image Object into our Array of Image Objects which we had declared earlier in the Constructor. Memory space is now reserved for this image on the visitors computer!

 

Next, we see a see a statement dealing with the OnLoad() event of the Image object:

oImage.onload = ImagePreload.prototype.OnLoad;

We are basically telling the Image Object to Call a Member Function in our class when the Image is loaded, and our Member Function will be responsible for tracking the progress.

But there is one tricky thing to note about this assignment; the 'ImagePreload.prototype.OnLoad' function now "belongs" to the Image Object, even though the function is implemented in our class. The important point is that the 'this' keyword within our 'ImagePreload.prototype.OnLoad' Member Function will not point to our 'ImagePreload' Object Instance, but rather the Image Object Instance. (Crude Analogy: this is not this anymore, it is that! -_-)

This may seem very confusing at first, but don't give up! It makes sense! Besides, you don't have to understand it, just know that it works and how to use it!

 

Now if you didn't understand what I just wrote, then the next statement won't make much sense to you:

oImage.oImagePreload = this;  // Give the Image Object a Reference to our Class..

Basically, we want the Image Object to have access to our Class. This is used to access the Call-Back functions in our class from within the OnLoad() function which now belongs to the Image Object. Make sense? I hope so, I don't know how else to explain it! :D But don't fret my friend, read further! Maybe it will clear up for you later!)

 

The next few statements are much simpler:

    oImage.bLoaded = false;       // Custom value added to track state    oImage.source = p_oImage;     // Original Source Path to Image (for later use)    oImage.src = p_oImage;        // Image Object Source Path 

The first is just a simple boolean flag to indicate whether the Image Object has been loaded or not, which is set to False by default.

The next two lines are pretty much the same, except that the first one is a custom variable and the second one is actually an Image Object Property 'src', much like in HTML <IMG> Tags. When you assign a a URL to this property it will be interpreted immediately and the actual image will be loaded into the Memory space we had reserved earlier! This is the load process internally, and when then image is done loading the OnLoad() event gets fired calling our OnLoad() Member Function.

The custom variable 'source' is used for referencing the original path & filename of the image (if you should need to) whenever you need to.

 

And that is the Preload() function!! Hopefully, you now understand how the actual Preload process works!

 

We will now move on to the final 2 Member Functions: OnLoad and OnComplete..

 

ImagePreload.prototype.OnLoad = function(){       // 'this' pointer points to oImage Object because this function was previously assigned    // as an event-handler for the oImage Object.    this.bLoaded = true;    this.oImagePreload.m_nLoaded++;	// Access our Class with the Reference assigned previously..    this.oImagePreload.OnComplete();}

Now, since the OnLoad() function belongs to the Image Object, we can directly manipulate the variables we gave it earlier, namely the 'bLoaded' boolean flag. We will set this to true, to indicate that this image object was loaded successfully.

We also need to increment the counter holding the total number of Loaded Images thus far, which is a Member Variable that belongs to the ImagePreload class, and this function doesn't! So, we access the reference we stored earlier as a custom variable in the Image Object. We can now use that reference object to access anything in our ImagePreload class, which the next two statements do; the first of which simple increases the counter, and the second calls our final Member Function 'OnComplete'.

 

ImagePreload.prototype.OnComplete = function(){       this.m_nProcessed++;    if ( this.m_nProcessed == this.m_nICount )        this.m_pfnFinished();    else        this.m_pfnPercent( Math.round( (this.m_nProcessed / this.m_nICount) * 10 ) );}

This function is pretty simple, it belongs to our ImagePreload class and simply increments the counter of Processed Images. (Note: If the # of Processed Images is not equal to the # of loaded images, then some of your imges fail to load. But the progress will still compute correctly!)

 

Next it checks to see if it has processed all the required images, and if so it raises the "Finished" event, which tells the Progress Bar code to redirect to the main page. However, if it is not done loading all of the required images, it will raise the "Percent" event, which tells the Progress Bar to update the display according to the Percent Complete!

(The Percentage is rounded to a single digit number from 1-10, but this could easily be changed to suit your needs).

 

Whew! Take a break! Your done Stage 1 of the Implementation Section! It's pretty much downhill from here! :D

 

 

Writing the Progress Bar Page:

I am going to keep this part of the tutorial a simple as possible, since it only deals with basic HTML tags, and some simple CSS styles for appearance. This is going to be the GUI of the Progress Bar, and most of you will probably change the appearance of it anyway.

 

Basically, you just need an empty webpage (preferably no images, otherwise, what's the point of the Preloader?)

So it could look something like this (keeping it simple):

 

File = index.html:

<html><head><style type="text/css"><!--.OuterBorder{  border:1px solid #426394;   padding: 2px 5px 2px 5px;}.FullDot{  border:1px solid #426394;   background-color:#DAE1EB;   cursor:default;}.EmptyDot{  border:1px solid #426394;   background-color:#F3F6FA;   cursor:default;}//--></style></head><body> <center> <table cellpadding="0" cellspacing="0" border="0" class="OuterBorder">  <tr>   <td>      <span id="sDot1" class="EmptyDot">  </span>       <span id="sDot2" class="EmptyDot">  </span>       <span id="sDot3" class="EmptyDot">  </span>       <span id="sDot4" class="EmptyDot">  </span>       <span id="sDot5" class="EmptyDot">  </span>       <span id="sDot6" class="EmptyDot">  </span>       <span id="sDot7" class="EmptyDot">  </span>       <span id="sDot8" class="EmptyDot">  </span>       <span id="sDot9" class="EmptyDot">  </span>       <span id="sDot10" class="EmptyDot">  </span>   </td>  </tr> </table> </center></body></html>

You'll notice it is just 10 span tags within a bordered table, each span tag representing an 'EmptyDot'. As the progress increases, the 'EmptyDots' will become 'FullDots'.

 

Well, nothing special there, just some regular HTML/CSS stuff.. So, we move on, to the Final Stage!

 

 

Putting it all together:

This stage shouldn't be too tricky either.. First we will have to include or ImagePreload class file into our HTML page, then we will write our 2 functions that will respond to the events raised by our ImagePreload class, as well as a third function to start the whole Loading process rolling! Also, we will add an extra link on the page, that will give the visitor the option to "Skip Preload" and go straight to the main page..

 

First, including the Preloader, which most of you I assume will be familiar with. Simple JS file including:

<script type="text/javascript" language="JavaScript" src="ipreload.js"></script>

Now, we want to create 3 more JavaScript functions inside the <HEAD> tag of the web page, as mentioned earlier. I will first show you the completed HTML file, and then like before, I will explain it all to you, with the code as reference:

 

File = index.html:

<html><head><style type="text/css"><!--.OuterBorder{  border:1px solid #426394;   padding: 2px 5px 2px 5px;}.FullDot{  border:1px solid #426394;   background-color:#DAE1EB;   cursor:default;}.EmptyDot{  border:1px solid #426394;   background-color:#F3F6FA;   cursor:default;}//--></style><script type="text/javascript" language="JavaScript" src="ipreload.js"></script><script type="text/javascript" language="JavaScript"><!--var g_iStep = 0;function OnImgUpdate( iProgress ){       if( (iProgress >= 1) && (iProgress <= 10) && (iProgress > g_iStep) )    {           g_iStep++;        var oSpan = document.getElementById( "sDot" + iProgress + "" );        oSpan.className = 'FullDot';    }}function OnCompletion(){       document.location.replace('main.html');}function StartPreload(){    var szImages = new Array( "image1.gif", "image2.jpg", "image3.png", "etc..." );    // Execute Image Preloader    var oPreload = new ImagePreload( szImages, OnImgUpdate, OnCompletion );}--></script></head><body onload="StartPreload()"> <center> <table cellpadding="0" cellspacing="0" border="0" class="OuterBorder">  <tr>   <td>      <span id="sDot1" class="EmptyDot">  </span>       <span id="sDot2" class="EmptyDot">  </span>       <span id="sDot3" class="EmptyDot">  </span>       <span id="sDot4" class="EmptyDot">  </span>       <span id="sDot5" class="EmptyDot">  </span>       <span id="sDot6" class="EmptyDot">  </span>       <span id="sDot7" class="EmptyDot">  </span>       <span id="sDot8" class="EmptyDot">  </span>       <span id="sDot9" class="EmptyDot">  </span>       <span id="sDot10" class="EmptyDot">  </span>   </td>  </tr> </table> </center></body></html>

Now, the first thing you'll notice, is that there is not much left to do! Yay! I'm exhausted from typing! Okay, going back on track now...

 

You could seperate the CSS and put it in an external *.css file if you prefer, but I kept this tutorial simple, with the use of only 2 files (plus the rest of your website).

 

The first thing to note in the newely added JavaScript code block is:

var g_iStep = 0;

This is a global variable that needs to maintain its value, hence it is declared outside of any specific code block. The reason for this variable is simple; The Progress Bar display in this tutorial only has 10 steps, but you could have 50+/- images. Since the Update Event gets called for every loaded image, then it is unnesseccary to Update the progress bar with every image, instead we track when the Percent value changes, store the new value in the 'g_iStep' variable and Update the display only if the 'g_iStep' variable has increased!

 

This all takes place in the 'OnImgUpdate' function:

function OnImgUpdate( iProgress ){       if( (iProgress >= 1) && (iProgress <= 10) && (iProgress > g_iStep) )    {           g_iStep++;        var oSpan = document.getElementById( "sDot" + iProgress + "" );        oSpan.className = 'FullDot';    }}

Should be pretty straight-forward from what I wrote above. Worth noting though, is the 'oSpan' variable, which refers to one of the HTML <SPAN> tags in the DOM that make up the Progress Bar Display. We can get access to this Span Tag as an Object via the 'document.getElementById()' function which is part of JavaScript. All we need to do, is tell the function the ID of the Span Tag, which we have named successively ranging from "sDot1" to "sDot10". Each ID corresponds to a Progress Interval. Now that we have access to the Span Tag Object, we can change its Style via the 'ClassName' property, which we then change to 'FullDot' so as to indicate a Full Dot, and Progress on the Progress Bar!

 

Well, that takes care of the Progress Bar actually moving! Now we have to Redirect to the Main page of your site once it is complete. Our ImagePreload class will take care of raising the Event when all of the images are loaded, we just need to do something now when that event occurs.

 

This will happen in our 'OnCompletion()' function:

function OnCompletion(){       document.location.replace('main.html');}

Pretty simple really, if you understand the Basics of Javascript. We just Redirect to the Main page of your site (assuming the page is called 'main.html', if not point it to your page). Also, the replace() function has the added benefit of removing the preloader from the history, so people don't click there Back button and go to a Preloader page!

 

 

And finally, where my tutorial draws near to its conclusion, we put it all together in one Simple function:

function StartPreload(){    var szImages = new Array( "image1.gif", "image2.jpg", "image3.png", "etc..." );    // Execute Image Preloader    var oPreload = new ImagePreload( szImages, OnImgUpdate, OnCompletion );}

Now the first thing you will notice, is the Array of Image URLs, these are "Relative" URLs and should point to the actual image files on your webserver that you wish to preload. This script will not work "As Is" unless you point to Your image files in the Array.

 

How ever you build that Array of images is up to you, I personally use PHP to recurse through my /img/ directory making a list of all the Image path/filenames it finds, and then outputs that list into the Preloader Pages Image URL Array above. That would be a tutorial of it's own, so I will save going into detail about that for another day!

 

Next, is the MAin line of execution for our Preloader script.

var oPreload = new ImagePreload( szImages, OnImgUpdate, OnCompletion );

In this one line is where we Instantiate a new 'ImagePreload' Object, passing to its Constructor 3 parameters: the Array of Image URLs, the 'Update' Event Function Pointer and the 'Finished' Event Function Pointer which starts the whole Preloading process in motion!

 

The 'StartPreload' function should be called as soon as the Preload Page loads, so we will call it in the onload event handler of the Body Tag:

<body onload="StartPreload()">

And there you have it! An Image Preloader with Progress Bar Status in JavaScript!

 

So, as the End-Result, we have the 2 completed Files (with the extra stuff I mentioned left in):

 

File = ipreload.js:

<!--function ImagePreload( p_aImages, p_pfnPercent, p_pfnFinished ){   // Call-back routines    this.m_pfnPercent = p_pfnPercent;    this.m_pfnFinished = p_pfnFinished;    // Class Member Vars    this.m_nLoaded = 0;    this.m_nProcessed = 0;    this.m_aImages = new Array;    this.m_nICount = p_aImages.length;    // Preload Array of Images    for( var i = 0; i < p_aImages.length; i++ )        this.Preload( p_aImages[i] );}ImagePreload.prototype.Preload = function( p_oImage ){   var oImage = new Image;    this.m_aImages.push( oImage );    oImage.onload = ImagePreload.prototype.OnLoad;    oImage.onerror = ImagePreload.prototype.OnError;    oImage.onabort = ImagePreload.prototype.OnAbort;    oImage.oImagePreload = this;    oImage.bLoaded = false;    oImage.source = p_oImage;    oImage.src = p_oImage;}ImagePreload.prototype.OnComplete = function(){   this.m_nProcessed++;    if ( this.m_nProcessed == this.m_nICount )        this.m_pfnFinished();    else        this.m_pfnPercent( Math.round( (this.m_nProcessed / this.m_nICount) * 10 ) );}ImagePreload.prototype.OnLoad = function(){   // 'this' pointer points to oImage Object    this.bLoaded = true;    this.oImagePreload.m_nLoaded++;    this.oImagePreload.OnComplete();}ImagePreload.prototype.OnError = function(){   // 'this' pointer points to oImage Object    this.bError = true;    this.oImagePreload.OnComplete();}ImagePreload.prototype.OnAbort = function(){   // 'this' pointer points to oImage Object    this.bAbort = true;    this.oImagePreload.OnComplete();}//-->

File = index.html:

<html><head><style type="text/css"><!--.OuterBorder{  border:1px solid #426394;   padding: 2px 5px 2px 5px;}.FullDot{  border:1px solid #426394;   background-color:#DAE1EB;   cursor:default;}.EmptyDot{  border:1px solid #426394;   background-color:#F3F6FA;   cursor:default;}//--></style><script type="text/javascript" language="JavaScript" src="ipreload.js"></script><script type="text/javascript" language="JavaScript"><!--var g_iStep = 0;function OnImgUpdate( iProgress ){       if( (iProgress >= 1) && (iProgress <= 10) && (iProgress > g_iStep) )    {           g_iStep++;        var oSpan = document.getElementById( "sDot" + iProgress + "" );        oSpan.className = 'FullDot';    }}function OnCompletion(){       document.location.replace('main.html');}function StartPreload(){    var szImages = new Array( "image1.gif", "image2.jpg", "image3.png", "etc..." );    // Execute Image Preloader    var oPreload = new ImagePreload( szImages, OnImgUpdate, OnCompletion );}--></script></head><body onload="StartPreload()"> <center> <table cellpadding="0" cellspacing="0" border="0" class="OuterBorder">  <tr>   <td>      <span id="sDot1" class="EmptyDot">  </span>       <span id="sDot2" class="EmptyDot">  </span>       <span id="sDot3" class="EmptyDot">  </span>       <span id="sDot4" class="EmptyDot">  </span>       <span id="sDot5" class="EmptyDot">  </span>       <span id="sDot6" class="EmptyDot">  </span>       <span id="sDot7" class="EmptyDot">  </span>       <span id="sDot8" class="EmptyDot">  </span>       <span id="sDot9" class="EmptyDot">  </span>       <span id="sDot10" class="EmptyDot">  </span>   </td>  </tr> </table> </center></body></html>

Conclusion:

 

Well, I hope that you have learned something from this tutorial, and maybe even use such a preloader in your web sites!

 

Also note, that this Preloader won't work well with less than 10 images, but in that case you don't need a preloader like this one!

 

Please feel free to comment on this tutorial, if you noticed anything wrong or out of place in this tutorial, please don't hesitate to mention it!

I am interested in all feedback really, I'm curious about what you think of my writing, tutorial, methods used, code, etc.. Thanks!

 

I would have a working example to show, but my web host went down a while back. Sorry!

 

Read part 2 of this tutorial entitled "Extending the Image Preloader with PHP4"

 

Notice from BuffaloHELP:
Edited per request.

Edited by BuffaloHELP (see edit history)

Share this post


Link to post
Share on other sites

Oh. My. Gosh. How long did it take you to write that?!Back on topic. I saw this on a site before, but I was too lazy to check the source to see how they preloaded their images. Anyways, I'm going to try this out on the weekends when I have more time.Good stuff man! Keep it up -_-

Share this post


Link to post
Share on other sites

Was it Mercury-Admin? I had hosting with them a while back, but they have gone down now, and I had originally posted the same tutorial there (that was the first time I posted it). Unfortunately for me, when their servers went down, I lost the original tutorial I posted, and I had to rewrite this one again from scratch.. Took about 2.5 hours today! -_-Did you read it? What did you think?

Share this post


Link to post
Share on other sites

Did you read it?  What did you think?

137863[/snapback]

To be honest, no, I did not read it, but I will read it over the weekend or some other time when I have...time. Too much school work right now -_-

Share this post


Link to post
Share on other sites

I don't do codings well but to a novice user such as myself, would it not be easier to make a file called "preload.js" with the following code?

img1 = new Image();	img1.src = "images/nameofIMAGE1.jpg";		img2 = new Image();	img2.src = "images/nameofIMAGE2.jpg";		img3 = new Image();	img3.src = "images/nameofIMAGE3.jpg";		img4 = new Image();	img4.src = "images/nameofIMAGE4.jpg";		img5 = new Image();	img5.src = "images/nameofIMAGE5.jpg";
And just call "preload.js" from your <BODY> tag just like any other JavaScripts? This not only works with any amount of array, short or long, but I guess I see the disadvantage if you have growing number of images. But it's easier for me to edit on this script.

Share this post


Link to post
Share on other sites

Technically, that is exactly what my code is doing, but I wrapped it in a class so as to provide Events used for generating a Progress Bar for its display.The code you posted will not give any visual indication of its progress, which was one of the problems solved by my tutorial.It comes into play mainly when you have alot of images; with your suggested method the user will see nothing for a while until all images are loaded, whereas with my suggested method they will see a Dynamic Real-Time Progress Bar.Either way, both methods work, and it boils down to opinion really.. Which method do you want to use? It is up to you! -_-

Share this post


Link to post
Share on other sites

I did, but my previous hosting (at Mercury-Admin.com) has gone down, so my site went with it... I have it backed up of course, and when I get new hosting I will put the site back online, which includes a working sample suited to my site, which loads approx. 60+ images.. (Although a portion of it is in PHP to dynamically load all the image URLs into the array)The tutorial code is however, all Client-side Javascript + HTML really, so you could test it out rather quickly if you have say 10 or more images you could use to make a mock-up test environment..As soon as I get new hosting and get my site back online, I will post a sample link to it.. Sorry for not having a Demo though, I know they are always nice!Also, I will write another tutorial shortly, about the PHP portion I mentioned above..

Share this post


Link to post
Share on other sites

Technically, that is exactly what my code is doing, but I wrapped it in a class so as to provide Events used for generating a Progress Bar for its display.

The code you posted will not give any visual indication of its progress, which was one of the problems solved by my tutorial.

 

It comes into play mainly when you have alot of images; with your suggested method the user will see nothing for a while until all images are loaded, whereas with my suggested method they will see a Dynamic Real-Time Progress Bar.

 

Either way, both methods work, and it boils down to opinion really.. Which method do you want to use? It is up to you!  -_-

137923[/snapback]


AH! Well, since my site has one main index with two links I have my preload.js called in index.htm. And when the visitor decides to choose, let's say door 1 or door 2, the images are already preloaded before the visitation. I made it so for the simple factor of surfing pleasure. And since my graphics and images were small sized that I preloaded the entire image content even before any visitor views that page. It's like instant load. Therefore I personally would not need the status bar showing what images are being loaded. But now that you mention it my coding is very elementary and does not tell me what is going on. I am going to utilize your coding for my next project. Thank you for your post.

 

function PreloadImages() { if (document.images) { var imgFiles = PreloadImages.arguments; var preloadArray = new Array(); for (var i=0; i<imgFiles.length; i++) { preloadArray[i] = new Image; preloadArray[i].src = "icons/" + imgFiles[i] + ".gif"; } } }  PreloadImages(img#1, img#2, img#3, etc);

This was one of the codes I found on the web. Interesting condensation.

Share this post


Link to post
Share on other sites

very well put together tutorial, a bit long, but the longer the better, that way you can understand it all.i am going to have to try this sometime soon, it looks quite useful. thanks

Share this post


Link to post
Share on other sites

Glad to hear you guys like it, thanks!

I finally have a web host again, Xisto! :(

So I have posted a working sample of this script on my site. The sample is just a rough copy sample, once I get my site integrated with Xisto the sample will be a part of my actual site.

View the Sample Progress Bar Here!

Enjoy! :(

Share this post


Link to post
Share on other sites

Glad to hear you guys like it, thanks!
View the Sample Progress Bar Here!


Hi,

Very nice tutorial; much appreciated. In particular I like the CSS progress bar.

One minor problem though. The sample link works just fine in Firefox and IE, but doesn' seem to be working properly in Safari (Mac). According to the browser status bar, it it is pre-loading the images, although no visual progress is shown in the progress-bar. After pre-loading is done, it just stays on the pre-loading page. The only way to advance is by clicking the "Skip Intro" link.

Any ideas?

Kai

Share this post


Link to post
Share on other sites

Thanks very much for this tutorial. I have seen others but thay have not worked as well or look as good as this script. I am astounded you are willing to provide this script for free, as I have seen others on the Internet costing upwards of $10. Thank you very much and good luck with any more coding you do! :rolleyes:

Share this post


Link to post
Share on other sites

One minor problem though. The sample link works just fine in Firefox and IE, but doesn' seem to be working properly in Safari (Mac). According to the browser status bar, it it is pre-loading the images, although no visual progress is shown in the progress-bar. After pre-loading is done, it just stays on the pre-loading page. The only way to advance is by clicking the "Skip Intro" link.
Any ideas?


Thx for the input and I'm glad you liked it for the most part, but I have never had the opportunity to test or even view this script on a Mac. I am guessing Safari handles the DOM differently than other browsers... Now that I know there is a problem with Mac's Safari browser processing my script I will look into resolving the issue (and here I thought it worked perfectly! lol).

I am glad you pointed out the actual problems for me, which makes fixing it one step easier! I will reply as soon as I figure out a solution. Hopefully you can test it out again for me on your Mac Safari!! :lol:


Thanks very much for this tutorial. I have seen others but thay have not worked as well or look as good as this script. I am astounded you are willing to provide this script for free, as I have seen others on the Internet costing upwards of $10. Thank you very much and good luck with any more coding you do! :rolleyes:


I couldn't imagine charging people money for my tutorials (they probably wouldn't get read!), I mainly write them so that I can add them to my Resume/portfolio, maybe they will help land me a job!

I'm especially glad to see such positive feedback from this tutorial (makes me want to write more)!

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×
×
  • Create New...

Important Information

Terms of Use | Privacy Policy | Guidelines | We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.