Jump to content
xisto Community
SystemWisdom

Extending The Image Preloader With Php4 Dynamically adds your images to Preloader

Recommended Posts

Tutorial: Extending the Image Preloader with PHP4, by Rob J. Secord, B.Sc. (SystemWisdom)

 

Second Tutorial in a Series of 2 Tutorials! Be sure to have read the First One here: "Image Preloader With Progress Bar Status"

 

 

See a working Sample of this Script!

(Note: Preloads 100 images, some images are larger than others, and may take awhile for some people.)

 

 

Description:

A Tutorial for Extending the Image Preloader with PHP4 to Dynamically Populate the Array of Preloaded Images. This tutorial is the second in a series of 2 tutorials, and assumes that you have read the first tutorial: "Image Preloader With Progress Bar Status".

 

 

Intended Audience:

Beginner to Intermediate Web Developers.

 

Assumed knowledge:

-- Tutorial 1: "Image Preloader With Progress Bar Status"

-- Recursion Basics

-- Strings, Arrays, Loops

-- PHP4

 

 

Background:

In the last tutorial I wrote about building a Dynamic Real-Time Image Preloader with Progress Bar Status using only Client-Side code (namely JavaScript + HTML). The Preloader worked by creating an Array of Image URLs and passing that array into the Preloader class.

 

The problem is that you have to manually add your Image URLs to the Array, and everytime you add/remove an image, you would have to add/remove it from the Array also. Borrrrring..

 

In this tutorial, we are going to Extend the ImagePreloader with some Server-Side code (namely PHP4, but you could use any language you want, really). We will be altering the 'index.html' page; renaming it to 'index.php' and adding PHP4 code to search our Image Directory and dynamically build an array of all the Images for us!

 

Now you don't have to worry about editing the Preloader array at all! You could practically forget about it, once you have it installed!

 

 

Theory:

We will start by creating a single directory to hold all of our images on our web server. We will call this the Image-Root folder for the rest of this tutorial. Within this directory you may place all of your images and/or sub-folders with more images.

 

We will then use PHP4 to walk through all of the images in all of the sub-folders for us. You could easily extend this tutorial by restricting certian images/sub-folders from being preloaded, but I will leave that open for you, as that would depend on your images!

 

Within each folder (from the Image-Root folder), we will use PHP4 to check every entry in the folder (this could be an image, a sub-folder, any other file) and then determine what to do with each entry found.

If the entry is an image we will add its Path & Filename to our Array of images, which will serve as the Image URL to preload.

If it is a sub-folder we will recursively search that sub-folder in the exact same way.

Any other file(s) will be ignored, since they will not be preloaded.

 

Once we have completed searching the Image-Root directory for Images and building an Array of Image URLs, we will then output that Array into our Client-Side Preloader code. Since the Client-Side Preloader code also expects an array, we will have to build that array's code dynamically using simple Strings in PHP4. Then it is all ready to go!

 

Your server will then send the completed Preloader Code to the visitors browser, which will then begin preloading all of the Images for your site!

 

To demonstrate the simple recursion, I will be using the following sample directory structure for our example web-server:

 

-- index.php

-- ipreload.js

-- images

????[/tab]+--- sub_dir1

????|????|-------- Image1.gif

????|????|-------- Image2.gif

????|

????+--- sub_dir2

????|????|-------- Image3.gif

????|????|-------- Image4.gif

????|

????|--- Image5.gif

????|--- Image6.gif

[tab]|--- Image7.gif

 

 

The Bold entries are Folders, and the Italic entries are Files.

Now, imagine those are the real file and folder names, as I may use some of those names in examples for the rest of this tutorial.

 

 

Implementation:

 

I will start off, by showing you the completed Source Code to the Progress Bar page from our last tutorial (we will not be editing the 'ipreload.js' file in this tutorial at all, but you still need it as in the last tutorial!).

 

If you recall, our 'index.html' file looked like this:

 

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>

