function Whisperer(parameters){
  this.form=null;
  this.inputBox=null;
  this.searchIn=null;
  this.xmlHttpRequest=null;
  this.whispererArea=null;
  this.timerBeforeExecution=null;
  this.isFormSentAutomatically=false;
  this.isXmlHttpAsync=true;
  this.id_org=null;
  this.objectSizeAnimator=null;  
  this.itemType=-1; // TYPE OF ITEM. RESULTS WILL BE FOUND BY THIS VALUE.    
  var whisperer=this;

  this.Whisperer=function(parameters){       
    this.initSettings(parameters);    
  }
  this.initSettings=function(parameters){            
    this.inputBox=this.getWhispererInputBox(parameters.inputBox_id);        
    this.form=document.getElementById(parameters.form_id)    
    this.submitButton=this.getWhispererSubmitButton(parameters.form_id);
    this.isFormSentAutomatically=(parameters.isFormSentAutomatically==undefined ? this.isFormSentAutomatically : parameters.isFormSentAutomatically);
    
    if(!this.inputBox || !this.form || !this.submitButton){setTimeout(function(){whisperer.initSettings(parameters);},50);return;}    
    
    this.id_org=this.getFirstElementByParameter(this.form,"input","name","id_org").value;
    this.itemType=(parameters.itemType==undefined ? this.itemType : parameters.itemType);

    this.xmlHttpRequestScriptPath=this.getXmlHttpRequestScriptPath(parameters.searchIn);

    this.xmlHttpRequest=this.getXmlHttp();        
    
    this.blured_handler(document.body);

    if(!this.inputBox/* || !this.xmlHttpRequest*/){this.init(parameters);return;}
            
    this.whispererArea=this.getWhispererArea(this.inputBox);
    document.body.appendChild(this.whispererArea);
    
    this.objectSizeAnimator=new ObjectSizeAnimator(this.whispererArea,true,true);
  }
  this.getXmlHttpRequestScriptPath=function(searchIn){
    var result="";
    switch(searchIn){
      case "rejstrik": result="/VismoOnline_ActionScripts/whisperer_getItems_rejstrik.asp"; break;
    }
    return result;
  }
  this.getXmlHttp=function(){
    var thisInst=this;
    try{
      return new XmlHttp();
    }
    catch(err){
      var xmlHttpLink=document.createElement("script");
      xmlHttpLink.setAttribute("type","text/javascript");
      xmlHttpLink.setAttribute("src","/aspinclude/vismoweb5/html/xmlHttp.js");      
      document.getElementsByTagName("head")[0].appendChild(xmlHttpLink);
      var tmpTimer=setInterval(
        function(){
          try{
            thisInst.xmlHttpRequest=new XmlHttp();
            thisInst.xmlHttpRequest.createXMLHTTPConnection(); //CREATE CONNECTION OBJECT
            clearInterval(tmpTimer);
          }
          catch(err){}
        }
      ,100);
      //return new XmlHttp();
    }
  }
  this.getWhispererInputBox=function(inputBoxId){    
    var inputBox=null;
    try{
      inputBox=document.getElementById(inputBoxId);      
      inputBox.instance=this;
      inputBox.setAttribute("autocomplete","off");  // DO NOT SHOW DEFAULT FORM WHISPERER
      inputBox.ExpressionData=new Object();      
      inputBox.onkeyup=function(e){             
        this.instance.keyPressedDown_handler(this,e);
      }
      inputBox.onfocus=function(e){
        this.instance.showWhispererArea(e);
      }      
      inputBox.onblur=function(e){
        if(this.instance.timerBeforeExecution)clearInterval(this.instance.timerBeforeExecution);
        this.instance.clearWhispererArea();
        this.instance.whispererArea.style.display="none";
      }
    }
    catch(err){return null;}
    
    return inputBox;
  }
  this.getWhispererSubmitButton=function(formId){
    var submitButton=null;
    try{
      submitButton=this.getFirstElementByParameter(document.getElementById(formId),"input","type","submit");
      submitButton.instance=this;
    }
    catch(err){return null;}
    
    return submitButton;
  }  
  this.getWhispererArea=function(inputBox){    
    var whispererArea=document.createElement("div");
    whispererArea.instance=this;
    whispererArea.className="whispererArea";
    whispererArea.style.display="none";
    whispererArea.style.position="absolute";
    //whispererArea.style.left=(inputBox.offsetLeft+inputBox.offsetParent.offsetLeft+document.body.scrollLeft)+"px";
    //whispererArea.style.top=(inputBox.offsetTop+inputBox.offsetParent.offsetTop+inputBox.offsetHeight+document.body.scrollTop)+"px";
    whispererArea.style.width="auto";
    whispererArea.style.height="auto";
    whispererArea.style.backgroundColor="#FFFFFF";
    whispererArea.style.border="1px solid #000000";
    whispererArea.style.zIndex="1000";
    whispererArea.style.overflow="hidden";
    whispererArea.lastCursorPosition=-1;
    
    return whispererArea;
  } 
  this.setLocationOfWhispererArea=function(){
    // COUNT AND SET LOCATION OF WHISPERER AREA
    var borderTop=0;
    var borderBottom=0;
    var borderLeft=0;
    var borderRight=0;
    
    // GET ELEMENT BORDERS WIDTHS
    try{
      // OTHER BROWSERS
      borderTop=parseInt(getComputedStyle(this.inputBox,'').getPropertyValue('border-top-width'));
      borderBottom=parseInt(getComputedStyle(this.inputBox,'').getPropertyValue('border-bottom-width'));
      borderLeft=parseInt(getComputedStyle(this.inputBox,'').getPropertyValue('border-Left-width'));
      borderRight=parseInt(getComputedStyle(this.inputBox,'').getPropertyValue('border-Right-width'));

      borderTop=borderBottom=borderLeft=borderRight=0;  // ANOTHER WAY TO COUNT POSITION OF ELEMENT IS USED IN OTHER BROWSER. SO IT IS NOT NECESSARY TO COUNT BORDER.
    } 
    catch(e){
      // IE
      borderTop = parseInt(this.inputBox.currentStyle.borderTopWidth);
      borderBottom = parseInt(this.inputBox.currentStyle.borderBottomWidth);
      borderLeft = parseInt(this.inputBox.currentStyle.borderLeftWidth);
      borderRight = parseInt(this.inputBox.currentStyle.borderRightWidth);
    }
    
    var iB=this.inputBox.getBoundingClientRect();
    //var iB_parent=this.inputBox.offsetParent.getBoundingClientRect();
    this.whispererArea.style.left=(iB.left+document.body.scrollLeft-borderLeft-borderRight)+"px";
    this.whispererArea.style.top=(iB.top+document.body.scrollTop+this.inputBox.offsetHeight-borderTop-borderBottom)+"px";     
  }
  this.keyPressedDown_handler=function(actObj,e){
    var thisInst=this;
    var actualEvent=e?e:event;    

    if(this.isDisposeAction(actualEvent))return;

    if(this.isMoveByArrows(actualEvent))return;
    else this.whispererArea.lastCursorPosition=-1;
    
    if(this.timerBeforeExecution)clearTimeout(this.timerBeforeExecution); // JE OTAZKA, JESTLI JE TOHLE CHTENY: POKUD BYLO STISKNUTO DALSI TLACITKO, ODDALIT PROVEDENI BEZICIHO INTERVALU TIM, ZE SE UKONCI
    this.timerBeforeExecution=setTimeout(
      function(){
        thisInst.showWhispererArea(actualEvent);
      }
    ,100);        
  }
  this.isDisposeAction=function(e){
    if(e.keyCode==27){  // WHEN ESCAPE WAS PRESSED
      this.disposeAction(e);
      return true;
    }
    return false;
  }
  this.disposeAction=function(e){
    this.inputBox.value="";
    this.clearWhispererArea();
    this.whispererArea.style.display="none";    
  }
  this.isMoveByArrows=function(e){
    var verticalMove=1;
    var itemsList=this.whispererArea.getElementsByTagName("ul");
    var items_li=((itemsList && itemsList.length>0)?itemsList[0].getElementsByTagName("li") : null);
    
    if(!items_li)return false;
    switch(e.keyCode){
      case 40: verticalMove=1; break; // ARROW DOWN
      case 38: verticalMove=-1; break; // ARROW UP
      default: return false;
    } 

    if(this.whispererArea.lastCursorPosition==-1 || (this.whispererArea.lastCursorPosition+1==items_li.length && verticalMove==1)){
      this.whispererArea.lastCursorPosition=0;
    }
    else if(this.whispererArea.lastCursorPosition==0 && verticalMove==-1){
      this.whispererArea.lastCursorPosition=items_li.length-1;
    }
    else{      
      this.whispererArea.lastCursorPosition+=verticalMove;
    }
    
    for(var i=0;i<items_li.length;i++){ items_li[i].className="whisperer"; }
    items_li[this.whispererArea.lastCursorPosition].className="whisperer_actItem";
    this.inputBox.value=items_li[this.whispererArea.lastCursorPosition].getElementsByTagName("a")[0].innerHTML;
    
    //document.getElementById("nadpisy").innerHTML=items_li[this.whispererArea.lastCursorPosition].innerHTML;
    
    return true;
  }
  this.getPressedKey=function(e){

  }  
  this.blured_handler=function(actObj){
    var thisInst=this;
    //var actualEvent=e;    
    //this.hideWhispererArea(actualEvent);
    if (document.body.addEventListener) {
      document.body.addEventListener ("click",function(e){thisInst.hideWhispererArea(e);},false);      
      //document.body.addEventListener ("click",function(e){document.getElementById("lista").innerHTML="ahoj";},false);
    } else if (document.body.attachEvent) {
      document.body.attachEvent ("onclick",function(e){thisInst.hideWhispererArea(e);});
      //document.body.attachEvent ("onclick",function(e){document.getElementById("lista").innerHTML="ahoj2";});
    }    
  }  
  this.showWhispererArea=function(e){
    if(this.inputBox.value.length==0){
      this.inputBox.ExpressionData.rowid=null;
      this.inputBox.ExpressionData.idOsnovy=null;
      return;
    }
    else if(this.inputBox.value.length<2){
      return;
    }
    
    this.clearWhispererArea();

    this.setLocationOfWhispererArea();
    
    this.executeRequest();
  }
  this.executeRequest=function(){
    this.resultData=null;
    var actInst=this;
    var tmpTimer=null;
    var attemptsCount=0;
    var MAX_ATTEMPTS_COUNT=40;  // MAX ATTEMPTS COUNT FOR ASYNCHRONOUS REQUEST
    
    if(this.isXmlHttpAsync){
      // SEND ASYNCHRONIZED      
      tmpTimer=setInterval(function(){if(actInst.resultData || attemptsCount==MAX_ATTEMPTS_COUNT){actInst.processReceivedData(actInst.resultData);clearInterval(tmpTimer);} else {attemptsCount++;} },100);  // CONTINUE, WHEN ASYNCHRONIZED XMLHTTP REQUEST RESPONSES RESULT
      this.xmlHttpRequest.executeXmlHttpRequest_ASYNC("POST",this.xmlHttpRequestScriptPath,"id_obce="+this.id_org+"&expression="+this.prepareForSend(this.inputBox.value)+"&itemType="+this.itemType,actInst);
    }
    else{
      // SEND SYNCHRONIZED
      //this.resultData=this.xmlHttpRequest.executeXmlHttpRequest("post",ActionScriptsPath+"whisperer_getItems_rejstrik.asp",false,"id_obce="+this.id_org+"&expression="+this.prepareForSend(this.inputBox.value));
      this.resultData=this.xmlHttpRequest.executeXmlHttpRequest("post",this.xmlHttpRequestScriptPath,false,"id_obce="+this.id_org+"&expression="+this.prepareForSend(this.inputBox.value)+"&itemType="+this.itemType);    
      this.processReceivedData(this.resultData);
    }
  }
  this.processReceivedData=function(result){    
    var foundItemsList=document.createElement("ul");        
    foundItemsList.className="whisperer";
    foundItemsList.style.listStyleType="none";
    foundItemsList.style.textAlign="left";
    foundItemsList.style.margin="0px";
    foundItemsList.style.padding="2px";        
    foundItemsList.innerHTML=result;
    
    if(foundItemsList.getElementsByTagName("li").length==0){
      this.whispererArea.style.display="none";
      return;
    }
    
    this.processListItems(foundItemsList);
    this.whispererArea.innerHTML="";
    this.whispererArea.appendChild(foundItemsList);    
    this.whispererArea.style.display="block";

    this.objectSizeAnimator.animate();
  }
  this.hideWhispererArea=function(e){
    e=e ? e : event;
    var srcElement=e.target ? e.target : e.srcElement;
    if(this.inputBox==srcElement)return;  // DO NOT HIDE WHEN SOURCE ELEMENT IS WHISPERER INPUT BOX
    
    this.clearWhispererArea();
    this.whispererArea.style.display="none";
  }
  this.clearWhispererArea=function(){
    if(this.whispererArea && this.whispererArea.getElementsByTagName("ul").length>0){
      this.whispererArea.getElementsByTagName("ul")[0].parentNode.removeChild(this.whispererArea.getElementsByTagName("ul")[0]);
    }
  }
  this.processListItems=function(list_ul){    
    var list_li=list_ul.getElementsByTagName("li");
    for(var i=0;i<list_li.length;i++){          
      var list_a=list_li[i].getElementsByTagName("a")[0];
      list_a.instance=this;
      list_a.rowId=eval(list_a.className).rowId;
      list_a.idOsnovy=eval(list_a.className).idOsnovy;
      //list_a.heslo=eval(list_a.className).expression;
      list_a.removeAttribute("class");      
      
      list_a.blur(); 
      list_a.hideFocus = true;
      list_a.style.outline = 'none';      
      
      //list_a.onclick=function(e){                      
      list_a.onmousedown=function(e){                    
        this.instance.processListItemClick(e,this);
        this.instance.hideWhispererArea(e);        
        this.instance.stopBubble(e);
      }
      
      list_li[i].instance=this;
    }
  }
  this.processListItemClick=function(e,actObj){
    //alert("rowId: "+actObj.rowId+", idOsnovy: "+actObj.idOsnovy);
    this.inputBox.ExpressionData.rowid=actObj.rowid;
    this.inputBox.ExpressionData.idOsnovy=actObj.idOsnovy;
    this.inputBox.value=actObj.innerHTML;
    if(this.isFormSentAutomatically && this.submitButton)this.submitButton.click(); // CLICK FORM SUBMIT BUTTON
  }
  this.getFirstElementByParameter=function(parentElement,elementTagName,parameterName,elementType){
    var elements=parentElement.getElementsByTagName(elementTagName);
    for(var i=0;i<elements.length;i++){
      if(elements[i].getAttribute(parameterName)==elementType){
        return elements[i];
      }
    }
    return null;
  }
  this.prepareForSend=function(value){
    while(value.indexOf(" ")>-1)value=value.replace(" ","#_#");
    return value;
  }
  this.stopBubble=function(e){
    if(e){e.stopPropagation();} else{window.event.cancelBubble=true;}
  }  
  
  this.Whisperer(parameters);
}

