(function($)
{
	$.fn.WidgetLoader = function(options)
	{	
		// need a reference to this for future use 
		var refThis = this;
	
		// the available options list that keep growing as time goes on time goes on
		var options = $.extend({
			loading     : '<img class="loading" src="/themes/global/default/normal/images/loading.gif" />',
			beforeSend  : function(){},
			url         : null,
			widget      : null,
			module      : null,
			success     : function(){}, // function() success callback 
			error404    : function(){}, // function() 404 error callback
			errorMsg404 : '<h3>We looked and looked and we can\'t find it anywhere.</h3>',
			error500    : function(){}, // function() 500 error callback
			errorMsg500 : '<h3>Oops, An error has occured.  Please contact your systems administrator.</h3>',
			animateIn   : null, // string - jQuery animation
			speedIn     : 'normal',
			animateOut  : null, // string - jQuery animation
			speedOut    : 'normal'
		}, options);

		// you need a module name and a widget-id or a url to hit to get the data
		if (options.module != null && options.widget != null){
			options.url = '/widget/load/mod/'+options.module+'/widget/'+options.widget;
		}
		// this is a nice little error message in case you messed up and forgot something 
		if (options.url == null){
			alert('This is a friendly message saying you forgot to supply a url for loading for '+this.attr('id'));
			return;
		}
		
		// replaces the existing object with new content using animations
		// for both removing the existing object and replacing with the new one
		
		// The new content must have the same value for the id attribute
		// for this to work correctly
		function _animateReplace(obj, content){
			var id = obj.attr('id');
			var refContent = content;			
			if (options.animateOut){
				obj[options.animateOut](options.speedOut,
						function(){
							$(this).replaceWith(refContent);
							if (options.animateIn){
								$('#'+id).hide()[options.animateIn](options.speedIn);
							}
						}
				);
			}
			else{
				obj.replaceWith(content);
				
				if (options.animateIn){
					$('#'+id).hide()[options.animateIn](options.speedIn);
				}
			} 			
		}
		
		// checks if any animation is to take place and perform 
		// the animated replace if necessary
		// make any defined success callbacks
		function _replace(obj, content){
			if (options.animateIn || options.animateOut){
				_animateReplace(refThis, content);
			}
			else{
				obj.replaceWith(content);
			}
				options.success.call();
		}
		
		// shows any error messages that have been defined
		// this will use the defined animations and any defined
		// error callbacks 
		function _showError(obj, errorCode){
			var errorMsg = 'errorMsg' + errorCode;
			var error    = 'error' + errorCode;
			if (options[errorMsg]){
				_replace(obj, options[errorMsg]);
			}			
			options[error].call();
		}
		
		// waits until the document has been loaded before starting 
		// up the process
		$(window).load(function(){	
					
					refThis.append(options.loading).find('img').css('position', 'relative').css('top','50%');
					
					$.ajax({
						url: options.url,
						beforeSend:
							options.beforeSend.call(),
						success:
							function(response){	
								_replace(refThis, response);
							},
						statusCode:{
								404:function(){
										_showError(refThis, 404);
									},
								500:function(){
										_showError(refThis, 500);
									}
							}							
					});
				}
		);
	};
}
)(jQuery);


