Press enter to skip the top menu

JavaScript

Photo Galleries

Learning Outcomes

Go to top

Introduction

We have already included images into web pages using the format

<img alt=”Unable to load image” src=”myImage.jpg”/>

In this case the image that is to be displayed in our image holder is determined by the scr attribute of that holder. In our example here the image will be 'myImage.jpg'.

For showing a single image this is all that we need. If, however, we wish to be able to alter that image interactively, then an option is to use JavaScript.

You will have seen plenty of JavaScript controlled image displays one the WEB. Many websites have home pages where a series of images are being displayed one after the other. Many of those are JavaScript controlled. An example is Flickr an example of which is shown below.

tiger image on Flickr
Fig 1

In this example you have two options of viewing the photographs. The arrowheads at the left and right of the screen allow you to move sequentially through the collection in either direction. The series of small images below the tiger are thumbnails of actual larger imges and clicking on any of those thumbnails will instantly show the larger image on the screen. We will be showing a version of this form of display. Another option would be for the images to automatically appear on the screen for a given time before bening replaced by another.

Fig 2 below shows the images that we shall be using for this demonstration.

Images used in this exercise
Fig 2

If you wish to follow along with this exercise you need to pick a number of digital images that you want to display. For each of those images you also need to create a thumbnail copy. In this copy select a square area of the main image and save the selected square as a separate file with a width of 100 pixels. These images will then be displayed in a sidebar on the left side of the screen and clicking on any one of them will display the appropriate image

Go to top

A Manual Gallery

Below are the three documents that makes up our image gallery. The CSS file below is farily sparse in places, especially when styling images. The reson for this is that most of the styling for images will be done by the JavaScript code and not CSS.

