/**

 * jQuery.Preload

 * Copyright (c) 2008 Ariel Flesler - aflesler(at)gmail(dot)com

 * Dual licensed under MIT and GPL.

 * Date: 3/25/2009

 *

 * @projectDescription Multifunctional preloader

 * @author Ariel Flesler

 * @version 1.0.8

 *

 * @id jQuery.preload

 * @param {String, jQuery, Array< String, <a>, <link>, <img> >} original Collection of sources to preload

 * @param {Object} settings Hash of settings.

 *

 * @id jQuery.fn.preload

 * @param {Object} settings Hash of settings.

 * @return {jQuery} Returns the same jQuery object, for chaining.

 *

 * @example Link Mode:

 *	$.preload( '#images a' );

 *

 * @example Rollover Mode:

 *	$.preload( '#images img', {

 *		find:/\.(gif|jpg)/,

 *		replace:'_over.$1'

 *	});

 *

 * @example Src Mode:

 *	$.preload( [ 'red', 'blue', 'yellow' ], {

 *		base:'images/colors/',

 *		ext:'.jpg'

 *	});

 *

 * @example Placeholder Mode:

 *	$.preload( '#images img', {

 *		placeholder:'placeholder.jpg',

 *		notFound:'notfound.jpg'

 *	});

 *

 * @example Placeholder+Rollover Mode(High res):

 *	$.preload( '#images img', {

 *		placeholder:true,

 *		find:/\.(gif|jpg)/,

 *		replace:'_high.$1'

 *	});

 */

;(function( $ ){



	var $preload = $.preload = function( original, settings ){

		if( original.split ) // selector

			original = $(original);



		settings = $.extend( {}, $preload.defaults, settings );

		var sources = $.map( original, function( source ){

			if( !source ) 

				return; // skip

			if( source.split ) // URL Mode

				return settings.base + source + settings.ext;

			var url = source.src || source.href; // save the original source

			if( typeof settings.placeholder == 'string' && source.src ) // Placeholder Mode, if it's an image, set it.

				source.src = settings.placeholder;

			if( url && settings.find ) // Rollover mode

				url = url.replace( settings.find, settings.replace );

			return url || null; // skip if empty string

		});



		var data = {

			loaded:0, // how many were loaded successfully

			failed:0, // how many urls failed

			next:0, // which one's the next image to load (index)

			done:0, // how many urls were tried

			/*

			index:0, // index of the related image			

			found:false, // whether the last one was successful

			*/

			total:sources.length // how many images are being preloaded overall

		};

		

		if( !data.total ) // nothing to preload

			return finish();

		

		var imgs = $(Array(settings.threshold+1).join('<img/>'))

			.load(handler).error(handler).bind('abort',handler).each(fetch);

		

		function handler( e ){

			data.element = this;

			data.found = e.type == 'load';

			data.image = this.src;

			data.index = this.index;

			var orig = data.original = original[this.index];

			data[data.found?'loaded':'failed']++;

			data.done++;



			// This will ensure that the images aren't "un-cached" after a while

			if( settings.enforceCache )

				$preload.cache.push( 

					$('<img/>').attr('src',data.image)[0]

				);



			if( settings.placeholder && orig.src ) // special case when on placeholder mode

				orig.src = data.found ? data.image : settings.notFound || orig.src;

			if( settings.onComplete )

				settings.onComplete( data );

			if( data.done < data.total ) // let's continue

				fetch( 0, this );

			else{ // we are finished

				if( imgs && imgs.unbind )

					imgs.unbind('load').unbind('error').unbind('abort'); // cleanup

				imgs = null;

				finish();

			}

		};

		function fetch( i, img, retry ){

			// IE problem, can't preload more than 15

			if( img.attachEvent /* msie */ && data.next && data.next % $preload.gap == 0 && !retry ){

				setTimeout(function(){ fetch( i, img, true ); }, 0);

				return false;

			}

			if( data.next == data.total ) return false; // no more to fetch

			img.index = data.next; // save it, we'll need it.

			img.src = sources[data.next++];

			if( settings.onRequest ){

				data.index = img.index;

				data.element = img;

				data.image = img.src;

				data.original = original[data.next-1];

				settings.onRequest( data );

			}

		};

		function finish(){

			if( settings.onFinish )

				settings.onFinish( data );

		};

	};



	 // each time we load this amount and it's IE, we must rest for a while, make it lower if you get stack overflow.

	$preload.gap = 14; 

	$preload.cache = [];

	

	$preload.defaults = {

		threshold:2, // how many images to load simultaneously

		base:'', // URL mode: a base url can be specified, it is prepended to all string urls

		ext:'', // URL mode:same as base, but it's appended after the original url.

		replace:'' // Rollover mode: replacement (can be left empty)

		/*

		enforceCache: false, // If true, the plugin will save a copy of the images in $.preload.cache

		find:null, // Rollover mode: a string or regex for the replacement

		notFound:'' // Placeholder Mode: Optional url of an image to use when the original wasn't found

		placeholder:'', // Placeholder Mode: url of an image to set while loading

		onRequest:function( data ){ ... }, // callback called every time a new url is requested

		onComplete:function( data ){ ... }, // callback called every time a response is received(successful or not)

		onFinish:function( data ){ ... } // callback called after all the images were loaded(or failed)

		*/

	};



	$.fn.preload = function( settings ){

		$preload( this, settings );

		return this;

	};



})( jQuery );
