;(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
                        //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 = '<img/>',//ensure one
                        thres = settings.threshold;//save a copy
                
                while( --thres > 0 )//it could be oddly negative
                        imgs += '<img/>';
                imgs = $(imgs).load(handler).error(handler).bind('abort',handler).each(fetch);
                
                function handler( e ){
                        data.found = e.type == 'load';
                        data.image = this.src;
                        var orig = data.original = original[this.index];
                        data[data.found?'loaded':'failed']++;
                        data.done++;
                        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.unbind )//sometimes IE gets here before finishing line 84
                                        imgs.unbind('load').unbind('error').unbind('abort');//cleanup
                                imgs = null;
                                finish();
                        }
                };
                function fetch( i, img, retry ){
                        if( $.browser.msie && data.next && data.next % $preload.gap == 0 && !retry ){//IE problem, can't preload more than 15
                                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.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.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)
        };

        $.fn.preload = function( settings ){
                $preload( this, settings );
                return this;
        };

})( jQuery );

