function CndSuggest(input) {
  this.input=input;
  this.lastValue='';
  this.lastTime=null;
  this.lastSelected=null;

  //Parameter fuer die AJAX-Requests
//this.url = input.form.action;
  this.url="http://www.schobertechnologies.de/-/allgemein/search/_/content/72/home.json";
  this.method = input.form.method.toUpperCase();
  this.params = {};

  if(CndSuggest.useDojo){
    dojo.query('input[type=hidden]', input.form).forEach(function(e){
      if (e.name!=='cssmarker') {
        this.params[e.name]=e.value;
      }
    },this);
  } else if(CndSuggest.usePrototype){
    $(input.form).select('input[type=hidden]').each(function(e){
      if (e.name!=='cssmarker') {
        this.params[e.name]=e.value;
      }
    },this);
  }
  
  //Select-Element fuer die Darstellung der Ergebnisse
  this.select=null;
  
  /*
   * Ereignishandler fuer: Taste losgelassen
   * Es wird die Pruefung der Tipppausen initiert.
   */
  this.handleKeypressed=function(event){
    event=(event)?event:window.event;
    if(event.keyCode!==13&&this.input.value!==this.lastValue&&this.input.value!==''){
      this.lastValue=this.input.value;
      var date=new Date();
      this.lastTime=date.getTime();
      var suggest=this;
      setTimeout(function(){suggest.handleSuggest();}, CndSuggest.timeout+30);
    }
  };
  
  /*
   * Es werden die Tipppausen geprueft - sind diese lang genug,
   * wird die eigentliche Suggest-Funktionalitaet aufgerufen
   */
  this.handleSuggest=function() {
    var date=new Date();
    var timeout=date.getTime()-this.lastTime;
    if(timeout>CndSuggest.timeout){
      this.loadSuggest();
    }
  };

  /*
   * Fuehrt die AJAX-Anfrage aus und verwendet hierfuer die Parameter vom
   * Parent-Formulares des Input-Elementes
   */
  this.loadSuggest=function(){
    var suggest=this;
    var params=this.params.valueOf();
    params[this.input.name]=this.lastValue;
    if(CndSuggest.useDojo) {
      dojo.xhr(this.method, {
        url:this.url,
        handleAs:'json',
        content:params,
        load: function(data, args){
          suggest.performAddSuggest(data);
        }
      },this.method=='POST');
    }else if(CndSuggest.usePrototype){
      var request=new Ajax.Request(this.url, {
        parameters: params,
        onSuccess: function(transport){
          suggest.performAddSuggest(transport.responseJSON);
        }
      });
    }
  };
  /*
   * Liefert das Select-Element zur Darstellung der Ergebisse
   */
  this.getSelectElement=function(){
    if(!this.select){
      this.select=document.createElement('ul');
      this.select.className='condero[suggest] hidden';
      
      this.select.style.visibility='hidden';
      this.select.style.position='absolute';
      this.select.style.left='0px';
      this.select.style.top=this.input.offsetHeight+'px';
      
      this.input.form.appendChild(this.select);

      var suggest=this;
      var mouseSelection=function(event){suggest.mouseSelection.call(suggest,event);};
      this.select.onmouseover=mouseSelection;
    }
    return this.select;
  };

  /*
   * Zeigt das Select-Element mit den Ergebnissen an
   */
  this.showResults=function(){
    if (this.select) {
      this.select.style.visibility='visible';
      this.select.className='condero[suggest] visible';
    }
  };

  /*
   * Blendet das Select-Element mit den Ergebnissen aus
   */
  this.hideResults=function(){
    if (this.select) {
      this.select.style.visibility='hidden';
      this.select.className='condero[suggest] hidden';
    }
  };

  /*
   * Gibt zurueck ob die Box sichtbar ist 
   */
  this.isVisible=function(){
    if (this.select) {
      return this.select.style.visibility != 'hidden';
    }
    return false;
  }

  /*
   * EventHandler zur Ergebnisselektion per Tastatur
   */
  this.keySelection=function(event){
    if (this.select && this.isVisible()){
      var elems=this.select.getElementsByTagName('li');
      if (elems.length>0){
        event=(event)?event:window.event;
        var code=event.keyCode;
        var sel=null;
        
        if(code==38){/*up*/
          sel=elems[elems.length-1];
          if(this.lastSelected) {
            this.lastSelected.className='';
            if (this.lastSelected.previousSibling) {
              sel=this.lastSelected.previousSibling;
            }
          }
          this.lastSelected = sel;
          this.lastSelected.className=this.checkedClass;

          //ggf. zum Eintrag scrollen
          if(this.lastSelected.offsetTop>=this.select.scrollTop+this.select.clientHeight){
            this.select.scrollTop=this.lastSelected.offsetHeight+this.lastSelected.offsetTop-this.select.clientHeight;
          }else if(this.lastSelected.offsetTop<this.select.scrollTop){
            this.select.scrollTop=this.lastSelected.offsetTop;
          }

          this.handleSelection(this.lastSelected.innerHTML, this.lastSelected.getAttribute('value'));
        }else if(code==40){/*down*/
          sel=elems[0];
          if(this.lastSelected) {
            this.lastSelected.className='';
            if (this.lastSelected.nextSibling) {
              sel=this.lastSelected.nextSibling;
            }
          }
          this.lastSelected = sel;
          this.lastSelected.className=this.checkedClass;

          //ggf. zum Eintrag scrollen
          if(this.lastSelected.offsetTop>=this.select.scrollTop+this.select.clientHeight){
            this.select.scrollTop=this.lastSelected.offsetHeight+this.lastSelected.offsetTop-this.select.clientHeight;
          }else if(this.lastSelected.offsetTop<this.select.scrollTop){
            this.select.scrollTop=this.lastSelected.offsetTop;
          }

          this.handleSelection(this.lastSelected.innerHTML, this.lastSelected.getAttribute('value'));
        }else if(code==13){/*RETURN*/
          this.fire();
          return true;
        }else if(code==27){/*ESCAPE*/
          this.hideResults();
        }
      }
    }
  };

  /*
   * EventHandler zur Ergebnisselektion per Maus
   */
  this.mouseSelection = function(event) {
    var src=(event)?event.target:window.event.srcElement;
    while(src && src.tagName!='LI') {
      src=src.parentNode;
    }
    if (src && src.tagName=='LI') {
            if(src!==this.lastSelected){
                if (this.lastSelected){
                    this.lastSelected.className='';
                }
                src.className=this.checkedClass;
                this.lastSelected=src;
            }
            this.handleSelection(src.innerHTML, src.getAttribute('value'));
    }
  };

  /*
   * EventHandler zur Ergebnisaktivierung per Maus
   */
  this.fire = function(event) {
    this.input.focus();
    if(this.lastSelected){
      this.hideResults();
      this.handleFire(this.lastSelected.innerHTML, this.lastSelected.getAttribute('value'));
    }
  };
}

