// Autocomplete - jsolution.org
var isIE = document.all?true:false;
var isGK = navigator.userAgent.toLowerCase().indexOf('gecko') != -1;
var isOP = navigator.userAgent.toLowerCase().indexOf('opera') != -1;
var __JSAutocompleteMap = new Object();
function JSAutocomplete(jsElemenID, param, useRandom) {
	this.jsUseRandom = true;
	if(useRandom != null) {
		this.jsUseRandom = useRandom;
	}
	this.jsElementID = jsElemenID;
	this.jsLayerElem = document.getElementById(jsElemenID);
	this.jsInputElem = document.getElementById(jsElemenID + '_value');
	if(this.jsInputElem == null) {
		this.jsInputElem = this.jsLayerElem;
	} else {
		this.jsElementID = jsElemenID + '_value';
	}
	this.jsParamElem = document.getElementById(jsElemenID + '_param');
	
	this.jsIFrameElem   = false;
	this.jsDropDownElem = false;
	
	this.jsMax   = 10;
	this.jsRows  = 10;
	this.jsChars = 3;
	this.jsDelay = 500;
	this.jsAjax    = false;
	this.isVisible = false;
	this.jsCache   = new Object();
	this.jsParam   = new Object();
	
	this.jsListener = null;
	
	this.jsData = false;
	if(param != null) {
		if(param['max']!=null)
			this.jsMax = param['max'];
		if(param['rows']!=null)
			this.jsRows = param['rows'];
		if(param['chars']!=null)
			this.jsChars = param['chars'];
		if(param['ajax']!=null)
			this.jsAjax = param['ajax'];
		if(param['data']!=null)
			this.jsData = param['data'];
		if(param['delay']!=null)
			this.jsDelay = param['delay'];
		if(param['listener']!=null)
			this.jsListener = param['listener'];
	}
	this.jsSelectedItem = false;
	this.jsFirstItem    = 0;
	this.jsLastItem     = this.jsRows-1;
	// Create List-Element ----------------------------
	if(this.jsInputElem) {
		__JSAutocompleteMap[this.jsElementID] = this;
        this.jsInputElem.setAttribute('autocomplete', 'off');
        this.jsInputElem.onkeydown  = function(ev) {
			return __JSAutocompleteMap[this.getAttribute('id')].onKeyDownEvent(ev);
		};
        this.jsInputElem.onkeyup    = function(ev) {
			return __JSAutocompleteMap[this.getAttribute('id')].onKeyUpEvent(ev);
		};
        this.jsInputElem.onkeypress = function(ev) {
			return __JSAutocompleteMap[this.getAttribute('id')].onKeyPressEvent(ev);
		};
        this.jsInputElem.ondblclick = function() {
			__JSAutocompleteMap[this.getAttribute('id')].onDblClickEvent();
		};
        this.jsInputElem.onclick    = function(ev) {
			__JSAutocompleteMap[this.getAttribute('id')].onClickEvent(ev);
		};
		
        jsLeft = param['left']!=null?param['left']:
        	acElemOffsetLeft(this.jsLayerElem);
        jsTop = param['top']!=null?param['top']:
        	acElemOffsetTop(this.jsLayerElem) + this.jsLayerElem.offsetHeight;
        width = param['width']!=null?param['width']:
        	this.jsLayerElem.offsetWidth;
    
        this.jsDropDownElem = document.createElement('div');
        this.jsDropDownElem.className = 'autocomplete';
    	this.jsInputElem.parentNode.insertBefore(
			this.jsDropDownElem, this.jsInputElem);
        //this.jsDropDownElem.style.left     = jsLeft + 'px';
        this.jsDropDownElem.style.top        = jsTop + 'px';
        this.jsDropDownElem.style.width      = width + 'px';
        this.jsDropDownElem.style.zIndex     = '999';
        this.jsDropDownElem.style.position   = 'absolute';
        this.jsDropDownElem.style.visibility = 'hidden';
		if(isIE) {
			this.jsIFrameElem = document.createElement('iframe');
            this.jsIFrameElem.id = this.jsElementID +'_iframe';
            this.jsIFrameElem.style.position   = 'absolute';
            this.jsIFrameElem.style.top        = '0';
            this.jsIFrameElem.style.left       = '0';
            this.jsIFrameElem.style.width      = '0px';
            this.jsIFrameElem.style.height     = '0px';
            this.jsIFrameElem.style.zIndex     = '998';
            this.jsIFrameElem.style.visibility = 'hidden';
            this.jsIFrameElem.style.backgroundColor = '#FFFFFF';
            this.jsInputElem.parentNode.insertBefore(
				this.jsIFrameElem, this.jsInputElem);
		}
	}
	//-------------------------------------------------
	this.onKeyDownEvent = function(ev) {
		if(!ev) ev=window.event;
        switch(ev.keyCode) {
            case 13: // RETURN, ENTER
                if(this.jsSelectedItem !== false) {
                    this.setValue();
                    this.hide();
					this.jsInputElem.focus();
                } else return true;
                ev.returnValue = false;
                ev.cancelBubble = true;
                return false;
            case 27: // ESC
                this.hide();
                ev.returnValue = false;
                ev.cancelBubble = true;
                return false;
            case 38: // UP
                if(!this.isVisible) {
                    this.show(__JSAutocompleteMap[this.jsElementID]);
                }
                this.doSelect(-1);
                this.doScroll(-1);
                return false;
            case 9: // TAB
                if(this.isVisible) {
                    this.hide();
                }
                return true;
            case 40: // DOWN
                if(!this.isVisible) {
                    this.show(__JSAutocompleteMap[this.jsElementID]);
                }
                this.doSelect(1);
                this.doScroll(1);
                return false;
        }
	};
	this.jsKeyUpTime = null;
	this.onKeyUpEvent = function(ev) {
		if(!ev) ev=window.event;
        switch (ev.keyCode) {
            case 13:
                ev.returnValue = false;
                ev.cancelBubble = true;
                return false;
            case 27:
                this.hide();
                ev.returnValue = false;
                ev.cancelBubble = true;
                return false;
            case 38:
            case 40:
                return false;
            default: window.setTimeout
            	if(this.jsKeyUpTime != null) {
            		window.clearTimeout(this.jsKeyUpTime);
            	}
            	this.jsKeyUpTime = window.setTimeout('__JSAutocompleteMap[\'' + 
            			this.jsElementID + '\'].show()',this.jsDelay);
                return true;
        }
	};
	this.onKeyPressEvent = function(ev) {
		if(!ev) ev=window.event; 
		if(ev.which==13 || ev.keyCode==13 || isOP) {
			if(this.jsSelectedItem !== false) {
				return false;
			} else return false;
		}
	};
	this.onDblClickEvent = function() {
		this.show(__JSAutocompleteMap[this.jsElementID]);
	};
	this.onClickEvent = function(ev) {
		if(!ev) ev=window.event;
		ev.cancelBubble = true;
		ev.returnValue = false;
	};
	this.jsAjaxMap = new Object();
	this.show = function(sACObject) {
		if(sACObject == null)
			sACObject = this;
    	if(this.jsKeyUpTime != null) {
    		window.clearTimeout(this.jsKeyUpTime);
    		this.jsKeyUpTime = null;
    	}
        val = sACObject.jsInputElem.value;
		if(val.length < sACObject.jsChars) 
			return false;
        toDisplay = sACObject.jsCache[val];
        toParam = sACObject.jsParam[val];
		if(toDisplay == null) {
			toDisplay = new Array();
			if(sACObject.jsAjax != null) {
				ajax = sACObject.jsAjaxMap[val];
				if(ajax == null) {
					ajax = new JSAjax(val);
					sACObject.jsAjaxMap[val] = ajax;
				}
				if(!ajax.isRunning()) {
					urlParam = sACObject.jsAjax.split('?');
					url = urlParam[0];
					qval = val;
					if(typeof(escape) != 'undefined') {
						qval = escape(val);
					}
					query = 'q=' + qval;
					if(this.jsUseRandom) {
						query+= '&rnd=' + 
						Math.round(Math.random()*100000000);
					}
					if(urlParam.length > 1 && urlParam[1] != '') {
						query+= '&' + urlParam[1];
					}
					ajax.doAJAXRequestURL(
						sACObject, url + "?" + query, null, true, false
					);
				}
				return false;
			} else if(sACObject.jsData != null) {
				for(i=0;i<sACObject.jsData.length;i++) {
					if(sACObject.jsData[i].substr(0, val.length) == val)
						toDisplay[toDisplay.length] = sACObject.jsData[i];
				}
			}
		}
        if(toDisplay.length == 0) {
        	sACObject.hide();
            return false;
        }
        newDiv    = null;
        text      = null;
        numItems  = sACObject.jsDropDownElem.childNodes.length;
        sACObject.jsSelectedItem = false;
		while(sACObject.jsDropDownElem.childNodes.length > 0) {
            sACObject.jsDropDownElem.removeChild(sACObject.jsDropDownElem.childNodes[0]);
        }
        for(i=0;i<toDisplay.length;++i) {
            newDiv = document.createElement('div');
            newDiv.className = 'acItemElem';
            newDiv.setAttribute('id', this.jsElementID + 'ACItem' + i);
            newDiv.setAttribute('index', i);
            if(toParam != null)
            	newDiv.setAttribute('param', toParam[i]);
            newDiv.style.zIndex = '999';
			if(toDisplay.length > sACObject.jsRows && navigator.userAgent.indexOf('MSIE') == -1) {
                newDiv.style.width = sACObject.jsInputElem.offsetWidth - 22 + 'px';
            }
            newDiv.onmouseover = function() {
				sACObject.selectItem(this.getAttribute('index'));
			};
            newDiv.onclick = function() {
				sACObject.setValue();
				sACObject.hide();
				sACObject.jsInputElem.focus();
			};
            text = document.createTextNode(toDisplay[i]);
            newDiv.appendChild(text);
            sACObject.jsDropDownElem.appendChild(newDiv);
        }
        if(toDisplay.length > sACObject.jsRows) {
            sACObject.jsDropDownElem.style.height = (sACObject.jsRows * 20) + 'px';
        } else sACObject.jsDropDownElem.style.height = '';

		sACObject.jsDropDownElem.style.left = acElemOffsetLeft(sACObject.jsInputElem);
        sACObject.jsDropDownElem.style.top  = acElemOffsetTop(sACObject.jsInputElem) + sACObject.jsInputElem.offsetHeight;
		if(isIE) {
            sACObject.jsIFrameElem.style.top    = sACObject.jsDropDownElem.style.top;
            sACObject.jsIFrameElem.style.left   = sACObject.jsDropDownElem.style.left;
            sACObject.jsIFrameElem.style.width  = sACObject.jsDropDownElem.offsetWidth;
            sACObject.jsIFrameElem.style.height = sACObject.jsDropDownElem.offsetHeight;
            sACObject.jsIFrameElem.style.visibility = 'visible';
        }
        if(!sACObject.isVisible) {
            sACObject.jsDropDownElem.style.visibility = 'visible';
            sACObject.isVisible = true;
        }
        if(sACObject.jsDropDownElem.childNodes.length != numItems) {
            sACObject.jsSelectedItem = false;
        }
        return true;
	};
	this.hide = function() {
        if(this.jsIFrameElem) {
            this.jsIFrameElem.style.visibility = 'hidden';
        }
        this.jsDropDownElem.style.visibility = 'hidden';
        this.jsSelectedItem = false;
        this.isVisible = false;
	};
	this.setValue = function()  {
		if(
		    this.jsSelectedItem !== false && this.jsSelectedItem > -1 
		    && this.jsSelectedItem < this.jsDropDownElem.childNodes.length
		) {
			this.jsInputElem.value = this.jsDropDownElem.childNodes[this.jsSelectedItem].innerHTML;
			param = this.jsDropDownElem.childNodes[this.jsSelectedItem].getAttribute('param');
			if(param && this.jsParamElem) {
				this.jsParamElem.value = param;
				if(this.jsListener != null) {
					this.jsListener.doAction(this.jsInputElem.value, param);
				}
			} else if(this.jsListener != null) {
				this.jsListener.doAction(this.jsInputElem.value);
			}
		}
	};
	this.selectItem = function(index) {
        if(this.jsDropDownElem.childNodes[index]) {
            for(i=0;i<this.jsDropDownElem.childNodes.length;++i) {
                if(this.jsDropDownElem.childNodes[i].className == 'acItemElemSelected') {
                    this.jsDropDownElem.childNodes[i].className = 'acItemElem';
                }
            }
            this.jsDropDownElem.childNodes[index].className = 'acItemElemSelected';
            this.jsSelectedItem = index;
        }
	};
	this.doSelect = function(index) {
        if(index == 1 && this.jsSelectedItem !== false && this.jsSelectedItem == this.jsDropDownElem.childNodes.length - 1) {
            this.jsDropDownElem.childNodes[this.jsSelectedItem].className = 'acItemElem';
            this.jsSelectedItem = false;
        } else if(index == -1 && this.jsSelectedItem !== false && this.jsSelectedItem == 0) {
            this.jsDropDownElem.childNodes[0].className = 'acItemElem';
            this.jsSelectedItem = this.jsDropDownElem.childNodes.length;
        }
        if(this.jsSelectedItem === false) {
            this.jsDropDownElem.childNodes[0].className = 'acItemElemSelected';
            this.jsSelectedItem = 0;
        } else {
            if(this.jsDropDownElem.childNodes[this.jsSelectedItem]) {
                this.jsDropDownElem.childNodes[this.jsSelectedItem].className = 'acItemElem';
            }
            newIndex = this.jsSelectedItem + index;
            if(this.jsDropDownElem.childNodes[newIndex]) {
                this.jsDropDownElem.childNodes[newIndex].className = 'acItemElemSelected';
                this.jsSelectedItem = newIndex;
            }
        }
	}
	this.doScroll = function(index) {
        if(this.jsSelectedItem > this.jsLastItem) {
            this.jsFirstItem = this.jsSelectedItem - (this.jsRows - 1);
            this.jsLastItem  = this.jsSelectedItem;
        }
        if(this.jsSelectedItem < this.jsFirstItem) {
            this.jsFirstItem = this.jsSelectedItem;
            this.jsLastItem  = this.jsSelectedItem + (this.jsRows - 1);
        }
        this.jsDropDownElem.scrollTop = this.jsFirstItem * 20;
	}
    this.doResponse = function(xml) {
    	_root = xml.getElementsByTagName('autocomplete').item(0);
    	id = _root.getAttribute('id');
    	result = new Array();
    	param = new Array();
    	for(i=0;i<_root.childNodes.length;i++) {
    		node = _root.childNodes.item(i);
	    	if(node != null && node.nodeName == 'value') {
	    		result[result.length] = node.firstChild.data;
	    		pAttr = node.getAttribute('param');
	    		if(pAttr != null) {
	    			param[param.length] = pAttr;
	    		}
	    	}
    	}
    	if(result.length > 0) {
    		this.jsCache[id] = result;
    		if(this.jsCache.length > 20)
    			this.jsCache.shift();
    		if(param.length > 0) {
    			this.jsParam[id] = param;
    			if(this.jsParam.length > 20)
    				this.jsParam.shift();
    		}
    		this.show();
    	}
    }
}
function acElemOffsetLeft(jsElem){
	jsCElem = jsElem;
	jsLeft = 0;
	do {
		jsLeft += jsCElem.offsetLeft;
		jsCElem = jsCElem.offsetParent;
	} while(jsCElem.tagName.toLowerCase() != 'body');
	return jsLeft;
}
function acElemOffsetTop(jsElem){
	jsCElem = jsElem;
	jsTop = 0;
	do {
		jsTop += jsCElem.offsetTop;
		jsCElem = jsCElem.offsetParent;
	} while(jsCElem.tagName.toLowerCase() != 'body');
	return jsTop;
}
function acDocumentOnClickEvent(){
   for(jsAcObject in __JSAutocompleteMap)
	   __JSAutocompleteMap[jsAcObject].hide();
}
if(document.addEventListener) {
	document.addEventListener('click', acDocumentOnClickEvent, false);
} else if(document.attachEvent) {
	document.attachEvent('onclick', acDocumentOnClickEvent, false);
}
