	tsControl.Autocomplete = Class.create();
	tsControl.Autocomplete.prototype = Object.extend(tsControl.Autocomplete,{
		initialize: function(control,options){
			this.items = [];
			this.classes = ['cnt_loading', 'passed','failed','cnt0','cnt1','cnt2'];
			this.control = $(control);
			this.container = null;
			this.target = this.control.up();
			this.timer = false;
			this.hider = false;
			this.value = '';
			this.cnt = 0;
			this.hideCnt = 0;
			this.options = Object.extend({
				url : false,
				method : 'POST',
				row_template : '<tr><td><a href="javascript:void(0);" selectable="#{haveChild}" nodeId="#{id}" path="#{path}">#{text}</td></tr>',
				Tree : null,
				interval : 3  // in a second
			},options || {});
			this.createContainer().hide();
			this.listener = this.keyListener.bindAsEventListener(this);
			this.blurListener = this.onBlur.bindAsEventListener(this);
			this.menuListener = this.menuObserver.bindAsEventListener(this);
			this.menuClicker = this.menuClick.bindAsEventListener(this);
			Event.observe( this.control, 'keydown', this.listener );
			Event.observe( this.control, 'keyup', this.listener );
			Event.observe( this.control, 'blur', this.blurListener );
			Event.observe( this.container, 'mouseout', this.menuListener );
			Event.observe( this.container, 'click', this.menuClicker );
			return this;
		},
		createContainer : function(){
			this.container = new Element( 'div', { className : 'searchBox' }).setStyle( {'position':'absolute', 'z-index':'9999'} );
			this.target.insert(this.container);
			return this.container;
		},
		keyListener : function(event){
			if (this.timer){
				this.classes.each(function(className){ this.control.removeClassName(className);}.bind(this));
				this.timer.stop();
			}
			var value = this.control.value.strip();
			var paste = false;
			paste = ( (event.ctrlKey && event.keyCode==86) || (event.shiftKey && event.keyCode==45) );
			if ( (value!='' && event.type=='keyup') || event.keyCode==13 || paste ){
				this.container.hide();
				this.startTimer();
			}
			this.value = value;
		},
		startTimer : function(callback){
			this.cnt = 0;
			this.timer = new PeriodicalExecuter(function(pe){
				this.classes.each(function(className){ this.control.removeClassName(className);}.bind(this));
				this.control.addClassName('cnt'+this.cnt);
				if (++this.cnt>=this.options.interval){
					this.timer.stop();
					this.cnt = 0;
					this.timer = false;
					this.getContent(callback);
				}
			}.bind(this),.5);
		},
		getTree : function(){
			if (typeof(this.options.Tree)=='object') return this.options.Tree;
			else return null;
		},
		getContent : function(callback){
			var params = {'query' : this.control.value.strip()};
			this.control.addClassName('cnt_loading');
			if (this.options.url)
			new Ajax.Request(this.options.url,{
				method : this.options.method,
				parameters : params,
				onComplete : function(transport){
					$A($$('.searchBox')).invoke('hide');
					str = ' var tmp_obj = '+transport.responseText;
					this.classes.each(function(className){ this.control.removeClassName(className);}.bind(this));
					tmp_obj = [];
					eval(str);
					var i=0;
					var strupdate = '<table>';
					for( i=0; i<tmp_obj.length; i++ ){
						var myTemplate = new Template(this.options.row_template); 
						strupdate+= myTemplate.evaluate(tmp_obj[i]); 
					}
					strupdate+='</table>';
					this.container.update(strupdate).show();
					var pos = this.control.positionedOffset();
					pos[1]+=this.control.getHeight();
					this.container.setStyle({'top':pos[1]+'px', 'left' : pos[0]+'px'});
					if ( tmp_obj.length > 0 ) this.control.addClassName('passed');
					else{
						this.control.addClassName('failed');
						this.container.hide();
					}
				}.bind(this)
			});
		},
		onBlur : function(event){
			if (this.timer) this.timer.stop();
			this.cnt = 0;
			this.timer = false;
			this.classes.each(function(className){ this.control.removeClassName(className);}.bind(this));
		},
		menuObserver : function(event){
			var elm = Event.element(event);
			if (!$(elm).descendantOf(this.container)){
				this.hider = new PeriodicalExecuter(function(pe){
					if (++this.hideCnt>3){
						pe.stop();
						this.hider = false;
						this.hideCnt = 0;
						this.container.hide();
					}
				}.bind(this),1);
			}else{
				if (this.hider) this.hider.stop();
				this.hider = false;
				this.hideCnt = 0;
			}
			Event.stop(event);
			
		},
		menuClick : function(event){
			var elm = Event.element(event);
			if (elm.tagName=='A'){
				var path = elm.readAttribute('path');
				var nodeId = elm.readAttribute('nodeId');
				var select = elm.readAttribute('selectable');
				if (!this.getTree().getItemById(nodeId)){
					this.getTree().openNodeByPath(path, function(id, obj){
						
						try{
							var mElm = this.getTree().getItemById(id).info;
							if ($(mElm.tControl).visible()) if (select && (this.getTree().options.selectAll || !mElm.haveChild)) this.getTree().checkNode(nodeId);
							if (this.getTree().options.parent.sysSelector.target.visible()) this.getTree().options.parent.sysSelector.updateItemList( this.getTree().items );
							this.getTree().updateComponents();
						}catch(e){};
						this.container.hide();
					}.bind(this));
				}else{
					
					try{
						var mElm = this.getTree().getItemById(nodeId).info;
						if ($(mElm.tControl).visible()) if (select && (this.getTree().options.selectAll || !mElm.haveChild)) this.getTree().checkNode(nodeId);
						this.getTree().updateComponents();
						this.getTree().updateInput();
						
						if (this.getTree().options.parent.sysSelector.target.visible()){
							this.getTree().options.parent.sysSelector.updateItemList( this.getTree().items );
						}
					} catch(e){};
					this.container.hide();
				}
			}
			Event.stop(event);
		}
	});