function ObjectSizeAnimator(actObj,isHorizontalAnimation,isVerticalAnimation){
  var objToResize=null;
  var defaultWidth=0;
  var defaultHeight=0;
  var finishSizeCatchedIndex=0;
  var ANIM_STEP_HORIZONTAL=20;
  var ANIM_STEP_VERTICAL=18;
  var isHorizontalAnim=false;
  var isVerticalAnim=false;
  var defaultSizes=null;

  this.ObjectSizeAnimator=function(actObj,isHorizontalAnimation,isVerticalAnimation){
    objToResize=actObj;
    isHorizontalAnim=isHorizontalAnimation;
    isVerticalAnim=isVerticalAnimation;
  }
  this.animate=function(){        
    objToResize.style.width="auto";
    objToResize.style.height="auto";    
    
    // GET DEFAULT SIZE OF OBJECT, THAT WILL BE TOUCHED
//    defaultSizes=this.getObjectComputedStyles(objToResize);
//    defaultWidth=parseInt(defaultWidth)>0 ? defaultSizes.width : objToResize.offsetWidth;
//    defaultHeight=parseInt(defaultHeight)>0 ? defaultSizes.height : objToResize.offsetHeight;
    defaultWidth=objToResize.offsetWidth;
    defaultHeight=objToResize.offsetHeight;
    
    // SET 0 TO OBJECT, WHICH WAY WILL BE ANIMATED
    objToResize.style.width=isHorizontalAnim ? 0 : objToResize.style.width;
    objToResize.style.height=isVerticalAnim ? 0 : objToResize.style.height;
    
    var timer=setInterval(    
      function(){
        finishSizeCatchedIndex=0;
        
        if(isHorizontalAnim && parseInt(objToResize.style.width)<=defaultWidth+ANIM_STEP_HORIZONTAL){
          objToResize.style.width=parseInt(objToResize.style.width)+ANIM_STEP_HORIZONTAL+"px";          
          finishSizeCatchedIndex++;
        }        
//        document.getElementById("nadpisy").innerHTML+="hodnota:"+parseInt(objToResize.style.height)+"<="+(defaultHeight+ANIM_STEP_VERTICAL)+",";
        if(isVerticalAnim && parseInt(objToResize.style.height)<=defaultHeight+ANIM_STEP_VERTICAL){                    
          objToResize.style.height=parseInt(objToResize.style.height)+ANIM_STEP_VERTICAL+"px";          
          finishSizeCatchedIndex++;
        }
        
        if(finishSizeCatchedIndex==0){
          objToResize.style.width=defaultWidth+"px";
          objToResize.style.height=defaultHeight+"px";
          clearInterval(timer);
        }
      }
    ,20);
  }
  // GET ELEMENT STYLES    
  this.getObjectComputedStyles=function(actObj){        
    var obj_width=0;
    var obj_height=0;
    try{
      // OTHER BROWSERS
      obj_width=parseInt(getComputedStyle(actObj,'').getPropertyValue('width'));
      obj_height=parseInt(getComputedStyle(actObj,'').getPropertyValue('height'));
    } 
    catch(err){
      // IE
      obj_width = parseInt(actObj.currentStyle.width);
      obj_height = parseInt(actObj.currentStyle.height);      
    }    
    return {width:obj_width,height:obj_height};
  }  
  
  this.ObjectSizeAnimator(actObj,isHorizontalAnimation,isVerticalAnimation);
}
