function autocomplete(settings) {
	_autocomplete = _ac = this;
	_ac.opts = {
		debug: false,
		style: {
			div: 'autocomplete_box',
			input: 'autocomplete'
		}
	};
	$.extend(_ac.opts, settings);
	
	_ac.inputs = new Array();
	
	_ac.active = '';
	
	_ac.activate = function(name) {
		if(_ac.active != name && _ac.active != '') {
			var n = _ac.active;
			_ac.deactivate(n);
		}
			_ac.inputs[name]['box'].fadeTo(50, 1);
			_ac.active = name;
			//_ac.inputs[name]['object'].bind('keypress', function(event) { _ac.keys(event, $(this)); });
		
	}
	
	_ac.deactivate = function(name, del, fade) {
		if(fade) {
			_ac.inputs[name]['box'].fadeTo(50, 0);
		}
		if(del) {
			_ac.inputs[name]['box'].empty();
		}
		_ac.active = '';
		//_ac.inputs[name]['object'].unbind('keypress');
	}
	/*
	_ac.keys = function(event, obj) {
		
		if(!event) { event = window.event; }
		if (event.keyCode) var code = event.keyCode;
		else if (event.which) var code = event.which;
		
		var obj = obj;
		var name = obj.attr('id');
		if(_ac.active==name) {
			if(!_ac.inputs[name]['select']) {
				_ac.select(_ac.inputs[name]['box'].find('li').eq(0), name);
			}
			
			var sel = (_ac.inputs[name]['box'].find('li').index(_ac.inputs[name]['select']) +1);
			var allamount = _ac.inputs[name]['data'].length;
			
			if(code==38) {
				if(allamount<2) {
					_ac.select(_ac.inputs[name]['box'].find('li').eq(0), name);
				} else {
					if(sel>1) {
						_ac.select(_ac.inputs[name]['box'].find('li').eq(sel-1), name);
					}
				}
			}
			if(code==40) {
				if(allamount>2) {
					_ac.select(_ac.inputs[name]['box'].find('li').eq(0), name);
				} else {
					if(sel<allamount) {
						_ac.select(_ac.inputs[name]['box'].find('li').eq(sel+1), name);
					}
				}
			}
			console.log(sel);
			console.log(_ac.inputs[name]['select']);
		}
	}
	*/
	_ac.select = function(obj, name) {
		_ac.inputs[name]['select'] = obj;
		obj.addClass('hover');
	}
	_ac.unselect = function(name) {
		_ac.inputs[name]['select'].removeClass('hover');
	}
	_ac.click = function(obj, name) {
		var a = _ac.inputs[name]['settings']['caption'];
		var b = obj.find(a);
		_ac.inputs[name]['object'].val(b.text()).trigger('blur');
		_ac.inputs[name]['value'].val(obj.attr('id'));
	}
	
	_ac.check = function(name) {
		
		var val = _ac.inputs[name]['object'].val();
		
		if(_ac.opts.debug) {
			console.log('Проверка на то что уже введено: '+val+'. Выполняется запрос / поиск.');
		}
		
		var opts = _ac.inputs[name]['settings'];
		
		$.ajax({
			url: opts.ajaxSettings.url,
			data: opts.ajaxSettings.data+val,
			type: opts.ajaxSettings.type,
			success: function(data) {
				var data = eval(data);
				if(data.length>0) {
					if(data.length==1) {
						_ac.fill(data, name, true);
						_ac.inputs[name]['box'].find('li').trigger('click');
						if(_ac.opts.debug) {
							console.log(_ac.inputs[name]['box'].find('li'));
						}
					} else {
						_ac.fill(data, name, true);
					}
				} else {
					box.empty().fadeTo(50, 0);
				}
			}
		});
	}
	
	_ac.fill = function(data, name, hide) {	

		var obj = $('#'+name);
		var template = _ac.inputs[name]['settings']['template'];
		var box = _ac.inputs[name]['box'];
		var data = eval(data);

		box.empty();
		
		_ac.inputs[name]['data'] = data;
		if(data) {
		for(i=0;i<data.length;i++) {
			var pat = /\{([a-z]*_*[a-z]*)\}/g
			var arr = template.match(pat);
			var tem = template;
						
			for(ii=0;ii<arr.length;ii++) {
				var a = arr[ii].slice(1, (arr[ii].length-1));
				var t = eval('data[i].'+a);
				var p = eval('/\{('+a+')\}/');
				tem = tem.replace(p, t);
			}
			box.append(tem);
		}
		
		var li = box.find('li');
		li.bind('mouseenter', function() { _ac.select($(this), name); })
		  .bind('mouseleave', function() { _ac.unselect(name); })
		  .bind('click', function() { _ac.click($(this), name); });
		
		if(_ac.inputs[name]['settings']['adding']) {
			var aop = _ac.inputs[name]['settings']['addSettings'];
			var add = $('<a />', {
				text: aop.text,
				'class': 'adding',
				click: function() {
					var div = $(aop.div);
					div.toggle();
					var s = div.find(':submit');
					var f = div.find('#action');
					s.bind('click', function() {
						var url = f.val();
						f.remove();
						var inps = div.find('input[type!="submit"][type!="hidden"]');
						
						$.ajax({
							url: url,
							type: 'POST',
							data: inps.serialize(),
							success: function(data) {
								_ac.inputs[name]['object'].val(inps.eq(0).val());
								_ac.check(name);
								s.unbind('click');
								div.toggle();
							}
						});
						
						return false;
					});
					
					box.trigger('mouseleave');
				}
			});
			box.append(add);
		
		}
		  
		}
		
		if(!hide) {
			_ac.deactivate(name);
			_ac.activate(name);
			//box.fadeTo(50, 1);
		}
		
	}
	
	_ac.show = function(event) {
		
		var name = $(this).attr('id');
		var box = _ac.inputs[name]['box'];
		
		
		if(!event) { event = window.event; }
		if (event.keyCode) var code = event.keyCode;
		else if (event.which) var code = event.which;

		if( event.type == 'focus' || (code>47 && code<91 || code==8 || code==38 || code==40)){
			if(event.type == 'focus' || code==38 || code==40) {
				_ac.fill(_ac.inputs[name]['data'],name);
			} else {
				_ac.inputs[name]['timer'] = setTimeout(function() {
					
					if($('#'+name).val().length >= _ac.inputs[name]['settings']['min']) {
							var val = $('#'+name).val();
							var opts = _ac.inputs[name]['settings'];
							if(opts.ajax) {
								$.ajax({
									url: opts.ajaxSettings.url,
									data: opts.ajaxSettings.data+val,
									type: opts.ajaxSettings.type,
									success: function(data) {
										if(data.length>0) {
											_ac.fill(data, name);
										} else {
											_ac.deactivate(name);
											//box.empty().fadeTo(50, 0);
										}
									}
								});
							} else {
								_ac.fill(opts.json, name);
							}
					} else {
						_ac.deactivate(name);
						//box.empty().fadeTo(50, 0);
					}
							
				}, 50);	
			}	
		} else {
			_ac.deactivate(name);
			//box.empty().fadeTo(50, 0);
		}
	}
	
	_ac.hide = function() {
			
		var name = $(this).attr('id');
		var box = _ac.inputs[name]['box'];
		
		_ac.inputs[name]['select'] = '';
		
		_ac.inputs[name]['timer'] = setTimeout(function() {
			_ac.deactivate(name, true, true);
			//box.empty().fadeTo(50, 0);
		}, 200);
		
	}
	
	_ac.add = function(obj, settings) {
		var opts = {
			adding: false,
			addSettings: { div: '', text: 'Добавить новую запись'},
			ajax: true,
			json: {},
			min: 2,
			maxHeight: 400,
			ajaxSettings: {
				url: 'index.php',
				data: 'mod=admin_news&op=search_source&source_value=',
				type: 'POST'
			},
			template: '<li id="{source_id}" style="background-image: url({source_url}favicon.ico)"><b>{source_name}</b><a>{source_url}</a></li>',
			caption: 'b'
		};
		
		$.extend(opts, settings);
		
		var name = obj.attr('name');
		var rand = parseInt(Math.cos(Math.random())*100000);
		
		if(_ac.opts.style.input) {
			obj.addClass(_ac.opts.style.input);
		}

		_ac.inputs[name] = {'object': obj, 'id': obj.attr('id'), 'name':name, 'settings': opts, 'rand': rand};
		obj.attr('name', name+'_input');
		obj.after('<div id="'+name+'_box" class="'+_ac.opts.style.div+'" style="display: none;"></div><input type="hidden" name="'+name+'" id="'+name+'_'+rand+'">');
		var box = $('#'+name+'_box');
		var hidden = $('#'+name+'_'+rand);
		_ac.inputs[name]['box'] = box;
		_ac.inputs[name]['value'] = hidden;
		if($.browser.msie) { // && ($.browser.version == 7.0)
			box.css('margin-top','26px');
		}
		box.css({'width' : obj.outerWidth()+'px', left: obj.offset().left+'px'})
			.bind('mouseenter click', function() { 
				var id = $(this).attr('id').slice(0, -4); clearTimeout(_ac.inputs[id]['timer']); 
				
				$(this).bind('mouseleave', function(event) {
					
					var th = $(this);
					var id = $(this).attr('id').slice(0, -4);
					
					_ac.inputs[id]['timer'] = setTimeout(function() {
						th.empty().fadeTo(50, 0);
					}, 200);
		
				});
			});
		
		obj.bind({
			focus:		_ac.show,
			keydown:	_ac.show,
			blur:		_ac.hide
		});
		
		if(obj.val().length>opts.min) { _ac.check(name); }
		
	}
	
	if(_ac.opts.debug) { console.log(_ac); }
	
}
