Bali Web Design Studio is a small enthusiast web design studio based in Bali, Jakarta, Indonesia.

Jquery Image Loader

jquery_image_load

Found a tutorial about image loading using Jquery written by Remy Sharp while trying to create the same function for company i am working at. Remy has publish the core script and here i will modify it to make it work for multiple images, and load in sequencing order.

Multiple Image Loading

First we create an HTML page which has list element with class “loading” which we’re going to define later in the CSS, the amount of the list element depend on how many images we need to put here, in this example i have 3 images.

	<ul id="portfolio">
	<li class="loading"></li>
	<li class="loading"></li>
	<li class="loading"></li>
	</ul>

Next we add CSS for “loading” class which contain the spinner animated gif, as the loading animation.

<style type="text/css">
ul#portfolio { margin:0; padding:0; }
ul#portfolio li { float:left; margin:0 5px 0 0; width:250px; height:250px; list-style:none; }
ul#portfolio li.loading { background: url(spinner.gif) no-repeat center center; }
</style>

and here is the javascript, i already put some comments, which explain what the block codes do. Dont forget to load the jquery core file before these block lines.

// DOM ready
$(function () {

			// image source
			var images = new Array();
				images[0] = 'http://farm4.static.flickr.com/3293/2805001285_4164179461_m.jpg';
				images[1] = 'http://farm4.static.flickr.com/3103/2801920553_656406f2dd_m.jpg';
				images[2] = 'http://farm4.static.flickr.com/3248/2802705514_b7a0ba55c9_m.jpg';

			// loop through matching element
			$("ul#portfolio li").each(function(index,el){
					// new image object
			        var img = new Image();
					// image onload
			        $(img).load(function () {
						// hide first
			            $(this).css('display','none'); // since .hide() failed in safari
						//
			            $(el).removeClass('loading').append(this);
			            $(this).fadeIn();
			        }).error(function () {
						$(el).remove();
			        }).attr('src', images[index]);
			});

		});

you can see the preview of what we did so far here

Create element programmaticaly

Because of sometimes we do not know how many images will be added there, so its better if we let the codes to create the element itself, as many as neccesary. First lets change the HTML codes and left the UL alone with no child.

<ul id="portfolio"></ul>

and we need to change the looping part of the javascript:

			// loop through images
			$(images).each(function(index,value){
					// create the LI programatically
					var list = $('<li id="portfolio_'+index+'"></li>').attr('class','loading');
					// append the new LI to UL
					$('ul#portfolio').append(list);
					// current LI object
					var curr = $("ul#portfolio li#portfolio_"+index);
					// new image
			        var img = new Image();
					// load image
			        $(img).load(function () {
			            $(this).css('display','none'); // since .hide() failed in safari
			            $(curr).removeClass('loading').append(this);
			            $(this).fadeIn();
			        }).error(function () {
						$(curr).remove();
			        }).attr('src', value);
			});

Whats the different?, well on the first part the loop is based on matching element, and load the image from the array based on the index of the element, here the loop is based on the images array, and create the LI element programmaticaly for each of them, and then load itself to the new LI element.

and here is the preview

Sequencing Image Load

At the both previous examples all the images are loaded almost at the same times, now we will make the next image loaded only after the previous ones loaded or could not loaded (error).

Here is the HTML block:

<div id="wrapper"></div>

and here are the final javascript codes:

		// DOM Ready
		$(function () {
			// Image Sources
			var images = new Array();
				images[0] = 'http://farm4.static.flickr.com/3293/2805001285_4164179461_m.jpg';
				images[1] = 'http://farm4.static.flickr.com/3103/2801920553_656406f2dd_m.jpg';
				images[2] = 'http://farm4.static.flickr.com/3248/2802705514_b7a0ba55c9_m.jpg';
			// images length
			var max = $(images).length;
			// at least 1 image exist
			if(max>0)
			{
				// create the UL element
				var ul = $('<ul id="portfolio"></ul>');
				// append to div#wrapper
				$(ul).appendTo($('#wrapper'));
				// load the first image
				LoadImage(0,max);
			}

			// function of loading image
			// params: (int) index of image in array, (int) length of images array
			function LoadImage(index,max)
				{
					// if current index is lower then max element (max-1)
					if(index<max)
						{
							// create the LI, add loading class
							var list = $('<li id="portfolio_'+index+'"></li>').attr('class','loading');
							// append to UL
							$('ul#portfolio').append(list);
							// current LI
							var curr = $("ul#portfolio li#portfolio_"+index);
							// new image object
					        var img = new Image();
							// image onload
					        $(img).load(function () {
					            $(this).css('display','none'); // since .hide() failed in safari
					            $(curr).removeClass('loading').append(this);
					            $(this).fadeIn('slow',function(){
										// once the current loaded, trigger the next image
										LoadImage(index+1,max);
									});
					        }).error(function () {
								// on error remove current
								$(curr).remove();
								// trigger the next image
								LoadImage(index+1,max);
					        }).attr('src', images[index]);
						}
				}

		});

