jQuery(function($) {
	$.fn.preload = function(load, progress){
		var imgs=[], preloaded=[];
		var self=this;
		
		this.filter("img").each(function(){
			imgs.push($(this).attr("src"));
		});

		var run = function() {
			var n = preloaded.length,m=imgs.length;

			if ($.isFunction(progress))
				progress.apply(self,[n,m]);
			
			var deq = function(e) {
				if (e.target.parentNode === null) {/* IE bug */
					$(this).unbind("error");
					$(this).unbind("load");
					setTimeout(function(){run.call(self)}, 200);
				}
			};
			if (n < m) {
				preloaded[n] = $("<img/>").load(deq).error(deq).attr({src:imgs[n]}); 
				return;
			}
			if ($.isFunction(load))
				load.call(self);
		};
		run();
		
		return this;
	};

	$.fn.waitload = function(onload, progress){
		var coda=this.filter("img");
		var setup=false;
		var m=coda.length;
		var self=this;
		var finito=false;
		
		var deq = function(e) {
			if (finito)
				return;
			
			var n=0;
			
			coda=coda.not($(this));
			n=m-coda.length;

			coda.each(function(){
				if ($(this).attr("complete"))
					n++;
			});
			$(this).unbind("load");
			$(this).unbind("error");
			if ($.isFunction(progress))
				progress.apply(self,[coda,n,m]);

			if (n < m)
				return;

			if ($.isFunction(onload))
				onload.call(self,[coda]);

			finito=true;
		};

		coda.each(function(){
			if (!$(this).attr("complete")) {
				setup=true;
				$(this).load(deq).error(deq).attr({
					src: $(this).attr("src")
				});
			}
		});

		if (!setup) {
			if ($.isFunction(progress))
				progress.apply(self,[coda,m,m]);
			if ($.isFunction(onload))
				onload.call(self,[coda]);
		}
		return this;
		
	};
});
