
(function () {
	var $ = jQuery;
	var options = {};
	
	var loading = function (elem) {
		if (!$.data(elem, '__plugin_loading'))
			$.data(elem, '__plugin_loading', new _loading(elem));
		return $.data(elem, '__plugin_loading');
	};
	
	
	var _loading = function (elem) {
		this.elem = elem;
		this.opts = {};
		this.visible = false;
		return this;
	};
	
	_loading.prototype = {
		
		show: function () {
			
			if (this.visible)
				return;
			this.visible = true;
			
			this.container = $(document.createElement('div'));
			var elem = this.elem && this.elem !== window ? $(this.elem) : undefined;

			this.container
				.css('border', '0')
				.css('opacity', '0')
				.css('text-align', 'center')
				.css('background', '#eee no-repeat center center url(data:image/gif;base64,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)')
			;

			if (!elem)

				this.container
					.css('z-index', '1001')
					.css('position', 'fixed')
				;
			
			else
			
				this.container
					.css('z-index', '1000')
					.css('position', 'absolute')
				;
			
			var self = this;
			this.updatePositionLoop = setInterval(function () {
				
				if (!elem)
					
					self.container
						.css('top', $('body').offset().top)
						.css('left', $('body').offset().left)
						.width($(window).width())
						.height($(window).height())
					;
				
				else
					
					self.container
						.css('top', $('body').offset().top + elem.offset().top)
						.css('left', $('body').offset().left + elem.offset().left)
						.width(elem.innerWidth())
						.height(elem.innerHeight())
					;
					
			}, 10);
			
			$('body').append(this.container.get(0));
			
			this.container.animate({'opacity': '.8'}, 200);
			
		},
		
		hide: function () {

			if (!this.visible)
				return;
			this.visible = false;
			
			var self = this;
			this.container.animate({opacity: '.0'}, 200, undefined, function () {
				clearInterval(this.updatePositionLoop);
				self.container.remove();
			});

		},
		
		options: function (opts) {
			if (typeof(opts) == 'undefined')
				return this;
			
			this.opts = opts;
			
			return this;
		}
		
	};
	
	$.extend({
	
		showLoading: function (opts) {
			loading(window).options(opts).show();
			return this;
		},
		
		hideLoading: function (opts) {
			loading(window).options(opts).hide();
			return this;
		},
		
		loadingOptions: function (opts) {
			options = opts;
			return this;
		}
		
	});
	
	$.fn.extend({
		
		showLoading: function (opts) {
			this.each(function () {
				loading(this).options(opts).show();
			});
			return this;
		},
		
		hideLoading: function (opts) {
			this.each(function () {
				loading(this).options(opts).hide();
			});
			return this;
		},

		loadingOptions: function (opts) {
			this.each(function () {
				loading(this).options(opts);
			});
			return this;
		}
	
	});
	
})();