How To Preload A Content Slider Full Of Images

classes, css, elsewhere, mootools

I've had a lot of emails over the last few months about my content slider class, and one of the most asked questions is regarding preloading a slider full of images.   Today, I'm going to show you how I've been doing it.  (And with a little help from my favorite MooTools guy we're going to make it look cool, too.)

Here's a sneak peek at the demo, although you may not even see the preloader bar if you're on a fast connection. Let's get to it!

What You Will Need:

  • MooTools (1.2 or higher), and MooToolsMore with the 'Utilities.Assets' package
  • My content slider class
  • David Walsh's dwProgress class (Thanks again to David Walsh for sharing this class!)

How To Do It:

Basically, we're just going to set up everything as we normally do with the content slider - but we're going to use the functionality of MooTools' Assets package to preload the images, and at the same time use David's ProgressBar to visually display that preloading.  If you need help understanding the initial content slider setup, please refer back to that post for a moment to refresh your brain.

The HTML

You'll need to add a tiny bit of extra markup to your existing content slider page.  (Hint: I usually add it inside my 'container' element.)

<div id="preloader"> </div>

I know, take a breather... that was rough. 

And A Little CSS

It really depends on your layout needs, but I typically add something along these lines:

#preloader {
    visibility: hidden;  //will fade in when needed
    position: absolute;
    top: 0px;
    left: 0px;
    z-index: 9000;
    width: 200px; //arbitrary value
    height: 30px; //setting a height helps w/ lame IE issues	
}

#pre_box  { border:1px solid #3dcdfe; width:200px; height:10px; background-color: #095b81;}
#pre_perc  { background:#bee1e9; height:10px; }
#pre_text { font-size:10px; color:#fff; padding:3px 0 0 10px; text-align: center; background: transparent; }

And Finally, The Javascript

Of course, to begin this we need to include our scripts.

<script type="text/javascript" src="js/moo_12.js"></script>
<script type="text/javascript" src="js/moo_12.js"></script>
<script type="text/javascript" src="js/sl_slider.js"></script>
<script type="text/javascript" src="js/dw_progress.js"></script> 

And then like always, we wrap our code in a 'domready' wrapper, instantiate our classes... and make use of the Assets function.  That's where things get a little different.  Here's the whole block of code, and I'll breakdown the new parts afterwards:

//slider variables for making things easier below
var itemsHolder = $('container');
var myItems = $$(itemsHolder.getElements('.item'));

//controls for slider
var theControls = $('controls1');
var numNavHolder = $(theControls.getElement('ul'));
var thePlayBtn = $(theControls.getElement('.play_btn'));
var thePrevBtn = $(theControls.getElement('.prev_btn'));
var theNextBtn = $(theControls.getElement('.next_btn'));
var thePreloader = $('preloader');



//create array from images to preload, and hide (will unhide when loaded)
var theImages = new Array();
myItems.each(function(el, i){
	var tempImg = $(el.getElement('img'));
	var tempSrc = tempImg.getProperty('src');
	theImages.push(tempSrc);
	el.set('opacity', 0);
});	

//some preloader positioning stuff
//(note: you can just set this in the CSS, but I'm setting it dynamically)
var contentCoords = itemsHolder.getCoordinates();
var contW = contentCoords.width;
var contH = contentCoords.height;
var preCoords = thePreloader.getCoordinates();
var preW = preCoords.width;
var preH = preCoords.height;

var preX = (contW - preW)/2;
var preY = (contH - preH)/2;
thePreloader.setStyles({ 'top': preY, 'left': preX});


//tween preloader into view
thePreloader.set('tween', {duration: 500, transition: 'cubic:out'}).tween('opacity', 1);


//determine how much to increment preloader per image load
var numImgs = theImages.length;
var percentBump = (100/numImgs).toInt();

//thanks to David Walsh for the loader bar class
var pb = new dwProgressBar({
	container: thePreloader,
	startPercentage: 0,
	speed:500,
	boxID: 'pre_box',
	percentageID: 'pre_perc',
	step:percentBump,
	allowMore: 0,
	displayID: 'pre_text',
	displayText: true,
	onComplete: function() {  
	   //alert('Done!');			
	}
});



