(function($) {
  //
  // plugin definition
  //
	$.fn.cyclicFade = function(options)
	{
		if (typeof(options) == 'string') {
			if (options=='stop') {
				$(this).stop(true);
				return this.each(function() {
					$(this).data('cyclic-fade').enabled = false;
				});
			}
			else return null;
		}
		else {
			var opts = $.extend({}, $.fn.cyclicFade.defaults, options);
			return this.each(function() {
				$(this).data('cyclic-fade', {enabled : true});
				$.fn.cyclicFade.doCycle(this,1,opts.repeat,opts.params,0);
			});
		}
	};
	
	$.fn.cyclicFade.defaults = {
		repeat: 0,
		params: [{fadeout:100, stayout:300, opout:0, fadein:100, stayin:300, opin:1.0}]
	};
	
	// this function is used internally
	$.fn.cyclicFade.doCycle = function(obj,start,finish,paramsList,paramsPos) {
		if (paramsPos >= paramsList.length) {
			paramsPos = 0;
		}
		// important: params must be a local variable (var) otherwise it gets overwritten by other
		// calls to doCycle
		var params = paramsList[paramsPos];
		if ($(obj).data('cyclic-fade').enabled) $(obj).fadeTo(params.fadeout, params.opout, function() {
			if ($(obj).data('cyclic-fade').enabled) setTimeout(function() {
				if ($(obj).data('cyclic-fade').enabled) $(obj).fadeTo(params.fadein, params.opin, function() {
					if ($(obj).data('cyclic-fade').enabled) setTimeout(function(){
						if(start!=finish) {
							// increment start only if it is bounded
							if (start<finish) {
								start++;
							}
							$.fn.cyclicFade.doCycle(obj,start,finish,paramsList,paramsPos+1);
						}
					}, params.stayin)
				})
			}, params.stayout)
		});	
	};
	
})(jQuery); 


