   
	/* loadingIndicator */

    /*config*/
    $.config.override({
        ajax: {
            scrollTime: 800
        }
    })
    
	function loadingIndicator() {}

	loadingIndicator.prototype.show = function(parentElement)
	{
		this.element = parentElement.ownerDocument.createElement('div');
		this.element.className = 'loadingIndicator';
		this.element.style.left = parentElement.offsetLeft + parentElement.offsetWidth/2 + 'px';
		this.element.style.top = parentElement.offsetTop + parentElement.offsetHeight/2 + 'px';
		parentElement.parentNode.insertBefore(this.element, parentElement.nextSibling);
	}

	loadingIndicator.prototype.hide = function()
	{
		this.element.parentNode.removeChild(this.element);
	}

	function importDocumentMedia(sourceDocument)
	{
		var scripts = []; $(document).find('head script').each( function() { scripts.push($(this).attr('src')) } )
		
		$(sourceDocument).find('head script').each( function() {
			if(scripts.indexOf($(this).attr('src')) == -1)
			{				
				var script = document.createElement('script');
				script.setAttribute('src', $(this).attr('src'));
				script.setAttribute('type', $(this).attr('type'));
				$(document).find("head").get('0').appendChild(script);
			}
		})

		var links = [];
		$(document).find('head link').each(function() { 
			var linkRefs = unpackStrings($(this).attr('href'));			
			for(var i in linkRefs) 
				links[linkRefs[i]] = null;
		});
		
		$(sourceDocument).find('head link').each(function() { 
			var linkRefs = unpackStrings($(this).attr('href'));
			
			for(var i in linkRefs) {
				if(!(linkRefs[i] in links)) {
					var link = document.createElement('link');
					link.setAttribute('href', linkRefs[i]);
					link.setAttribute('type', $(this).attr('type'));
					link.setAttribute('media', $(this).attr('media'));
					link.setAttribute('rel', $(this).attr('rel'));
					$(document).find("head").get('0').appendChild(link);
				}
			}
		});
	}

	function ajaxUpdateComponent(component, link)
	{
		if(link == undefined) link = new ajaxLink(window.location.href);

		if(typeof component == 'string')
		{
			var element = link.a;
			if(element == undefined) element = link.form;
			var rootNode = document.documentElement;
			if(element != undefined)
			{
				rootNode = $(element).parents(".window:first").get(0);
				if(!rootNode) rootNode = element.ownerDocument.documentElement;
			}

			var componentId = component;
			$(rootNode).find("[component='"+componentId+"']")
			var sourceComponent = $(rootNode).find("[component='"+componentId+"']").get(0);

		}
		else
		{
			var sourceComponent = component;
			var componentId = sourceComponent.getAttribute('component');
		}

		if(!$(sourceComponent).is('.ajaxUpdating'))
		{
			$(sourceComponent).addClass('ajaxUpdating');
		
			if(link.submit != undefined) $(link.submit).attr('disabled', 'disabled');

			var indicator = new loadingIndicator();
			indicator.show(sourceComponent);

			$(sourceComponent).fadeToHidden('medium');

			var success = function(loadedDocument) {
				if(link.submit != undefined) $(link.submit).removeAttr('disabled');
				importDocumentMedia(loadedDocument);
				
				var component = $(loadedDocument).find("[component='"+ componentId +"']").first().css('visible', 'hidden').css('opacity', '0');
				indicator.hide();
				var container = sourceComponent.parentNode;
				/* disabled due to the problems with old objectControl code */
				/* var oldHeight = $(sourceComponent).height(); */
				$(sourceComponent).replaceWith(component.toXML());
				var o = $(container).offset();
				var bottomPosition = o.top + $(container).height();
				var replacement = $("[component='"+ componentId +"']", container);
				replacement.fadeToVisible('fast');
				$(document).trigger('update');
				$(document).trigger('updateComponent');
				if ($(document).scrollTop() > o.top) {
					$(document).scrollTo(o.top, $.config.get("ajax.scrollTime"));
				}
			}

			var error = function() {
			    if (link.submit != undefined) $(link.submit).removeAttr('disabled');
			    $(sourceComponent).removeClass('ajaxUpdating').fadeToVisible('fast');
			    indicator.hide();
			}

			link.setParameter('componentFilter', componentId, false);
			link.setParameter('outputMimeType', 'application/xhtml+xml', true);
			link.loadXml({success: success, error: error});
		}

		return true;
	}

	function ajaxUpdate(link)
	{
		var targetComponentId = link.getParameter('targetComponent');

		if(targetComponentId != undefined && targetComponentId.length)
		{
			return ajaxUpdateComponent(targetComponentId, link)
		}

		return false;
	}

	function ajaxOpen(link)
	{
		var targetComponentId = link.getParameter('targetComponent');
		if (targetComponentId != undefined && targetComponentId.length) {
			var winObject = new win({mode: link.getParameter('window.mode')});
			winObject.autoDestroy = true;
			winObject.href = link.assembleRef();
			winObject.open();

			switch($('html').attr('lang'))
			{
				case 'ru':
					winObject.setContent('<div class="message">Содержимое загружается. Пожалуйста, подождите...</div>');
					break;

				case 'en':
					winObject.setContent('<div class="message">Content loading in process. Please wait, this may take a few seconds...</div>');
			}

			var indicator = new loadingIndicator();
			indicator.show(winObject.contentContainer);

			link.setParameter('componentFilter', targetComponentId, false);
			link.setParameter('outputMimeType', 'application/xhtml+xml', true);
			var loadedDocument = link.loadXml();

			importDocumentMedia(loadedDocument);

			var component = $(loadedDocument).find("[component='"+ targetComponentId +"']");
			indicator.hide();

			winObject.setContent(component.toXML());

			$(winObject.contentContainer).hide().fadeIn('fast').slideDown('fast');
			$(document).trigger('updateComponent');				
			$(document).trigger('update');

			return true;
		}
		return false;
	}

	function ajaxLoad(link, currentRef)
	{
		if(currentRef == undefined) currentRef = window.location.href;

		var oldLink = new ajaxLink(currentRef);
/*		try
		{
*/			
			if(link.protocol == 'http:' && oldLink.host == link.host)
			{
				var target = link.getParameter('target');
				if(target == undefined) target = oldLink.path != link.path ? 'new' : 'this';
				return !(target == 'new' ? ajaxOpen(link) : ajaxUpdate(link));
			}
/*
		}
		catch(e) {
			alert('AJAX handler: ' + e.message)
		}
*/
		return true;
	}

	function ajaxHandleLink(a)
	{
		var windowNode = $(a).parents(".window:first").get(0);
		var currentRef = windowNode && windowNode.control ? windowNode.control.href : window.location.href;

		var link = new ajaxLink();
		link.assignA(a);
		return ajaxLoad(link, currentRef);
	}

	function ajaxHandleFormSubmit(submit)
	{
		
		var form = $(submit).parents("form:first").get(0);
		
		var windowNode = $(form).parents(".window:first").get(0);
		var currentRef = windowNode && windowNode.control ? windowNode.control.href : window.location.href;
		
		var link = new ajaxLink();
		link.assignForm(form, submit);
		
		var oldLink = new ajaxLink(currentRef);
		if(link.protocol == 'http:' && oldLink.host == link.host && oldLink.path == link.path) {
			link.setParameter('targetComponent', form.hasAttribute('targetComponent') ? $(form).attr('targetComponent') : $(form).parents("[component]:first").andSelf().filter("[component]:last").attr('component'), false);
		}
		
		//TEMP//
		var handler = function(component) {
			var spikeLink = new ajaxLink(currentRef);
			spikeLink.setParameter('targetComponent', component);
			ajaxLoad(spikeLink, currentRef);
		};
		if($(submit).hasClass('addItemToCurrentOrder'))  
		{
			if($("body").find("div.orderStatus[component='page.info.orderStatus']").length > 0) {
				$(document).one("update", function(){
					handler('page.info.orderStatus');
				})
			} 
			else return true; // reload entire page  
		}
		//TEMP//
		
		return ajaxLoad(link, currentRef);
	}

	function ajaxLinkHandler(event)
	{
	    if(event.button == 1) return true; //right click disabled
		if(!ajaxHandleLink(this)) event.preventDefault();
	}

	function ajaxFormSubmitHandler(event)
	{
		if(event.type == "mousedown") { 
			
			if(event.button == 2) return true; //right click disabled
			
			if(!$(this).parents("form:first").get(0).target) {
				if(!ajaxHandleFormSubmit(this)) event.preventDefault();
			}
		}
		
		if (event.type == "submit") {
			var defaultButton = $(this).find(":submit[default='default']").first().get(0);
			
			if($(this).find(":submit[default='default']").length == 0) {
				defaultButton = $(this).find(":submit").first().get(0);
			}
			
			if(!ajaxHandleFormSubmit(defaultButton)) event.preventDefault();
		}
	}

	function ajaxInit()
	{
	    if($.browser.msie) {
			$(document).trigger('update');
			return;
		}
		
		$("form").live('submit',  ajaxFormSubmitHandler);
		
		$("form :submit:not([onclick]), form :image:not([onclick])").live('mousedown',  ajaxFormSubmitHandler);
		
		$("a:not([onclick])").live('click', ajaxLinkHandler);

		$("body").ajaxStart(function(){
			$(this).css('cursor', 'progress');
		});

		$("body").ajaxStop(function(){
			$(this).css('cursor', 'auto');
		});

		$(document).trigger('update');
	}

	jQuery.fn.fadeToHidden = function(duration)
	{
		var animation = !($.browser.msie); // IE7-8 smoothed font opacity bug
		if(animation) this.animate({opacity: 0}, {duration: duration, complete: function() {$(this).css('visibility', 'hidden')}});
		else this.css('visibility', 'hidden');
	}

	jQuery.fn.fadeToVisible = function(duration)
	{
		var animation = !($.browser.msie); // IE7-8 smoothed font opacity bug
		if(animation)	this.css('visibility', 'visible').animate({opacity: 1}, duration);
		else this.css('visibility', 'visible');
	}

	$(document).ready(function() {
		ajaxInit();
	});

	$(document).bind('update', function() {		
		$(".lx-component-delayed").each(function(){
			ajaxUpdateComponent(this)
		});
	})

	// TOFIX:
	// 1. concurent requests
