Tutorial: How to add preloader with loading image in a gallery using jQuery

In my previous article on understanding preloading for components, we talk about a lot about preloading. If you are seeking for other methods you may want to visit that article. In this article, i will demonstrate how to perform a preload with those loading in progress image in a gallery using jQuery.

Requirement

The gallery used will be the one at How to create your own continuously slide effect plugin with jQuery. But if you have your own gallery, this can safely be skipped.

Concept

The concept of preloading images with a loading image is pretty easy. The important thing we need to know is onload and onerror functionality in JavaScript. onload is here to tell us whether the picture is ready and onerror is here to tell us whether the picture cannot be loaded due to various reason. With some additional checking and animation to make it look nice.

The Code

HTML

I have added one additional div block, 'loading' into the gallery and added the image link in the picture instead of image tag.

<div id="frame">
	<div id="container">
		<div class="box" id="box1">images/1.jpg</div>
		<div class="box" id="box2">images/2.jpg</div>
		<div class="box" id="box3">images/3.jpg</div>
		<div class="box" id="box4">images/4.jpg</div>
		<div class="box" id="box5">images/5.jpg</div>
		<div class="box" id="box6">images/whatever/6.jpg</div>
	</div>
<div id="prev"></div>
<div id="next"></div>
<div id="loading"></div>
</div>

The sole purpose of doing this is to load the page faster and enable any window.onload function. This way, user will not have to wait a few second for the overall page to load. Take note that i purposely write a wrong URL for box id 'box6' so that it won't load.

CSS

Since i have added a new div block, i will have to declare its CSS rule.

#loading
{
	display: none;
	position: absolute;
	height: 234px;
	width: 234px;
	margin-top: -117px;
	margin-left: -117px;
	left: 50%;
	top: 50%;
	background: transparent url('../images/loading.gif') no-repeat 100% 100%;
}

Basically i have align the loading image at the center of the gallery and hide it for the time being.

jQuery

I i have just added the following one line after the animation has completed,

			$("div#container").animate({marginLeft: i*op.containerW+"px"},op.duration, function(){
			var imgObj = getImg(pathObj[0-i]);
			});

once the animation is over, we can start preload the images out to show our users. And the two resuable and cross browser methods i have made for myself in case of future gallery are getImg() and loadImg(). Let's first talk about getImg.

	function getImg(obj)
	{
		url = $(obj).css({"display":"block", "visibility":"visible"}).html();			//get the image url from the div block
		loaded = false;										//check whether image has been loaded
		if(url.search(/<.*/) != -1)							//search for opening tag, doing /'<img.*/>'/ doesn't work in IE7 and Opera somehow.
		{
			loaded=true;									//found opening tag, assume its loaded
			tmp = $(obj).children();						//get the img tag obj
			url = $(tmp[0]).attr("src");						//retrieve the url
			if(tmp[1] != undefined)							//check whether there is a second block in the children of the div block (this is added in loadImg when it fail)
				loaded = false;								//there is an error message, we try to load again
		}
		if(!loaded)
			loadImg(url,obj, "#loading", "there seems to be an issue, try again later");
	}

In getImg, it takes in one parameter, obj which is the current div block we are looking at. Basically, what the above method do is to retrieve the image link provided in the div block, check whether this block image has been loaded and determine whether it needs to be loaded. This method also provides a second chance for user to reload the image again which depend on loadImg(). Comment are written in the code.

loadImg is the preloading that takes place,

	function loadImg(url, obj, loading, msg)
	{
		$(loading).css({"display":"block"}).animate({opacity:1},1000);					//display the loading in progress image
		$(obj).html("<img src='"+url+"' width='500px' height='350px'/>").css({opacity: 0});	//throw in the image into the div block
		var tmp = $(obj).children();													//gets the image obj we just thrown in
			tmp[0].onload = function(){													//when the image has complete loaded
				$(obj).animate({opacity:1},1000);										//display the image
				$(loading).animate({opacity:0},1000).css({"display":"none"});				//hide the loading in progress image
			}
			tmp[0].onerror = function(){												//when the image fail to load for various reason
				$(this).css({"display":"none"});											//we hide the image that fail
				$(obj).html($(obj).html()+"<div>"+msg+"</div>").animate({opacity:1},1000);//provides a message to the user instead
				$(loading).animate({opacity:0},1000).css({"display":"none"});				//hide the loading in progress image
			}
	}

This method takes in four parameter which can join together with the first method and become one but i prefer them to be seperated. What it does are commented above and the parameter are listed below,

  • url: the image url. eg, 'http://hungred.com/hello.jpg' or images/hello.jpg
  • obj: the current div block with the image url on it.
  • loading: the loading in progress image block id. eg, '#loading'
  • msg: the image or message when the url image fail to load. eg, 'fail to load image, try again later'

As we can see the first image doesn't load yet as getImg() only gets fire up whenever the user clicked the next or previous button. What we do is to provide the first element div block to getImg() as shown below,

getImg(pathObj[0]);

where pathObj is the list of div blocks with the class 'box' as shown on the HTML section.

Additional preloading

if you want to preload further, you can try to add the code mention in preload all images in jQueryafter document.ready() to preload in advance all images and stored it to their cache. In this way, user might not even need to wait a millisecond for an image to load up.

The Demo

The demo and files are provided below,

Conclusion

Well, the purpose of this article is to share with you how i make a preloader in a gallery with jQuery and also provide my code snippet for you to integret this small method into your gallery to make your page with gallery more responsive.