We will be adding only two sections to this code in this tutorial. But first, we must rename the file to 'index.php' without the single-quotes. Now you have a PHP file! Let's add some PHP4 Code to it.

 

We begin by adding a PHP code block to the very top of the page, where we will add the bulk of our code. I will first show you the completed code block and then I will explain how it works, this way you will have reference to what I am writing about. After I explain it, I will add it to the completed code from the first tutorial so you see how it fits in.

 

The PHP4 code block:

<?php// Image-Root Directory..$g_szImagesDir = 'images/';// Global Variables used by 'BuildFileList' function...$g_szFileList = array();$g_iFileCount = 0;// Build File List of Imagesfunction BuildFileList( $szDir ){   global $g_iDepth, $g_szFileList, $g_iFileCount;    $oDirHandle = opendir( $szDir );    while( false !== ($szFile = readdir( $oDirHandle )) )    {        if( $szFile == '.' || $szFile == '..' ) continue;        $szCurrPath = $szDir.'/'.$szFile;        if( is_dir( $szCurrPath ) )        {            BuildFileList( $szCurrPath );        }else        {            if( (false !== strpos($szFile, '.jpg')) || (false !== strpos($szFile, '.gif')) || (false !== strpos($szFile, '.png')) )            {                $g_szFileList[$g_iFileCount++] = str_replace( './', '', $szCurrPath );            }        }    }    closedir( $oDirHandle );    return;}// Start the search for Images!BuildFileList( './' . $g_szImagesDir );?>

The first thing you should note, are the 3 globally defined variables; g_szImagesDir, g_szFileList and g_iFileCount.

 

The first one 'g_szImagesDir' will be a string containing the path to and the name of the Image-Root folder. In our sample directory structure from above it would be: 'images/'. This variable will not be used by our 'BuildFileList' function, instead it will be passed into the function as the starting parameter.

 

The 'g_szFileList' variable is our Array which will hold all of our Image URLs to be preloaded.

 

And finally, the 'g_iFileCount' will count how many Images have been found and added to our 'g_szFileList' Array.

 

Next you will notice a PHP4 function called 'BuildFileList' which is the main focus of this tutorial. This function will recursively search our Image-Root directory and build a PHP4 Array of all of the Image URLs. Later on we will use the PHP4 Array to build our JavaScript Array for the visitor to download. The JavaScript Array will then be used on the visitors machine to Preload the images for your site!

 

 

Now, let's jump into the code for the 'BuildFileList' function.

The first thing you should notice about this function is that it accepts 1 parameter indicating the Directory (or Folder) to search in. To start off with, we would pass our Image-Root directory into this function, as you will see later. Knowing that, we can assume the starting value of the 'szDir' variable will be 'images/' and that's where the function will start searching for images.

 

The next line is an important one; it gives the function access to the globally defined variables that our function will require. These variables are not declared within the function because we want the values of those variables to maintain their state with each call to our function.

 

Now that our function is declared and has access to 2 of the previously defined global variables, we can start implementing the function itself. What is important to note before going any further, is that this function will be used "Recursively", meaning it will call itself. If you don't understand recursion I suggest you read up on the subject and come back to this tutorial once you have a good understanding of the concept. There are many good resources on the Internet to learn about recursion.

 

Now, the first thing we will need to do, is open a Directory Handle to the current folder (namely 'szDir' which at first will contain 'images/'). This is acheived with the built-in PHP4 function called 'opendir()'. We simply tell the PHP function what directory to open, and it will return a Directory Handle for us to use. When we are done using the Directory Handle we simpley call the built-in PHP function 'closedir()' to close it.

 

If you are having trouble following from the code above, we open the Directory Handle in this line of code:

$oDirHandle = opendir( $szDir );

Now that we have a Directory Handle, we can use that Directory Handle to read the entries found in the Directory using the built-in PHP function 'readdir()' which will return each directory entry with each successive call. What I mean is, every time we call the readdir() function it will return the next entry in the directory, until finally it returns False indicating that there are no more entries in the current directory.

 

