
var actb = Class.create();
actb.prototype = {
    initialize: function(obj, valueObj, ca, cv, selected) {
	/* ---- Public Variables ---- */
	this.actb_timeOut = -1; // Autocomplete Timeout in ms (-1: autocomplete never time out)
	this.actb_lim = 10;    // Number of elements autocomplete can show (-1: no limit)
	this.actb_firstText = false; // should the auto complete be limited to the beginning of keyword?
	this.actb_mouse = true; // Enable Mouse Support
	this.actb_delimiter = new Array(';',',');  // Delimiter for multiple autocomplete. Set it to empty array for single autocomplete
	this.actb_startcheck = 1; // Show widget only after this number of characters is typed in.
        this.actb_allowMissing = false; // Allow entry of values that are not in the array

	/* ---- Public Variables ---- */

	/* --- Styles --- */
	this.actb_bgColor = '#888888';
	this.actb_textColor = '#FFFFFF';
	this.actb_hColor = '#000000';
	this.actb_fFamily = 'Verdana';
	this.actb_fSize = '11px';
	this.actb_hStyle = 'text-decoration:underline;font-weight="bold"';

	/* --- Styles --- */

	/* ---- Private Variables ---- */
	this.actb_delimwords = new Array();
	this.actb_cdelimword = 0;
	this.actb_delimchar = new Array();
	this.actb_display = false;
	this.actb_pos = 0;
	this.actb_total = 0;
	this.actb_curr = null;
	this.actb_rangeu = 0;
	this.actb_ranged = 0;
	this.actb_bool = new Array();
	this.actb_pre = 0;
	this.actb_toid;
	this.actb_tomake = false;
	this.actb_getpre = "";
	this.actb_mouse_on_list = 1;
	this.actb_kwcount = 0;
	this.actb_caretmove = false;
	this.actb_keywords = new Array();
        this.actb_values = new Array();

	/* ---- Private Variables---- */
	this.actb_keywords = ca;
        this.actb_values = cv;

        /* The display field */
	this.actb_curr = obj;
        /* The value field */
        this.actb_currValue = valueObj;

        if (selected > 0) {
            this.actb_curr.value = this.actb_keywords[selected];
            this.actb_currValue.value = this.actb_values[selected];
        }

	addEvent(this.actb_curr, "focus", this.actb_setup.bind(this));

    },

    actb_setup: function() {
        addEvent(document,"keydown",this.actb_checkkey.bind(this));
	addEvent(this.actb_curr,"blur",this.actb_clear.bind(this));
	addEvent(document,"keypress",this.actb_keypress.bind(this));
    },

    actb_clear: function(evt) {
	if (!evt) evt = event;
	removeEvent(document,"keydown",this.actb_checkkey.bind(this));
	removeEvent(this.actb_curr,"blur",this.actb_clear.bind(this));
	removeEvent(document,"keypress",this.actb_keypress.bind(this));
	if ((this.actb_currValue.value == null || this.actb_currValue.value.length == 0) && this.actb_allowMissing == false) {
	    this.actb_curr.value = "";
	}
        this.actb_removedisp();
    },

    actb_parse: function(n){
        if (this.actb_delimiter.length > 0){
            var t = this.actb_delimwords[this.actb_cdelimword].trim().addslashes();
            var plen = this.actb_delimwords[this.actb_cdelimword].trim().length;
        } else {
            var t = this.actb_curr.value.addslashes();
            var plen = this.actb_curr.value.length;
        }
        var tobuild = '';
        var i;

	if (this.actb_firstText){
            var re = new RegExp("^" + t, "i");
        } else {
            var re = new RegExp(t, "i");
        }
        var p = n.search(re);
        for (i = 0; i < p; i++) {
            tobuild += n.substr(i,1);
        }
        tobuild += "<font style='"+(this.actb_hStyle)+"'>"
	for (i = p; i < plen + p; i++) {
            tobuild += n.substr(i,1);
        }
        tobuild += "</font>";
	
        for (i=plen+p;i<n.length;i++){
            tobuild += n.substr(i,1);
        }
        return tobuild;
    },

    actb_generate: function() {
        if (document.getElementById('tat_table')){ this.actb_display = false;document.body.removeChild(document.getElementById('tat_table')); } 
            if (this.actb_kwcount == 0){
                this.actb_display = false;
                return;
            }
            a = document.createElement('table');
            a.cellSpacing='1px';
            a.cellPadding='2px';
            a.style.position='absolute';
            a.style.top = eval(curTop(this.actb_curr) + this.actb_curr.offsetHeight) + "px";
            a.style.left = curLeft(this.actb_curr) + "px";
            a.style.backgroundColor=this.actb_bgColor;
            a.id = 'tat_table';
            a.style.width = this.actb_curr.style.width;
            document.body.appendChild(a);
            var i;
            var first = true;
            var j = 1;
		if (this.actb_mouse){
			a.onmouseout = this.actb_table_unfocus.bind(this);
			a.onmouseover = this.actb_table_focus.bind(this);
		}
		var counter = 0;
		for (i=0;i<this.actb_keywords.length;i++){
			if (this.actb_bool[i]){
				counter++;
				r = a.insertRow(-1);
				if (first && !this.actb_tomake){
					r.style.backgroundColor = this.actb_hColor;
					first = false;
					this.actb_pos = counter;
				}else if(this.actb_pre == i){
					r.style.backgroundColor = this.actb_hColor;
					first = false;
					this.actb_pos = counter;
				}else{
					r.style.backgroundColor = this.actb_bgColor;
				}
				r.id = 'tat_tr'+(j);
				c = r.insertCell(-1);
				c.style.color = this.actb_textColor;
				c.style.fontFamily = this.actb_fFamily;
				c.style.fontSize = this.actb_fSize;
				c.innerHTML = this.actb_parse(this.actb_keywords[i]);
				c.id = 'tat_td'+(j);
				c.setAttribute('pos',j);
				if (this.actb_mouse){
					c.style.cursor = 'pointer';
					c.onclick=this.actb_mouseclick.bind(this, c);
					c.onmouseover = this.actb_table_highlight.bind(this, c);
				}
				j++;
			}
			if (j - 1 == this.actb_lim && j < this.actb_total){
				r = a.insertRow(-1);
				r.style.backgroundColor = this.actb_bgColor;
				c = r.insertCell(-1);
				c.style.color = this.actb_textColor;
				c.style.fontFamily = 'arial narrow';
				c.style.fontSize = this.actb_fSize;
				c.align='center';
				replaceHTML(c,'\\/');
				if (this.actb_mouse){
					c.style.cursor = 'pointer';
					c.onclick = this.actb_mouse_down.bind(this);
				}
				break;
			}
		}
		this.actb_rangeu = 1;
		this.actb_ranged = j-1;
		this.actb_display = true;
		if (this.actb_pos <= 0) this.actb_pos = 1;
	},
	
	
	actb_remake: function(){
		document.body.removeChild(document.getElementById('tat_table'));
		a = document.createElement('table');
		a.cellSpacing='1px';
		a.cellPadding='2px';
		a.style.position='absolute';
		a.style.top = eval(curTop(this.actb_curr) + this.actb_curr.offsetHeight) + "px";
		a.style.left = curLeft(this.actb_curr) + "px";
		a.style.backgroundColor=this.actb_bgColor;
		a.id = 'tat_table';
		if (this.actb_mouse){
			a.onmouseout= this.actb_table_unfocus.bind(this);
			a.onmouseover= this.actb_table_focus.bind(this);
		}
		document.body.appendChild(a);
		var i;
		var first = true;
		var j = 1;
		if (this.actb_rangeu > 1){
			r = a.insertRow(-1);
			r.style.backgroundColor = this.actb_bgColor;
			c = r.insertCell(-1);
			c.style.color = this.actb_textColor;
			c.style.fontFamily = 'arial narrow';
			c.style.fontSize = this.actb_fSize;
			c.align='center';
			replaceHTML(c,'/\\');
			if (this.actb_mouse){
				c.style.cursor = 'pointer';
				c.onclick = this.actb_mouse_up.bind(this);
			}
		}
		for (i=0;i<this.actb_keywords.length;i++){
			if (this.actb_bool[i]){
				if (j >= this.actb_rangeu && j <= this.actb_ranged){
					r = a.insertRow(-1);
					r.style.backgroundColor = this.actb_bgColor;
					r.id = 'tat_tr'+(j);
					c = r.insertCell(-1);
					c.style.color = this.actb_textColor;
					c.style.fontFamily = this.actb_fFamily;
					c.style.fontSize = this.actb_fSize;
					c.innerHTML = this.actb_parse(this.actb_keywords[i]);
					c.id = 'tat_td'+(j);
					c.setAttribute('pos',j);
					if (this.actb_mouse){
						c.style.cursor = 'pointer';
						c.onclick= this.actb_mouseclick.bind(this, c);
						c.onmouseover = this.actb_table_highlight.bind(this, c);
					}
					j++;
				}else{
					j++;
				}
			}
			if (j > this.actb_ranged) break;
		}
		if (j-1 < this.actb_total){
			r = a.insertRow(-1);
			r.style.backgroundColor = this.actb_bgColor;
			c = r.insertCell(-1);
			c.style.color = this.actb_textColor;
			c.style.fontFamily = 'arial narrow';
			c.style.fontSize = this.actb_fSize;
			c.align='center';
			replaceHTML(c,'\\/');
			if (this.actb_mouse){
				c.style.cursor = 'pointer';
				c.onclick = this.actb_mouse_down.bind(this);
			}
		}
	},
	
	
	actb_goup: function(){
		if (!this.actb_display) return;
		if (this.actb_pos == 1) return;
		document.getElementById('tat_tr'+this.actb_pos).style.backgroundColor = this.actb_bgColor;
		this.actb_pos--;
		if (this.actb_pos < this.actb_rangeu) this.actb_moveup();
		document.getElementById('tat_tr'+this.actb_pos).style.backgroundColor = this.actb_hColor;
		if (this.actb_toid) clearTimeout(this.actb_toid);
		if (this.actb_timeOut > 0) this.actb_toid = setTimeout(function(){this.actb_mouse_on_list=0; this.actb_removedisp();}.bind(this),this.actb_timeOut);
	},
	
	actb_godown: function(){
		if (!this.actb_display) return;
		if (this.actb_pos == this.actb_total) return;
		document.getElementById('tat_tr'+this.actb_pos).style.backgroundColor = this.actb_bgColor;
		this.actb_pos++;
		if (this.actb_pos > this.actb_ranged) this.actb_movedown();
		document.getElementById('tat_tr'+this.actb_pos).style.backgroundColor = this.actb_hColor;
		if (this.actb_toid) clearTimeout(this.actb_toid);
		if (this.actb_timeOut > 0) this.actb_toid = setTimeout(function(){this.actb_mouse_on_list=0;this.actb_removedisp();}.bind(this),this.actb_timeOut);
	},
	
	actb_movedown: function(){
		this.actb_rangeu++;
		this.actb_ranged++;
		this.actb_remake();
	},
	
	actb_moveup: function(){
		this.actb_rangeu--;
		this.actb_ranged--;
		this.actb_remake();
	},

	/* Mouse */
	actb_mouse_down: function(){
		document.getElementById('tat_tr'+this.actb_pos).style.backgroundColor = this.actb_bgColor;
		this.actb_pos++;
		this.actb_movedown();
		document.getElementById('tat_tr'+this.actb_pos).style.backgroundColor = this.actb_hColor;
		this.actb_curr.focus();
		this.actb_mouse_on_list = 0;
		if (this.actb_toid) clearTimeout(this.actb_toid);
		if (this.actb_timeOut > 0) this.actb_toid = setTimeout(function(){this.actb_mouse_on_list=0;this.actb_removedisp();}.bind(this), this.actb_timeOut);
	},
	actb_mouse_up: function(evt){
		if (!evt) evt = event;
		if (evt.stopPropagation){
			evt.stopPropagation();
		}else{
			evt.cancelBubble = true;
		}
		document.getElementById('tat_tr'+this.actb_pos).style.backgroundColor = this.actb_bgColor;
		this.actb_pos--;
		this.actb_moveup();
		document.getElementById('tat_tr'+this.actb_pos).style.backgroundColor = this.actb_hColor;
		this.actb_curr.focus();
		this.actb_mouse_on_list = 0;
		if (this.actb_toid) clearTimeout(this.actb_toid);
		if (this.actb_timeOut > 0) this.actb_toid = setTimeout(function(){this.actb_mouse_on_list=0;this.actb_removedisp();}.bind(this),this.actb_timeOut);
	},
	actb_mouseclick: function(c, evt){
		if (!evt) evt = event;
		if (!this.actb_display) return;
		this.actb_mouse_on_list = 0;
		this.actb_pos = c.getAttribute('pos');
		this.actb_penter();
	},
	actb_table_focus: function(){
		this.actb_mouse_on_list = 1;
	},
	actb_table_unfocus: function(){
		this.actb_mouse_on_list = 0;
		if (this.actb_toid) clearTimeout(this.actb_toid);
		if (this.actb_timeOut > 0) this.actb_toid = setTimeout(function(){this.actb_mouse_on_list = 0; this.actb_removedisp();}.bind(this), this.actb_timeOut);
	},
	actb_table_highlight: function(c){
		this.actb_mouse_on_list = 1;
		document.getElementById('tat_tr'+this.actb_pos).style.backgroundColor = this.actb_bgColor;
		this.actb_pos = c.getAttribute('pos');
		while (this.actb_pos < this.actb_rangeu) this.actb_moveup();
		while (this.actb_pos > this.actb_ranged) this.actb_movedown();
		document.getElementById('tat_tr'+this.actb_pos).style.backgroundColor = this.actb_hColor;
		if (this.actb_toid) clearTimeout(this.actb_toid);
		if (this.actb_timeOut > 0) this.actb_toid = setTimeout(function(){this.actb_mouse_on_list = 0; this.actb_removedisp();}.bind(this), this.actb_timeOut);
	},
	/* ---- */

	actb_insertword: function(a){
		if (this.actb_delimiter.length > 0){
			str = '';
			l=0;
			for (i=0;i<this.actb_delimwords.length;i++){
				if (this.actb_cdelimword == i){
					prespace = postspace = '';
					gotbreak = false;
					for (j=0;j<this.actb_delimwords[i].length;++j){
						if (this.actb_delimwords[i].charAt(j) != ' '){
							gotbreak = true;
							break;
						}
						prespace += ' ';
					}
					for (j=this.actb_delimwords[i].length-1;j>=0;--j){
						if (this.actb_delimwords[i].charAt(j) != ' ') break;
						postspace += ' ';
					}
					str += prespace;
					str += a;
					l = str.length;
					if (gotbreak) str += postspace;
				}else{
					str += this.actb_delimwords[i];
				}
				if (i != this.actb_delimwords.length - 1){
					str += this.actb_delimchar[i];
				}
			}
			this.actb_curr.value = str;
			this.setCaret(this.actb_curr,l);
		}else{
			this.actb_curr.value = a;
		}
		this.actb_mouse_on_list = 0;
		this.actb_removedisp();
	},

        actb_insertword2: function(position) {
            this.actb_insertword(this.actb_keywords[position]);
            this.actb_currValue.value = this.actb_values[position];
            this.actb_mouse_on_list = 0;
            this.actb_removedisp();
        },
	actb_penter: function(){
		if (!this.actb_display) return;
		this.actb_display = false;
		var word = '';
                var wordPosition = -1;
		var c = 0;
		for (var i=0;i<=this.actb_keywords.length;i++){
			if (this.actb_bool[i]) c++;
			if (c == this.actb_pos){
				word = this.actb_keywords[i];
                                wordPosition = i;
				break;
			}
		}
		// actb_insertword(word);
                this.actb_insertword2(wordPosition);
		l = this.getCaretStart(this.actb_curr);
	},
	actb_removedisp: function(){
		if (this.actb_mouse_on_list==0){
			this.actb_display = 0;
			if (document.getElementById('tat_table')){ document.body.removeChild(document.getElementById('tat_table')); }
			if (this.actb_toid) clearTimeout(this.actb_toid);
		}
	},
	actb_keypress: function(e){
		if (this.actb_caretmove) stopEvent(e);
		return !(this.actb_caretmove);
	},
	actb_checkkey: function(evt){
		if (!evt) evt = event;
		a = evt.keyCode;
		caret_pos_start = this.getCaretStart(this.actb_curr);
		this.actb_caretmove = 0;
		switch (a){
			case 38:
				this.actb_goup();
				this.actb_caretmove = 1;
				return false;
				break;
			case 40:
				this.actb_godown();
				this.actb_caretmove = 1;
				return false;
				break;
			case 13: case 9:
				if (this.actb_display){
					this.actb_caretmove = 1;
					this.actb_penter();
					return false;
				}else{
					return true;
				}
				break;
			default:
				setTimeout(function(){this.actb_tocomplete(a)}.bind(this),50);
				break;
		}
	},

	actb_tocomplete: function(kc){
		if (kc == 38 || kc == 40 || kc == 13) return;
		var i;
		if (this.actb_display){ 
			var word = 0;
			var c = 0;
			for (var i=0;i<= this.actb_keywords.length;i++){
				if (this.actb_bool[i]) c++;
				if (c == this.actb_pos){
					word = i;
					break;
				}
			}
			this.actb_pre = word;
		}else{ this.actb_pre = -1};
		
		if (this.actb_curr.value == ''){
			this.actb_mouse_on_list = 0;
			this.actb_removedisp();
			return;
		}
		if (this.actb_delimiter.length > 0){
			caret_pos_start = this.getCaretStart(this.actb_curr);
			caret_pos_end = this.getCaretEnd(this.actb_curr);
			
			delim_split = '';
			for (i=0;i<this.actb_delimiter.length;i++){
				delim_split += this.actb_delimiter[i];
			}
			delim_split = delim_split.addslashes();
			delim_split_rx = new RegExp("(["+delim_split+"])");
			c = 0;
			this.actb_delimwords = new Array();
			this.actb_delimwords[0] = '';
			for (i=0,j=this.actb_curr.value.length;i<this.actb_curr.value.length;i++,j--){
				if (this.actb_curr.value.substr(i,j).search(delim_split_rx) == 0){
					ma = this.actb_curr.value.substr(i,j).match(delim_split_rx);
					this.actb_delimchar[c] = ma[1];
					c++;
					this.actb_delimwords[c] = '';
				}else{
					this.actb_delimwords[c] += this.actb_curr.value.charAt(i);
				}
			}

			var l = 0;
			this.actb_cdelimword = -1;
			for (i=0;i<this.actb_delimwords.length;i++){
				if (caret_pos_end >= l && caret_pos_end <= l + this.actb_delimwords[i].length){
					this.actb_cdelimword = i;
				}
				l+=this.actb_delimwords[i].length + 1;
			}
			var ot = this.actb_delimwords[this.actb_cdelimword].trim(); 
			var t = this.actb_delimwords[this.actb_cdelimword].addslashes().trim();
		}else{
			var ot = this.actb_curr.value;
			var t = this.actb_curr.value.addslashes();
		}
		if (ot.length == 0){
			this.actb_mouse_on_list = 0;
			this.actb_removedisp();
		}
		if (ot.length < this.actb_startcheck) return this;
		if (this.actb_firstText){
			var re = new RegExp("^" + t, "i");
		}else{
			var re = new RegExp(t, "i");
		}

		this.actb_total = 0;
		this.actb_tomake = false;
		this.actb_kwcount = 0;
		for (i=0;i<this.actb_keywords.length;i++){
			this.actb_bool[i] = false;
			if (re.test(this.actb_keywords[i])){
				this.actb_total++;
				this.actb_bool[i] = true;
				this.actb_kwcount++;
				if (this.actb_pre == i) this.actb_tomake = true;
			}
		}

                if (this.actb_kwcount == 0 && this.actb_allowMissing == false) {
                        this.actb_removeCharacter();
                        this.actb_tocomplete(kc);
                }

		if (this.actb_toid) clearTimeout(this.actb_toid);
		if (this.actb_timeOut > 0) this.actb_toid = setTimeout(function(){this.actb_mouse_on_list = 0; this.actb_removedisp();}.bind(this), this.actb_timeOut);
		this.actb_generate();
                this.actb_currValue.value = "";
	},

        actb_removeCharacter: function() {
            if (this.actb_curr.value != null && this.actb_curr.value.length > 0) {
                this.actb_curr.value = this.actb_curr.value.substring(0, this.actb_curr.value.length - 1);
            }
        },
	
/*    Caret Functions     */



// Get the end position of the caret in the object. Note that the obj needs to be in focus first

getCaretEnd: function(obj){

	if(typeof obj.selectionEnd != "undefined"){

		return obj.selectionEnd;

	}else if(document.selection&&document.selection.createRange){

		var M=document.selection.createRange();

		try{

			var Lp = M.duplicate();

			Lp.moveToElementText(obj);

		}catch(e){

			var Lp=obj.createTextRange();

		}

		Lp.setEndPoint("EndToEnd",M);

		var rb=Lp.text.length;

		if(rb>obj.value.length){

			return -1;

		}

		return rb;

	}

},

// Get the start position of the caret in the object

getCaretStart: function(obj){

	if(typeof obj.selectionStart != "undefined"){

		return obj.selectionStart;

	}else if(document.selection&&document.selection.createRange){

		var M=document.selection.createRange();

		try{

			var Lp = M.duplicate();

			Lp.moveToElementText(obj);

		}catch(e){

			var Lp=obj.createTextRange();

		}

		Lp.setEndPoint("EndToStart",M);

		var rb=Lp.text.length;

		if(rb>obj.value.length){

			return -1;

		}

		return rb;

	}

},

// sets the caret position to l in the object

setCaret: function(obj,l){

	obj.focus();

	if (obj.setSelectionRange){

		obj.setSelectionRange(l,l);

	}else if(obj.createTextRange){

		m = obj.createTextRange();		

		m.moveStart('character',l);

		m.collapse();

		m.select();

	}

},

// sets the caret selection from s to e in the object

setSelection: function(obj,s,e){

	obj.focus();

	if (obj.setSelectionRange){

		obj.setSelectionRange(s,e);

	}else if(obj.createTextRange){

		m = obj.createTextRange();		

		m.moveStart('character',s);

		m.moveEnd('character',e);

		m.select();

	}

}


}