CndSuggest.prototype.checkedClass='selected';
/*
 * Methode wird aufgerufen, wenn sich die Auswahl der Suggest-Values geaendert hat
 * (per Tastatur od. Maus)
 */
CndSuggest.prototype.handleSelection = function(label, value){};

/*
 * Methode wird aufgerufen, wenn ein Suggest-Value ausgewaehlt wurde
 * (per RETURN od. Maus-Klick)
 */
CndSuggest.prototype.handleFire = function(label, value){
  this.input.value=label;
};


CndSuggest.prototype.performAddSuggest=function(jsonResponse){
  //Ergebnisse abrufen;
  var values=null;
  try{
    values = CndSuggest.reader.getRecords(jsonResponse);
  }catch(ex){}
  
  if (values instanceof Array&&values.length>0) {
    //Alte Ergebisse aus der Darestellung entfernen
    var select=this.getSelectElement();
    for(var i=select.childNodes.length-1; i>=0; i--) {
      select.removeChild(select.childNodes[i]);
    }
    //ggf. Scrolling ganz nach oben
    select.scrollTop=0;
    
    this.lastSelected=null;
  
    //Funktionsreferenzen fuer Mouse-Events
    var suggest=this;
    var mouseFire=function(event){suggest.fire.call(suggest,event);};
    
    var count=0;
    for(i=0;i<values.length;i++){
    //Ergebnisdetails abrufen und auf Gueltigkeit pruefen
    var label=CndSuggest.reader.getLabel(values[i]);
    var value=CndSuggest.reader.getValue(values[i]);
    if(label===''||value===''){continue;}
    
    var elem=this.createSearchResultListEntry(label, values[i]);
    elem.setAttribute('value', value);
    
    //Event-Handler fuer die Selektion per Maus
    elem.onclick=mouseFire;
    select.appendChild(elem);
    
    count++;
    }
    
    if(count>0){
      this.showResults();
    }
  }else{
    this.hideResults();
  }
};

CndSuggest.prototype.createSearchResultListEntry=function(label, entry){
    var elem=document.createElement('li');
    elem.innerHTML=label;
    return elem;
};

/*
 * Initialisiert das Suggest-System mit allen Input-Elementen,
 * welche die CSS-Klasse condero[suggest] deklariert haben
 */
CndSuggest.init=function(reader,timeout){
  CndSuggest.reader=reader;
  CndSuggest.timeout=(timeout)?timeout:380;
  //auf verfuegbare JS-Bibliotheken pruefen
  CndSuggest.useDojo=false;
  CndSuggest.usePrototype=false;
  CndSuggest.useJQuery=false;
  var flag=false;
  if(dojo) {
    CndSuggest.useDojo=true;
    flag=dojo.isWebKit || dojo.isIE;
  } else if(Prototype){
    CndSuggest.usePrototype=true;
    flag=Prototype.Browser.WebKit || Prototype.Browser.IE;
  }else{
    alert('Keine Unterstuetzte JS Bibliothek gefunden (Prototype');
    return;
  }
  //Input-Elemente heraussuchen, Event-Handler registrieren
  if(CndSuggest.useDojo){
    dojo.query('form input[class*="condero[suggest]"]').forEach(function(e){
      dojo.attr(e, 'autocomplete', 'off');

      var suggest=new CndSuggest(e);
      dojo.connect(e, 'onkeyup', function(event){
        suggest.handleKeypressed.call(suggest, event);
      });
      dojo.connect(e,(flag?'keydown':'keypress'),function(event){
        if(suggest.keySelection.call(suggest, event)){
          event.preventDefault();
        }
      });
      dojo.connect(e,'click',function(event){
        suggest.hideResults();
      });
      dojo.connect(e,'blur',function(event){
        setTimeout(function(){suggest.hideResults();}, 1000);
      });
    });
  } else  if(CndSuggest.usePrototype){
    $$('form input[class~="condero[suggest]"]').inputs.each(function(e){
      e.setAttribute('autocomplete', 'off');

      var suggest=new CndSuggest(e);
      Event.observe(e,'keyup',function(event){
        suggest.handleKeypressed.call(suggest, event);
      });
      Event.observe(e,(flag?'keydown':'keypress'),function(event){
        if(suggest.keySelection.call(suggest, event)){
          if(CndSuggest.usePrototype) {
            event.stop();
          }
        }
      });
      Event.observe(e,'click',function(event){
        suggest.hideResults();
      });
      Event.observe(e,'blur',function(event){
        setTimeout(function(){suggest.hideResults();}, 1000);
      });
    });
  }
};