So, if we look at the next line of code (starting with 'while') you'll notice we are using the 'readdir()' function which I just mentioned. First, we call the 'readdir()' function passing it the Directory Handle we created earlier. The 'readdir()' function then returns an entry in the directory which we store as 'szFile'. If this entry is Not Equal to Boolean False, then it is a valid entry, and the code continues inside of the 'while' loop. If however, the entry IS equal to Boolean False, then the 'while' loop quits, and the Directory Handle gets closed. The function then returns control to the calling statement.

 

Now, assuming the entry was valid (and from my sample directory structure given above it would be 'sub_dir1'), we would then check to see if the entry is equal to either "." or ".." which are Virtual Directories that point to the Current Directory and the Parent Directory respectively. If the entry is a Virtual Directory to either of the Current or Parent directories then we consider them invalid directories for our search, calling the 'continue' statement to search again.

 

The code for this looks like:

if( $szFile == '.' || $szFile == '..' ) continue;

If at this point, the directory entry is still valid, then it is either a sub-folder or a file. In either case, we append the entry name to the current directory name in proper format (resulting in either a sub-directory or a filename + path) as seen in the following code:

$szCurrPath = $szDir.'/'.$szFile;

Next we can determine whether the entry is really a sub-folder using the built-in PHP function 'is_dir()' which returns True if the entry is a Directory and False if the entry is not a Directory. If the entry IS a directory, then we simply call ourself through the method of recursion, which will go through the whole process again, but in the newly found sub-folder. This can be seen here:

    if( is_dir( $szCurrPath ) )    {        BuildFileList( $szCurrPath );  // <----  Recusive call..    }else    {        // [...ignore for now...]    }

As you can see, the 'BuildFileList' function is calling itself! But this time, it is passing a new directory (a sub-folder within the current directory) as the Directory to search from. When this happens, the script starts executing the whole function again, but with a new directory to search from. And when the function is done, it comes right back to this point in itself and continues executing the rest of the orignally called function.

 

However, if the entry we found is NOT a sub-folder then the 'is_dir()' function would have returned False and we would have entered the 'else' block of the if statement, which looks like:

    if( is_dir( $szCurrPath ) )    {        // [...ignore for now...]    }else    {        if( (false !== strpos($szFile, '.jpg')) || (false !== strpos($szFile, '.gif')) || (false !== strpos($szFile, '.png')) )        {            $g_szFileList[$g_iFileCount++] = str_replace( './', '', $szCurrPath );        }    }

At this point, we know that the entry we found is not a Virtual Directory or even a Physical Directory, so we proceed to assume it is a valid file. But we don't know what type of file it is, and so we check the File Extension to determine if the file is an Image File used on websites.

Since the 'szFile' variable is a string containing the entry name, we can search that string using PHP4 to find and compare the file extension. We use the built-in PHP function 'strpos()' to server this purpose.

We tell the 'strpos()' function what string to search, and what string to search for (in this case, a file extension), and if the function returns Boolean False then the file extension we searched for was not found. Otherwise, the 'strpos()' function will return spot (or starting index) that the extension was found in the search string. The fact that it doesn't return False is enough for us to proceed.

 

For example, we are searching the 'szFile' string for the File Extension '.jpg' and if the result is Not Equal to Boolean False then the File Entry is a Jpg Image File:

        if( false !== strpos($szFile, '.jpg') )        {            // [...ignore for now...]        }

Hence, if the File Entry is a valid Image File (.jpg, .gif or .png), then the full path and filename are added to our Image URL Array ('g_szFileList') which we created globally. We also increment (add 1 to) our 'g_iFileCount' variable, to keep track of how many Image URLs we have.

A good point to note is the removal of any unneccessary Virtual Current directory entries that may have been added to the file path using, before adding the Image URL to the Array. Our end result for the File Extension Test:

        if( (false !== strpos($szFile, '.jpg')) || (false !== strpos($szFile, '.gif')) || (false !== strpos($szFile, '.png')) )        {            $g_szFileList[$g_iFileCount++] = str_replace( './', '', $szCurrPath );        }

And finally, once the function is ready to exit, the 'closedir()' function is called to clean up our Directory Handle that we used, as in:

closedir( $oDirHandle );

And that concludes the 'BuildFileList' function. To recall; We pass in the Image-Root directory to search and the function recursively searches all sub-directories building an Array of valid Image File entries found.

 

 

Now that we have our Global Variables and our Function declared, we can call the function passing in our Image-Root directory, and when the function is done we will have an Array of Image URLs, which is done in one line of code:

BuildFileList( './' . $g_szImagesDir );
The './' denotes that the Image-Root directory resides in the Current Directory from which this script is executed.

 

 

Now that we have completed the first section of this tutorial, I will show you a sample of the 'index.php' up to this point so far. We will use this as reference for the last part of the tutorial, which fortunately is alot shorter!

 

File = index.php

<?php// Image-Root Directory..$g_szImagesDir = 'images/';// Global Variables used by 'BuildFileList' function...$g_szFileList = array();$g_iFileCount = 0;// Build File List of Imagesfunction BuildFileList( $szDir ){   global $g_iDepth, $g_szFileList, $g_iFileCount;    $oDirHandle = opendir( $szDir );    while( false !== ($szFile = readdir( $oDirHandle )) )    {        if( $szFile == '.' || $szFile == '..' ) continue;        $szCurrPath = $szDir.'/'.$szFile;        if( is_dir( $szCurrPath ) )        {            BuildFileList( $szCurrPath );        }else        {            if( (false !== strpos($szFile, '.jpg')) || (false !== strpos($szFile, '.gif')) || (false !== strpos($szFile, '.png')) )            {                $g_szFileList[$g_iFileCount++] = str_replace( './', '', $szCurrPath );            }        }    }    closedir( $oDirHandle );    return;}// Start the search for Images!BuildFileList( './' . $g_szImagesDir );?><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, you should be able to notice that the new code block we have just added doesn't interact with the old page from the previous tutorial in any way! Not yet, at least.

We will now use our PHP Array of Image URLs to populate the JavaScript Array of Image URLs, completing the Dynamic Image Preloader with Progress Bar Status!

 

We start, by adding another PHP code block to our 'index.php' page, but not at the top like before, rather, in the middle of our JavaScript Array!

Since PHP outputs text to the source code of your HTML file, we will output our Array as text into our JavaScript source code for the visitor to download.

 

We will start this last section by looking at the completed code block all alone so that you may reference it as I go along:

<?php        for( $i = 0; $i < $g_iFileCount; $i++ )        {            if( $i == ($g_iFileCount - 1) )                echo '"' . $g_szFileList[$i] . '"';            else                echo '"' . $g_szFileList[$i] . '",';        }?>

You will notice it is a simple FOR Loop that iterates through all of the Image URLs in the PHP Array 'g_szFileList'. It is for this purpose that we kept track of how many Images we had in the Array using the global variable 'g_iFileCount'.

 

Now before we look at how this is implemented, it is good to understand what we are trying to output, which is basically a series of comma-seperated quoted strings, as in:

 

"sting1", "string2", string3", "etc"

 

Of course, the strings themselves are the Image URLs, so all we have to do issurround each Image URL in Quotes ("...") and seperate them with commas! So for each iteration of the FOR loop, we could just output either: A quoted string + a comma; OR: A comma + a quoted string.

 

Now, if you choose to output A quoted string + a comma, then the very lasted quoted string should NOT have a comma following it, right? (look at example just above..).

 

But, if you choose to output A comma + a quoted string, then the very first quoted string shouldn't have a comma in front of it, right? (again, look at example just above..).

 

So, we will choose (for this tutorial) to output: A quoted string + a comma, during each iteration. Which means (as previously stated) that we must take care NOT to output a comma after the very last quoted string. We achieve this with a simple IF statement that checks whether the current Array Index is Equal to the Total Number of Image URLs in our Array (which is stored in the 'g_iFileCount' variable. But don't forget, Arrays are indexed starting from 0 not 1, so we must minus 1 from the 'g_iFileCount' variable when comparing, as in:

    if( $i == ($g_iFileCount - 1) )

This checks to see if the current Array Index is equal to the Total Number of Image Files minus 1. If so, then we just output the quoted string, otherwise we output the quoted string + a comma, as in:

        for( $i = 0; $i < $g_iFileCount; $i++ )        {            if( $i == ($g_iFileCount - 1) )                echo '"' . $g_szFileList[$i] . '"';            else                echo '"' . $g_szFileList[$i] . '",';        }

You may have to look carefully at the quotes in the above example; the single quotes are PHP and the double-quotes are the output.

 

Now that we know what we are outputting and how we are outputting it, we can place this PHP code block in the correct spot in our 'index.php' page. Looking at the examples provided above, I am sure you could figure out where that spot would be, but in either case, I shall show you:

function StartPreload(){   var szImages = new Array( <?php        for( $i = 0; $i < $g_iFileCount; $i++ )        {            if( $i == ($g_iFileCount - 1) )                echo '"' . $g_szFileList[$i] . '"';            else                echo '"' . $g_szFileList[$i] . '",';        } ?> );   // Execute Image Preloader   var oPreload = new ImagePreload( szImages, OnImgUpdate, OnCompletion );}

Notice it is placed directly inside of the 'Array()' function as its parameters, thus creating the required JavaScript Array used to Preload the images on the visitors machine!

 

 

Putting it all together, we have:

 

 

File = index.php

<?php// Image-Root Directory..$g_szImagesDir = 'images/';// Global Variables used by 'BuildFileList' function...$g_szFileList = array();$g_iFileCount = 0;// Build File List of Imagesfunction BuildFileList( $szDir ){   global $g_iDepth, $g_szFileList, $g_iFileCount;    $oDirHandle = opendir( $szDir );    while( false !== ($szFile = readdir( $oDirHandle )) )    {        if( $szFile == '.' || $szFile == '..' ) continue;        $szCurrPath = $szDir.'/'.$szFile;        if( is_dir( $szCurrPath ) )        {            BuildFileList( $szCurrPath );        }else        {            if( (false !== strpos($szFile, '.jpg')) || (false !== strpos($szFile, '.gif')) || (false !== strpos($szFile, '.png')) )            {                $g_szFileList[$g_iFileCount++] = str_replace( './', '', $szCurrPath );            }        }    }    closedir( $oDirHandle );    return;}// Start the search for Images!BuildFileList( './' . $g_szImagesDir );?><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( <?php        for( $i = 0; $i < $g_iFileCount; $i++ )        {            if( $i == ($g_iFileCount - 1) )                echo '"' . $g_szFileList[$i] . '"';            else                echo '"' . $g_szFileList[$i] . '",';        } ?> );   // 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!

 

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!

 

 

See a working Sample of this Script!

 

:(

Share this post


Link to post
Share on other sites

Wow, the sample took a long time to load!As always, awesome tutorial! I don't have the opportunity to try it out yet, but I will on the weekends.I think it'll be cool if you show the images that were preloaded instead of displaying the messages...

Share this post


Link to post
Share on other sites

Yeah, the images take a while to load because there are so many, roughly 100 Images that are preloaded in the sample.But the only reason I didn't show the images afterward is because the images are actually the GUI to my site, and once I get my site online again you will see all of the images in place on my site, instead of the plain text page I have at the end of it now.Sorry 'bout that, I should have my site online soon, and then these links will automatically point o the right preloader and you will see my site!!I hope you enjoy the tutorials when you find the time to read and test them out!

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.