//starts loading images here
var myImages = new Asset.images(theImages, {
	onProgress: function(counter){
		pb.step();
	},

	onComplete: function(){
		
			
		//create instance of the slider, and start it up		
		var mySlider = new SL_Slider({
			slideTimer: 6000,
			orientation: 'horizontal',  
			fade: true, 
			isPaused: true,
			container: itemsHolder,
			items: myItems,
			numNavActive: true,
			numNavHolder: numNavHolder,
			playBtn: thePlayBtn,
			prevBtn: thePrevBtn,
			nextBtn: theNextBtn
		});
		mySlider.start();
		
		//unhide slides			
		myItems.each(function(el){
			el.set('opacity', 1);
		});
		
		thePreloader.tween('opacity', 0);
		
	}
	
});
//end images load

I tried to comment a lot of the above code, but just in case things aren't clear I want to explain a few parts.  First,

var theImages = new Array();
myItems.each(function(el, i){
	var tempImg = $(el.getElement('img'));
	var tempSrc = tempImg.getProperty('src');
	theImages.push(tempSrc);
	el.set('opacity', 0);
});   

In this block above, we create an array of the image sources from our content items.  (We're going to feed this array of image sources into the Assets class a bit later in the script.) We also hide each item for now, since things may look a bit weird if there's a lot of images/slides to load.

The next part handles positioning the preloader.  This isn't required, as you could just position it with CSS.

var contentCoords = itemsHolder.getCoordinates();
var contW = contentCoords.width;
var contH = contentCoords.height;
var preCoords = thePreloader.getCoordinates();
var preW = preCoords.width;
var preH = preCoords.height;

var preX = (contW - preW)/2;
var preY = (contH - preH)/2;
thePreloader.setStyles({ 'top': preY, 'left': preX});


//tween preloader into view
thePreloader.set('tween', {duration: 500, transition: 'cubic:out'}).tween('opacity', 1);

Basically, I'm just getting the coordinates and dimensions of the container element, and then centering the preloader element with that info.  But remember - that's just optional stuff!  Aftter that, I am just fading in the preloader.  Moving along...

In this next code block, we figure out how much to increment the preloader bar per image load, and then instantiate David's progress bar class with the appropriate info - all of which we now have.

//determine how much to increment preloader per image load
var numImgs = theImages.length;
var percentBump = (100/numImgs).toInt();

//thanks again to David Walsh for the sweet loader bar class
var pb = new dwProgressBar({
	container: thePreloader,
	startPercentage: 0,
	speed:500,
	boxID: 'pre_box',
	percentageID: 'pre_perc',
	step:percentBump,
	allowMore: 0,
	displayID: 'pre_text',
	displayText: true,
	onComplete: function() {  
	   //alert('Done!');			
	}
});

Finally, we just make use of Mootools' Asset.images method to handle the actual preloading.  Note the use of the onProgress function to bump the progress bar up each time an image loads.  After all the images are loaded, we just instantiate the content slider class like normal - but inside the onComplete function.

//starts loading images here
var myImages = new Asset.images(theImages, {
	onProgress: function(counter){
		pb.step();
	},

	onComplete: function(){
		
			
		//create instance of the slider, and start it up		
		var mySlider = new SL_Slider({
			slideTimer: 6000,
			orientation: 'horizontal',  
			fade: true, 
			isPaused: true,
			container: itemsHolder,
			items: myItems,
			numNavActive: true,
			numNavHolder: numNavHolder,
			playBtn: thePlayBtn,
			prevBtn: thePrevBtn,
			nextBtn: theNextBtn
		});
		mySlider.start();
		
		//unhide slides			
		myItems.each(function(el){
			el.set('opacity', 1);
		});
		
		thePreloader.tween('opacity', 0);
		
	}
	
});
//end images load

And that's all there is to it.  It may seem a little complex at first glance, but I promise it's really not.  Go check out the demo, look at the example code and you'll see for yourself.   Note: I have left out the images from the .zip file to save on bandwidth/resources... just put your own images in there.  (But you were going to do that anyhow, right?)

 

 

Find This Post Useful? Share it!


Comments (4 Total)

on Tue. Aug 4th, 2009 6:12am

Great and very useful! Thanks!

Regards Andrew

on Tue. Sep 1st, 2009 9:56pm

Great work. I like an auto play version. of course we can change it in script the settings.

Oliver
on Fri. Sep 25th, 2009 3:14am

Thank you very much for all the hard work.

I am using your slider class for our company website and I have just added (part of) this preloader (even though it's just an animated gif... :) ). Works a treat.

on Mon. Aug 23rd, 2010 4:39am

all is cool - I would like to use this as a gallery script that paginates a block of 5 X 4 images per page - would you be able to (more like willing too) show a demo of this pre loading only the next 20 images too? - possibly with david walsh's lazy load?

thanks for the tut and the code :)

Your Name
0 seconds ago
Add Your Comment