Listing 1
                        body{background-color: #444}
                        aside{
                            width:9%;
                            border: thick solid black;
                            border-radius: 15px;
                            display: inline;
                            float: left;
                        }
                        article{
                            width: 89%;
                            display: inline;
                            float: right; 
                            }
                        img{
                            display: block;
                            margin-left: auto;
                            margin-right: auto;
                        }
                        aside img{
                            max-width: 100px;
                            width: 80%;
                            margin-bottom: 10px;
                            border-radius: 5px;
                        }
                        article img{
                            border-radius: 15px;
                        }
                    

For the next few paragraphs we shall be simultaneously discussing Listing 1 and Listing 2 as well as the image between them: Fig 2. This is the wireframe that we will use to build the structure of the image gallery.

On the left is a vertical block containing small icons. Those are thumbnails of the actual images we wish to show. To the right and taking up most of the remaining space is the block where we display our images.

Clicking on any of the icons in the left column will cause the corresponding image to appear in the space to the right.

A wireframe layout of the photo gallery page.
Fig 3

Next we look at how the above relates to our HTML code below.

Listing 2
                        <html xmlns="http://www.w3.org/1999/xhtml">
                           <head>
                              <link href="Photo%20Gallery.css" type="text/css" rel="stylesheet">
                              <script src="Photo%20Gallery.js" type="text/javascript"></script>
                           </head>
                           <body>
                              <script type="text/javascript">
                                 preloadimages();
                              </script>
                              <aside id="WideScreen">
                                <img src="Goroka Composite-small.jpg" onclick= "showImage(0)"/>
                                <img src="Goroka solo-small.jpg" onclick= "showImage(1)"/>
                                <img src="manus dancer-small.jpg" onclick= "showImage(2)"/>
                                <img src="Morobe Bilas-small.jpg" onclick= "showImage(3)"/>
                                <img src="manus%20trio1-small.png" onclick= "showImage(4)"/>
                                <img src="Tari1-1-small.png" onclick= "showImage(5)"/>
                                <img src="Central%203-small.png" onclick= "showImage(6)"/>
                                <img src="Taro1%20Thumbnail.png" onclick= "showImage(7)"/>
                                <img src="White%20Flower%20Thumbnail.jpg" onclick= "showImage(8)"/>
                               </aside>
                              <article>
                                 <img  id="mainImage" alt="" src="#"/>
                               </article>
                           </body>
                        </html>
                    

In Listing 2 we will begin by examining lines 10 to 20. This is an <aside> block and contains nine images. We also see that each of them has an onclick() property. In other words they all cause the same function to run, i.e. showImage() except that each one is passing a different parameter value to it.

Now checking Listing 1, lines 2 to 8 we find that our <aside> is narrow, only 9% of the width of the page, and that it floats to the left. This is the narrow column to the left of Fig 1 and the images in it are the icons that we discussed.

Lines 21 to 23 is an <article> element and contains only one blank image holder with an id of 'mainImage'.

The idea of an <img> may appear strange, but the element and the image that it holds are two different items. If you think of the <img> as a picture frame, which is simply wood and glass. It is of no use until a picture is fitted inside it. It is the same with the <img> element and the image that it holds. So currently at line 20 we have the equivalent of a blank picture frame.

Listing 3
                         arr=['Goroka%20Composite.png','Goroka%20solo.jpg','manus%20dancer.jpg','Morobe%20Bilas.jpg','manus%20trio1.png','Tari1-1.png','Central%203.png','Taro1.png','White%20Flower1.png'];
                         var imageArray=[];
                         function preloadimages()
                         {   
                             for (var i=0; i < arr.length; i++)
                             {
                                 imageArray[i]=new Image();
                                 imageArray[i].src=arr[i];
                             }
                         }
                         function showImage(par)
                         {  
                            var intImageHeight=imageArray[par].height;
                            var intImageWidth=imageArray[par].width;
                            var sngImageProportion=intImageWidth/intImageHeight;
                            var intWindowHeight=window.innerHeight;
                            var intWindowWidth=window.innerWidth;
                            var sngWindowProportion=(intWindowWidth*0.89)/intWindowHeight;
                            var styleText="";
                            if(sngImageProportion>sngWindowProportion)
                               styleText="width:"+ (window.innerWidth * 0.87) +"px";
                            else
                               styleText="height:"+ (window.innerHeight *0.95) +"px";
                            document.getElementById("mainImage").setAttribute("style",styleText);
                            document.getElementById("mainImage").src=imageArray[par].src;
                         }
                    

The first item in the JavaScript file is the array arr[] at line 1. It contains the names of nine .jpg or .png files. Since the files have no folder predending them then we know that the files reside in the same folder as the HTML, CSS and JavaScript documents.

If you compare the filenames with those of the icons in Listing 2 you will notice that the names are the same except that those in Listing 2 has the word 'small' or 'thumbnail' appended to them. This is to distinguish them from the full size files that are to be displayed in the main part of the gallery window.

Note that the array arr[] does not contain any file data. It only contains the names of the files themselves. To get the actual file contents and not their names we need another array. This array, imageArray[], is declared at line 2. Currently it is empty. It is populated only when the function preloadImages() is run.

So when does the function preloadImages() run? To answer this we go back to listing 2 and look at lines 7 to 9. Those are immediately after the <body> block. Therefore they are the first lines that get executed when we open up the web page. The only activity that happens in those line is to call the function preloadImages().

Now let us get back to Listing 3, lines 5 to 9. This is a for loop that iterates from zero to one below the length of the array arr[]

When the loop starts the counter i will have a value of zero and thus the first element of imageArray[] will have a blank image container assigned to it at line 7.

At line 8 the actual contents of the file is read and then stored in the container.

The counter i is now incremented to 1 and the contents of the second image is read into the array in the same as the first one.

This process continues until all of the images' data is read into the array.

Our next task now is to look at how this data can be fransferred from the arry onto the screen for the viewer to see.

This is done in the function showImage(). However, before we examine it we first need to look at how the proportions of a web page are measured.

Fig 4

All HTML pages are inside a browser. This browser has a border along its four sides. It also has a number of bars at the top and may have a status bar at the bottom. All of those items reduce the amount of space available for us to position images, text boxes and other elements we put on a web page. Therefore when deciding on the size of an image that we wish to position on a browser we must be aware of the amount of space available, espcially the width and height of the windows.

JavaScript comes to our aid here, in that it provides us with four variables that give us the requierd measurements we need. These are:

Fig 4 above illustrates the difference between the inner and outer versions of the variables. For the purpose of calculating widths of elements to place inside a window, we use the inner measurements.

With that let us look at how our images are sized and positioned within our gallery. For this we fist go to Line 11 of Listing 2. This line calls the function showImage() and passes the value zero to it as a parameter. Now we examine showImage() itself.

This spans lines 11 to 26 of Listing 3. At line 11 the function receives its parameter through the par. Following from our example above the value of par should be zero. With this value then, let us look at lines 13 and 14.

These two lines read the height and width of the image stored at imageArray[0] and stored them in the local variables intImageHeight and intImageWidth

Fig 5: Windows explorer showing the width and height of an image. We cannot get those values using either HTML or CSS, but JavaScript can access them.

At line 15 the orientation of the image is determined by dividing its width by its height. If it is less than zero then the image is protrait shape, otherwise it is landscape shape.

Lines 16 to 18 determine the orientation of the window itself using its internal dimensions. At line 18 the orientation of the window itself is calculated but in a slightly different manner to how the image's orientation was calculated. Here only 87% of the window's width is used. This is because we cannot use the full width of the window since the column of buttons already take up 9% of it.

Lines 20 to 23 determine how the image is to be sized so that it can be fully shown on the gallery window. If the image proportion is greater than the window proportion then the image is styled as being 87% of the window's width at line 21, otherwise at line 23 it is styled as being 95% of the window's height. At either line 21 or line 23 these styling data are stored in the text variable styleText

At line 24 the blank image holder that we met at line 22 of Listing 2 is now styled using the contents of the variable styleTextt while line 25 copies the image data into the newly styled holder.

Below is an example of our completed gallery.

Follow this link for a full screen rendering of the Photo Gallery

Go to top

Auto Gallery

Most of the code here is already familiar to you so we shall be skipping most of it and concentrating on the unfamiliar code.

Listing 4
                    .imageSyle{
                        height:100%;
                        display:block;
                        border:4px orange solid;
                        margin-top:10px;
                        margin-right:auto;
                        margin-left:auto;
                        box-shadow:20px 20px 20px black;
                        border-radius:20px
                    }
                    .mainDivStyle{
                        width:100%;
                    }
                    

The CSS styling above is straightforward and does not require any explanation.

Listing 5
                        <!DOCTYPE html>
                        <html lang="en">
                            <head>
                                <title>Simple Photo Gallery</title>
                                <link href="AutoGallery.css" rel="stylesheet" type="text/css">
                                <script src="AutoGallery.js" type="text/javascript"></script>
                            </head>
                            <body style="background-color:#444">

                                <div class="mainDivStyle">
                                    <img class="imageSyle" id="mainImage"    alt="" src="#"/>
                                </div>
                                <script type="text/javascript">
                                    preloadimages();
                                    imageIndex=0;
                                    showImage();
                                    startup();
                                </script>
                            </body>
                        </html>
                    

Although this file has an extension of .html there is hardly any HTML code in it. Its main activity is to call three functions from the JavaScript file and set a counter to zero.

The order that the functions are called, however is importand and we shall have a short discussion on that topic.

The functions are called starting at line 13. This is preloadImages() We have met this function above. It simply loads the contents of the image files into memory

At line 14 the variable imageIndex is initialised to zero. As the program runs it counts each image as it is being displayed. We shall be talking more about it when we discuss the JavaScript code.

At line 15 we run the function showImage(). Again we have met this one before. This time we are not passing any parameter to it as we have a diffrerent way of calculating which image will be shown next.

Finally at line 16 we run startup(). this is the function that gives our page its spirit. It is a function that you nave not met before, so we will be concentrating on it.

Listing 6
                        arr=['Goroka%20Composite.png','Goroka%20solo.jpg','manus%20dancer.jpg','Morobe%20Bilas.jpg','manus%20trio1.png','Tari1-1.png','Central%203.png','Taro1.png','White%20Flower1.png'];
                        var imageArray=[];
                        var loadedImages;
                        var imageIndex=0;
                        function preloadimages()
                        {
                            loadedImages=0		
                            for (var i=0; i <arr.length; i++)
                            {
                                imageArray[i]=new Image();
                                imageArray[i].src=arr[i];
                                loadedImages++;
                            }
                        }
                        function showImage(par)
                        {	
                            var intImageHeight=imageArray[imageIndex].height;
                            var intImageWidth=imageArray[imageIndex].width;
                            var sngImageProportion=intImageWidth/intImageHeight;
                            var intWindowHeight=window.innerHeight;
                            var intWindowWidth=window.innerWidth;
                            var sngWindowProportion=intWindowWidth/intWindowHeight;
                            var styleText="";
                            if(sngImageProportion>sngWindowProportion)
                                styleText="width:"+ (window.innerWidth * 0.9) +"px;height:" + (window.innerWidth * 0.9 /sngImageProportion) +"px";
                            else
                                styleText="box-shadow:20px 20px 20px black;border-radius:20px;height:"+ (window.innerHeight *0.9) +"px";
                            document.getElementById("mainImage").setAttribute("style",styleText);
                            document.getElementById("mainImage").src=imageArray[imageIndex].src;
                        }
                        function startup()
                        {
                            myVar = setInterval(function(){nextItem()}, 6000);
                        }
                        function nextItem()
                        {
                            if(imageIndex==loadedImages-1)
                                imageIndex=0;
                            else
                                imageIndex++;
                            showImage();
                        }  
                    

The first 30 lines here are well nigh identical to their equivalents in Listing 3. The only differences are:

So now we come to the functions startup() and nextItem(). The former is the spirit of the application because without it the system would load the first image and just leave it there. The function startup() however keeps prodding the system to move forward to the next image.

The function itself is JavaScript at its most cryptic. The simplest way to explain it is to describe what it does.

Firstly the number 6000 means 6000 milliseconds or in other words 6 seconds. The meaning of the rest of the line of code is 'every 6 seconds call the function nextItem()'. These six second calls will continue while the page is opened.

So what does the function nextItem() do?

Its first action is to test if value of the variable imageIndex is equal to the value of loadedImages less 1. If it is then imageIndex is set to zero at line 38, otherwise it is incremented by 1 at line 40.

Either way, at line 41 showImage() is called to display the image currently pointed to by imageIndex.

Since the function nextItem() is called every six seconds, each time it is called the counter imageIndex is increaded by 1. When it get as far as one below the number of images we have, it is reset back to zero, in order to begin counting up again. This results in the list of images being circulated indefinitely until the user moves to a different page.

Go to top