	/**
	* Плагин, позволяющий навешивать всплывающие информационные окна
	* В настоящиее время поддерживает 3 типа окон: 
	*   - titleBlock - с заголовком (и кнопкой "закрыть") и с внутренним ДИВом (в который биндится полученное извне содержимое)
	*   - normalBlock - с внутренним ДИВом (в который биндится полученное извне содержимое), но без заголовочного блока
	*   - noNoBlock - просто ДИВ без ничего (в него напрямую биндится все извне)
	* Также поддерживаются 2 способа получения информации для размещения в окне: 
	* 	- из элемента со страницы с заданным id
	*	- через ajax-запрос заданной страницы
	* Вид окна задается через css, за исключением параметра, корректирующего длину блока названия заголовка: 
	*  - options.blockOpt.titleWidthCorrector - этот параметр подбирается в зависимости от заданных основных css-параметров окна
	* @param object пользовательские установки объекта options
	* @param object пользовательские установки объекта blockOptions
	* @param object пользовательские установки объекта sourceOptions
	* @return false
	* TODO: сделать, чтобы для IE6 под враппер подкладывался frame 
	* TODO: сделать анимацию открытия-закрытия окна
	*
	* Примеры использования внизу файла
	*/
	jQuery.fn.infoLayer = function(options, blockOptions, sourceOptions) {			
				// общие настройки по умолчанию
			var options = jQuery.extend({
				wrapper : 'noNoBlock', // Тип выводимого блока
				source : 'Id', // Источник хранения информации, выводимой в окне: ajax-запрос или блок с заданным id
				width : 200, // ширина блока содержимого
				height : 'auto',
				cssCW : '' // css-класс контент-враппера
			}, options);
				// Настройки для каждого типа блока-оболочки 
			var blockOpt = {
				normalBlock : {tInterval : 800, useTitle : false, deltaH:17, titleWidthCorrector : 0  }, 
				titleBlock  : {tInterval : 0, useTitle : true,  deltaH:27, titleWidthCorrector : 27, title : 'Заголовок окна'},
				noTitleBlock : {tInterval : 0, useTitle : true,  deltaH:27, titleWidthCorrector : 0},
				noNoBlock : {tInterval : 0, useTitle : false,  deltaH:0, titleWidthCorrector : 0}
			};	
				// настройки источника информации
			var sourceOpt = {
				Id   : {id:null},
				Ajax : {url:'', imgLoader : '/img/ajax-loader2.gif'}
			};
			
				// Сливаем настройки в общий объект
			options = jQuery.extend(options,{
				blockOpt : jQuery.extend(blockOpt[options.wrapper],blockOptions),
				sourceOpt : jQuery.extend(sourceOpt[options.source],sourceOptions),
				tTimer : null //метка таймера
			});			

			var wrapper, caller = $(this), win = eval('new IL_win_'+options.wrapper+'(options)');

				// При убирании курсора с вызывающего объекта очищаем tTimer
				// но только в случае, если окно еще не открыто (иначе мы не дадим окну закрыться)
			$(this).mouseout(function(){
				if ('undefined' == typeof wrapper) {
					win.stopClose(options); // остановить закрытие 
				} else {
					win.close($(wrapper), options);	//инициировать закрытие		
				}
			});
			
			options.tTimer = setTimeout(function(){
		
				wrapper = win.createWrapper(); // Создаем оболочку. Здесь wrapper без var!!!
				$(wrapper).append(win.createTitle(options.blockOpt.title));//Вставляем заголовочный блок
				var contentWrapper = win.createContentWrapper(options);// Создаем оболочку для блока информации
				$(wrapper).css('width',options.width).css('height',options.height);
				$(wrapper).css('visibility','hidden').append($(contentWrapper));
				
				$(wrapper).IL_setInfo(options, win, caller); // Вставляем информационный блок

			}, options.blockOpt.tInterval);
			
		return false;
	}

	

	/**
	* Прокси-метод для прозрачного вызова одного из двух последующих
	*/
	jQuery.fn.IL_setInfo = function(options, win, caller) {
		eval('$(this).IL_setInfoBy'+options.source+'(options, win, caller)');
		return $(this);
	}
	
	/**
	* Биндит информацию из результата ajax-запроса
	*/		
	jQuery.fn.IL_setInfoByAjax = function(options, win, caller) {
		$('<img src="'+options.sourceOpt.imgLoader+'" alt="" id="ajax-loading"/>').css('position','absolute')
			.css('top', $(caller).offset().top).css('left', $(caller).offset().left)
			.css('z-index', 102).appendTo('body');		
		$.ajax({
			url:options.sourceOpt.url,
			context:this,
			cache:false,
			dataType: 'html',
			success: function (data, status){
				$(this).find('.IL_contentWrapper').append(data);
				$(this).IL_setWrapperSize(options, win, caller);
				$('#ajax-loading').remove();
			},
			error: function (data, status, e){
				alert('Error: ' + e);
			}
		})
	}
	
	/**
	* Биндит информацию из элемента с заданным ID
	*/	
	jQuery.fn.IL_setInfoById = function(options, win, caller) {
		$(this).find('.IL_contentWrapper').append($('#'+options.sourceOpt.id).html());
		$(this).IL_setWrapperSize(options, win, caller);
	}	
	

	/**
	* Корректировка размеров, назначение обработчиков 
	* Метод вызывается после того, как получили и забиндили информацию
	*/	
	jQuery.fn.IL_setWrapperSize = function(options, win, caller){
		
		$(this).appendTo('body');	
			// Корректируем ширину заголовочного блока
		win.correctTitleWidth($(this), options);		
			// Вешаем на кнопку "закрыть" (если она есть) событие закрытия (раньше нельзя, нужно передавать объект враппера)
		win.setCloseButton($(this), options);

		$(this).mouseover(function(){
			win.stopClose(options); // остановить закрытие 
		}).mouseout(function(){
			win.close($(this), options); //инициировать закрытие
		});    

		$(this).IL_setWrapperOffset(caller).css('visibility','visible');       
	}  
	
	
	/**
	* Устанавливает позицию всплывающего окна относительно вызывающего элемента
	* @param object элемент, на кот. произошло событие!doctype
	* @return this (объект всплывающего окна)
	*/
	jQuery.fn.IL_setWrapperOffset = function(caller) {
		var top, left;
		var callerLeft   = $(caller).offset().left - $(document).scrollLeft();//расстояние от левого края окна браузера до левого края вызывающего эл-та
		var callerRight  = callerLeft + $(caller).width();					//расстояние от левого края окна браузера до правого края вызывающего эл-та
		var callerTop    = $(caller).offset().top - $(document).scrollTop(); //расстояние от верхнего края окна браузера до верхнего края вызывающего эл-та
		var callerBottom = callerTop + $(caller).height();                  //расстояние от верхнего края окна браузера до нижнего края вызывающего эл-та

			// Расстояние от левого края окна браузера до правого края ВЭ (вызывающего эл-та) больше ширины открываемого окна
		if ( callerRight >= $(this).outerWidth() )  {
			left = callerRight - $(this).outerWidth();
			// Расстояние от правого края вызывающего эл-та до правого края окна браузера больше ширины открываемого окна
		} else if ( $(window).width() - callerRight > $(this).outerWidth()) {
			left = callerLeft;			
			// Расстояние от левого края документа (НЕ окна браузера!) до правого края ВЭ меньше ширины открываемого окна
		} else if ( $(caller).offset().left - callerLeft < $(this).outerWidth() ) { 
			left = callerLeft;
		} else {
			left = callerRight - $(this).outerWidth();
		}

			// Расстояние от нижнего края ВЭ до нижнего края окна браузера больше высоты открываемого окна 
			// или растояние от верхнего края ВЭ до верхнего края документа(НЕ окна браузера!) меньше высоты открываемого окна 
		if ( $(window).height() - callerBottom > $(this).outerHeight() || $(caller).offset().top < $(this).outerHeight() ) { 
			top = callerBottom;
		} else {
			top = callerTop - $(this).outerHeight();
		}
		$(this).offset({top: top+$(document).scrollTop(), left: left+$(document).scrollLeft()});
		return $(this);
	}	
	
	

	/**
	* Базовое окно, о которого наследуем
	*/
	var IL_win = newClass(null, {
		constructor: function() {},
		createWrapper : function(){
			return $('<div class="popup IL_wrapper" />');
		},
		createContentWrapper : function(options){
			return $('<div class="'+options.cssCW+' IL_contentWrapper" />');
		},
		correctTitleWidth : function(obj, options){
			var tmp = $(obj).width() - $(obj).find('.IL_closeButton').outerWidth() - options.blockOpt.titleWidthCorrector;
			$(obj).find('.IL_title').width(tmp);
			return obj;
		},        
		stopClose : function(options){
			if (options.tTimer != null) {
				clearTimeout(options.tTimer);
				options.tTimer = null;
			}                    
			return options.tTimer;                        
		}        
	}); 

	/**
	* Окно без заголовка
	*/
	var IL_win_normalBlock = newClass(IL_win, {
		constructor: function() {
			this.constructor.prototype.constructor.call(this);
		},
		createTitle : function(){return '';},
		setCloseButton : function(obj){return obj;},    
		close : function(obj, options){
			options.tTimer = setTimeout(function(){
				$(obj).remove();
			}, options.blockOpt.tInterval);
			return options.tTimer;
		}
	}); 


	/**
	* Окно с заголовком и с кнопкой "закрыть"
	*/
	var IL_win_titleBlock = newClass(IL_win, {
		constructor: function() {
			this.constructor.prototype.constructor.call(this);
		},
		createTitle : function(title){
			return $('<div class="IL_titleBlock" />') // Оболочка для блока заголовка и кнопки "закрыть"
				.append($('<div class="IL_title" />').append(title)) // Блок заголовка
				.append($('<div class="close IL_closeButton" />').append('&times;')); // Кнопка "закрыть"
		},    
		setCloseButton : function(obj){
			$(obj).find('.IL_closeButton').click(function(){
				$(obj).remove();
			});    
			return obj;
		},
		close : function(obj, options){return options.tTimer;}    
	});
	
	/**
	* Окно с кнопкой "закрыть" но без заголовка
	*/
	var IL_win_noTitleBlock = newClass(IL_win_titleBlock, {
		createTitle : function(title){
			return $('<div class="IL_titleBlock" />') // Оболочка для блока заголовка и кнопки "закрыть"
				.append($('<div class="close IL_closeButton" />').append('&times;')); // Кнопка "закрыть"
		} 		
	});	
	
	/**
	* Окно без ничего, только общий враппер
	*/
	var IL_win_noNoBlock = newClass(IL_win, {
		createWrapper : function(){
			return $('<div class="IL_wrapper" />');
		},	
		createTitle : function(title){return '';} ,
		correctTitleWidth : function(obj, options){
			return obj;
		},   		
		setCloseButton : function(obj){
			$(obj).find('.close').click(function(){
				$(obj).remove();
			});    
			return obj;
		},
		close : function(obj, options){return options.tTimer;} 		
	});		
	

	
	/**
	* упрощает организацию наследования 
	* Отсюда: http://dklab.ru/chicken/nablas/40.html#list15
	*/
	function newClass(parent, prop) {
	  // Dynamically create class constructor.
	  var clazz = function() {
		// Stupid JS need exactly one "operator new" calling for parent
		// constructor just after class definition.
		if (clazz.preparing) return delete(clazz.preparing);
		// Call custom constructor.
		if (clazz.constr) {
		  this.constructor = clazz; // we need it!
		  clazz.constr.apply(this, arguments);
		}
	  }
	  clazz.prototype = {}; // no prototype by default
	  if (parent) {
		parent.preparing = true;
		clazz.prototype = new parent;
		clazz.prototype.constructor = parent;
		clazz.constr = parent; // BY DEFAULT - parent constructor
	  }
	  if (prop) {
		var cname = "constructor";
		for (var k in prop) {
		  if (k != cname) clazz.prototype[k] = prop[k];
		}
		if (prop[cname] && prop[cname] != Object)
		  clazz.constr = prop[cname];
	  }
	  return clazz;
	}
	
	/*
	Примеры использования
	
	$(document).ready(function(){
		$('.myslass').each(function(){
			$(this).mouseover(function(){
				$(this).infoLayer({}, {}, {id:'myid'}) // вставляем в обычное окно информацию из скрытого блока с id=myid
			});
		});
	});	
	
	<a href="#" onmouseover="$(this).infoLayer({wrapper:'titleBlock'},{tInterval:800},{id:'asdf'}); ">qwerqwer</a>

	<a href="#" class="myslass">asdfasdfasf</a>
	
	<a href="#" onclick="$(this).infoLayer({wrapper:'titleBlock',source:'Ajax',width:300},{title:'йцукйцку11',tInterval:0},{url:'/login.html'}); ">zxcv</a>
	
	*/
	
	/* вариант стиля окон
	.IL_wrapper {
		position: absolute; 
		z-index: 10;
		background-color: #FDFEFE; 
		border: 1px solid #79B7E7;
		width:50px;
	}
	.IL_titleBlock {height:25px;}
	.IL_title { 
		float:left;
		background-color: #5497CA;
		border: 1px solid #6EA6D1;
		color:#FFFBDF; 
		margin:5px 5px 0 5px;
		padding: 1px 5px 1px 5px;
		height:15px;
		font-size:12px;
		font-weight:bold;	
		line-height:1.2em;	
	}
	.IL_closeButton	{ 
		float:right;
		width:19px;
		height:19px;
		margin:5px 5px 0 0;
		text-align:center;
		background-color: #F75F5F; 
		color:#F5F8F9; 	
		cursor:pointer;
		font-size:30px;
		font-weight:bold;
		line-height:0.6em;		
	}
	.IL_contentWrapper{
		margin:5px 5px 5px 5px;
		padding:2px 1px 2px 2px;
		background-color:#E3F1FC;
		border: 1px solid #CCE4FB;
		width:auto;		
	}	
	*/
	