What the changes we made?, we completely changed the load method. Here we use a function “LoadImage” to load the image one by one based on the index of the image as the parameter.

	if(max>0)
	{
		// create the UL element
		var ul = $('<ul id="portfolio"></ul>');
		// append to div#wrapper
		$(ul).appendTo($('#wrapper'));
		// load the first image
		LoadImage(0,max);
	}

you probably knew what the code above does, it check if image sources at least has 1 image, if so then it create UL element, and append it to div with id=”wrapper”, and then load the first image.

$(this).fadeIn('slow',function(){
		LoadImage(index+1,max);
});

once the current image has completely loaded we trigger the same function to load the next image

and here is the final preview.

Experiments

Take a look at my Flickr Photo Set, uses PHP Flickr API, and the Jquery Image Loader above.

Small Update

Small update about grabbing the images from the DOM instead of declare it manualy at the javascript codes, could be found here, thanks for commenting :)

40 Responses.

  1. hams June 23, 2012

    it’s very wonderful

  2. Jonas July 29, 2011

    Thanks for this tutorial

  3. Group Bird July 1, 2011

    Thanks for this great tutorial

  4. Mamzelle April 11, 2011

    Thank for the sharing :) . It helped me a lot! I start to use jquery

  5. Neilo October 12, 2010

    Neilo here again,

    Actually, on second thoughts, I do not need to load the list elements programatically as I know how many images there are.

    This means I can have two classes with different sizes corresponding to my images. So, I just need help on how to load the images in sequence using html list elements used in the first part of the tutorial.

    I’m guessing the solution is easier here than in my previous post!

    Any help would be fantastic!

    Thanks,
    Neilo.

  6. Neilo October 12, 2010

    Hey There,

    Great tutorial mate! I wonder if you could indulge a complete Javascript amateur here.

    My problem is I want to create the list elements programatically, but my images are two different sizes (portrait & landscape). The loading .gif will not be centered using just the one “loading” class.

    Is there any way around this?

    Thanks,
    Neilo.

  7. Eduardo September 17, 2010

    Hi,

    Great solution!

    I wonder if is possible to integrate this kind of loader inside of JQuery Acordeon Menu… I have to build a Acordeon menu wich has large buttons with images.

    The problem is, when loading the JQuery the images appear before the Acordeon build.

    My code for acordeon:

    var slideMenu=function(){
    var sp,st,t,m,sa,l,w,sw,ot;
    return{
    build:function(sm,sw,mt,s,sl,h){
    sp=s; st=sw; t=mt;
    m=document.getElementById(sm);
    sa=m.getElementsByTagName(‘li’);
    l=sa.length; w=m.offsetWidth; sw=w/l;
    ot=Math.floor((w-st)/(l-1)); var i=0;
    for(i;i<l;i++){s=sa[i]; s.style.width=sw+'px'; this.timer(s)}
    if(sl!=null){m.timer=setInterval(function(){slideMenu.slide(sa[sl-1])},t)}
    },
    timer:function(s){s.onmouseover=function(){clearInterval(m.timer);m.timer=setInterval(function(){slideMenu.slide(s)},t)}},
    slide:function(s){
    var cw=parseInt(s.style.width,'10');
    if(cw<st){
    var owt=0; var i=0;
    for(i;iot){oi=Math.floor((ow-ot)/sp); oi=(oi>0)?oi:1; o.style.width=(ow-oi)+’px’}
    owt=owt+(ow-oi)}}
    s.style.width=(w-owt)+’px’;
    }else{clearInterval(m.timer)}
    }
    };
    }();

  8. Hassan March 12, 2010

    the correct url for the update that Remy sharp made is
    (http://www.chazzuka.com/blog/?p=103)
    also it includes example of what u all looking for.

  9. master February 21, 2010

    Hi,
    I was interested in “Small update about grabbing the images from the DOM” but couldn’t find anything cause of page error. Where may I find something about it? Thanks!

  10. bz February 4, 2010

    Hi,
    I was interested in “Small update about grabbing the images from the DOM” but couldn’t find anything cause of page error. Where may I find something about it? Thanks!

    P.S. great job

  11. ersin October 27, 2009

    Thanks for this great tutorial

Leave a Reply

bali web design studio Freelance Web Developer Works Bali Web Design Portfolio Get Web Design Quotation RSS Feeds