function initHafasSuggest() {
  timer = null;
  document.body.onmousedown = function(){
    if(document.getElementById("suggestion") && bodySelect){
      SLs.delete_SLs();
    }
    bodySelect = true;
  }
  for(var i=0;i<hafasInputFields.length;i++){
    if(document.getElementById(hafasInputFields[i]["id"])){
      currentField = document.getElementById(hafasInputFields[i]["id"]);
      currentField.setAttribute("autocomplete","off");
      currentField.onkeyup = function(ereignis){
        test = this;
        if(timer) window.clearTimeout(timer);
        currentKC=(ereignis)?ereignis.keyCode:window.event.keyCode;
        if(test.value.length < getStopMinChar){
          // give suggestion only when at least 4 (or other set value) characters are typed in
          if(document.getElementById("suggestion")) SLs.delete_SLs();
        }else if(currentKC!=40&&currentKC!=38&&currentKC!=9&&currentKC!=16&&currentKC!=13){
          timer = window.setTimeout('suggestion(test, currentKC)', getStopDelay);
        }else{
          suggestion(test, currentKC);
        }
      }
      // timeout wird benoetigt, da onblur sonst die korrekte durchfuehrung eines evtl. onclick auf einen der Eintraege behindert
      currentField.onblur = new Function ("ereignis","window.clearTimeout(timer);leaveInputField();");
      currentField.onclick = new Function("ereignis", "if(SLs.container)SLs.delete_SLs();");
      //if(hafasInputFields[i]["id"]!="stationname" && (i==0 || i==2)){ -- Via-Feld nicht mehr fokusieren
      if(setFocus == "yes" && (i==0)){
			
			// only focus an element which is not hidden or in a hidden container
			var parent = currentField;
			var bFocus = true;
			// while parent node exists and isn't body or html tag
			while (parent) {
				if ((parent.tagName == "BODY") || (parent.tagName == "HTML")) {
					break;
				}
				// The parent node is hidden this so this element is no good.
				if ((parent.style.display == "none") || (parent.style.visibility == "hidden")) {
					bFocus = false;
					break;
				}
				// climb up DOM tree
				parent = parent.parentNode;
			}
			if (bFocus) {
				currentField.focus();
			}
      }
    }
  }

  // wenn nach waehlen eines Eintrags der Liste (Pfeiltasten) Enter gedrueckt wird,
  // wird nur der Container geloescht, nicht das Formular abgeschickt
  document.getElementsByName(currentFormName)[0].onsubmit = function (){
    if(SLs.container){
      //hideWaitIcon();
      SLs.inputField.focus();
      return false;
    }
    else {
      resetHafasSuggest();
      return true;
    }
  }

  // Initialisieren der flags und des Inputs
  clickSel = 0;
  scrollSel = 0;
  userInput = "";
  bodySelect = true;
}

function resetHafasSuggest () {
  for(var i=0;i<hafasInputFields.length;i++){
    if(document.getElementById(hafasInputFields[i]["id"])){
      currentField = document.getElementById(hafasInputFields[i]["id"]);
      currentField.removeAttribute('autocomplete');
    }
  }
}

function leaveInputField(){
  if (SLs.container){
    // wenn per mouse selektiert wurde bleibt der Focus im Eingabefeld
    if(scrollSel && scrollSel == 1 && !clickSel){
      SLs.inputField.focus();
      scrollSel = 0;
    }else{
      if(clickSel == 1){
        SLs.inputField.focus();
        clickSel = 0;
      }else if(SLs.countList > -1) SLs.inputField.value = SLs.container.getElementsByTagName("div")[SLs.countList].firstChild.nodeValue;
      SLs.delete_SLs();
    }
  }
}

function suggestion(curField, kc) {
  // find index
  var count = 0;
  do{
    fieldIndex = count;
    count++;
  }while(curField.id != hafasInputFields[count-1]["id"])

  SLs.inputField = curField;

  if((kc == 40) && (SLs.container)){
    // Bei Druecken der Pfeiltaste 'runter' wird in den Eintraegen navigiert
    if(SLs.container.getElementsByTagName("div")[SLs.countList+1]){
      if(SLs.countList != -1) SLs.container.getElementsByTagName("div")[SLs.countList].className = "";
      else SLs.container.scrollTop = 0;
      SLs.countList++;
      // setzen der bisherigen Scrollhoehe, falls diese ueber die Scrollbar veraendert wurde
      SLs.container.scrollTop = SLs.currentTop * 15;
      if(SLs.countList > SLs.currentBottom){
        SLs.container.scrollTop = SLs.container.scrollTop + 15;
        SLs.currentBottom++;
        SLs.currentTop++;
      }
      SLs.container.getElementsByTagName("div")[SLs.countList].className = "selected";
      SLs.container.getElementsByTagName("div")[SLs.countList].style.width = SLs.container.clientWidth + "px";
    }
  }else if((kc == 38) && (SLs.container)){
    // Bei Druecken der Pfeiltaste 'rauf' wird in den Eintraegen navigiert
    if(SLs.countList >= 0){
      SLs.container.getElementsByTagName("div")[SLs.countList].className = "";
      SLs.countList--;
      if(SLs.countList == -1){
        SLs.inputField.value = userInput;
      }else{
        // setzen der bisherigen Scrollhoehe, falls diese ueber die Scrollbar veraendert wurde
        SLs.container.scrollTop = SLs.currentTop * 15;
        if(SLs.countList < SLs.currentTop){
          SLs.container.scrollTop = SLs.container.scrollTop - 15;
          SLs.currentTop--;
          SLs.currentBottom--;
        }
        SLs.container.getElementsByTagName("div")[SLs.countList].className = "selected";
        SLs.container.getElementsByTagName("div")[SLs.countList].style.width = SLs.container.clientWidth + "px";
      }
    }
  }else if(kc != 9 && kc != 16 && kc != 13){
    // bei Druecken der Tab-, Shift- oder der Entertaste passiert nichts...
    // erzeugt den suggestion-Container und holt die Inhalte
    // user-Eingabe merken, wird bei verlassen der Auswahlliste ueber die Pfeiltasten wieder im Feld eingetragen
    userInput = curField.value;
    if (SLs.container){
      SLs.delete_SLs();
      // Markierung des ausgewaehlten Eintrags zuruecksetzen.
      SLs.countList = -1;
    }
    if(curField.value != ""){
      document.getElementsByTagName("body")[0].appendChild(SLs.erzeugen(fieldIndex));
      SLs.holen(curField.value+"?", fieldIndex);
    }
  } else if(kc == 13){
    if(SLs.container){
      if(SLs.countList > -1)SLs.inputField.value = SLs.container.getElementsByTagName('div')[SLs.countList].firstChild.nodeValue;
      SLs.inputField.focus();
      SLs.delete_SLs();
    }
  }
  // naechsten Tastendruck werten
}

// suggestion-Layer-Objekt 'SuggestionLocations'
var SLs = {
  container: null,		// DIV-Container
  ajax: false,			// XMLHttpRequest-Objekt
  div_breite: "auto",		// Breite und ...
  div_hoehe: 150,			// Hoehe des suggestion-Containers
  countList: -1,
  currentTop: 0,
  currentBottom: 9,
  inputField: null,
  pos_x: 0,
  pos_y: 0,

  erzeugen: function(fieldIndex) {
    // erzeugt Div-Container
    SLs.container = document.createElement("div");
    SLs.container.id = "suggestion";
    // Opera braucht zwingend eine feste Breite, um 'overflow' korrekt zu interpretieren
    if(navigator.userAgent.toLowerCase().indexOf("opera")>-1) SLs.container.style.minWidth = "148px";
    SLs.container.style.width = "auto";
    SLs.container.style.height = "auto";
    // Positionieren direkt unterhalb des Eingabefelds (L&F einer LB)
    SLs.pos_x = SLs.getPosX(SLs.inputField);
    SLs.pos_y = SLs.getPosY(SLs.inputField)+18;
    SLs.container.style.left = SLs.pos_x + "px";
    SLs.container.style.top = SLs.pos_y + "px";

    // MSIE/Opera setzt bei scrollen in der Auswahllist den Focus auf den Container um,
    // das Eingabefeld wird also verlassen und der Container loescht sich quasi selbst...
    // Das hier gesetzte Flag faengt diesen Fall in leaveInputField() ab.
    SLs.container.onmousedown = new Function ("ereignis", "bodySelect=false;if(navigator.userAgent.toLowerCase().indexOf('msie')>-1)scrollSel=1;")
    //SLs.container.onmousedown = new Function ("ereignis", "bodySelect=false;scrollSel=1;")


    // zurueckgeben
    return SLs.container;
  },

  holen: function(input, fieldIndex) {
    // Ajax-Verbindung herstellen
    try {			// W3C-Standard
      SLs.ajax = new XMLHttpRequest();
    } catch(w3c) {
      try {			// Internet Explorer
        SLs.ajax = new ActiveXObject("Msxml2.XMLHTTP");
      } catch(msie) {
        try {		// Internet Explorer alt
          SLs.ajax = new ActiveXObject("Microsoft.XMLHTTP");
        } catch(msie_alt) {
          SLs.delete_SLs();
          for(var i=0;i<hafasInputFields.length;i++){
            if(document.getElementById(hafasInputFields[i]["id"])){
              document.getElementById(hafasInputFields[i]["id"]).onfocus = null;
              document.getElementById(hafasInputFields[i]["id"]).onkeyup = null;
              document.getElementById(hafasInputFields[i]["id"]).onblur = null;
              document.getElementById(hafasInputFields[i]["id"]).onclick = null;
            }else if(document.getElementById(hafasInputFields[i]["id"])){
              document.getElementById(hafasInputFields[i]["id"]).onfocus = null;
              document.getElementById(hafasInputFields[i]["id"]).onkeyup = null;
              document.getElementById(hafasInputFields[i]["id"]).onblur = null;
              document.getElementById(hafasInputFields[i]["id"]).onclick = null;
            }
          }
          return false;	
        }
      }
    }
    // Datei anfordern (asynchron)
    var tempURL = XMLRequestURL+input+"&";
    if(hafasInputFields[fieldIndex]['locType'] && document.getElementsByName(hafasInputFields[fieldIndex]['locType'])[0]){
      var currentLocType = document.getElementsByName(hafasInputFields[fieldIndex]['locType']);
      var currentLocTypeValue = 7;
      for(i=0; i<currentLocType.length;i++){
        if((currentLocType[i].checked == true) || (currentLocType[i].type == "hidden"))
          currentLocTypeValue = currentLocType[i].value;
      }
      tempURL = tempURL+XMLRequestURL2+currentLocTypeValue+"&";
    }
    SLs.ajax.open('GET', tempURL, true);
    SLs.ajax.setRequestHeader('Content-Type', 'text/xml');
    // umgeht Internet Explorers Caching von GET-Anfragen
    SLs.ajax.setRequestHeader('If-Modified-Since', 'Sat, 1 Jan 2000 00:00:00 GMT');
    SLs.ajax.send(null);
    SLs.ajax.onreadystatechange = function() {
      // wenn Ergebnis komplett empfangen ist ...
      if (SLs.ajax.readyState == 4) {
        // Fehler bei der Uebertragung (Server nicht gefunden...)
        if (SLs.ajax.status != 200) {
          SLs.delete_SLs();
          return false;
        }
        // schreibe alle Vorschlaege in sls
        if(SLs.ajax.responseXML != null){
          var sls = SLs.ajax.responseXML.getElementsByTagName("suggestions");
          // Eine Schleife, die alle Vorschlaege durchlaeuft und jeden mit allen subnodes in den Container einfuegt
          for(var i = 0; i < sls.length; i++) {
            sugCount = 0;
            // Werden Eingaben schnell hintereinander geloescht und das Eigabefeld ist leer,
            // wird der Container geloescht waehrend die Funktion noch laeuft, daher Abbruch.
            if(SLs.container)klonen(sls[i].cloneNode(true), SLs.container);
            else return false;
            // Border wird erst hier gesetzt damit leeres div nicht zu sehen ist...
            SLs.container.style.borderWidth = "1px";
            if(sugCount < 10)SLs.container.style.height = "auto";
            else SLs.container.style.height = SLs.div_hoehe + "px";
            if(navigator.userAgent.toLowerCase().indexOf("msie")>-1) SLs.container.style.width = SLs.container.clientWidth+20;
            if(navigator.userAgent.toLowerCase().indexOf('msie')>-1 && navigator.userAgent.indexOf('7.0')<0){
              SLs.hideSelect();
            }
            if(sugCount < 1) SLs.delete_SLs();
            else suggestion(SLs.inputField, 40);
            return true;
          }
        }
        var nicht_gefunden = document.createTextNode("No suggestions for your input '" + input + "'.");
        SLs.container.appendChild(nicht_gefunden);
        return false;
      }
    }
  },

  delete_SLs: function() {
    // loescht den suggestion-Container
    if(SLs.container){
      document.getElementsByTagName("body")[0].removeChild(SLs.container);
      if(navigator.userAgent.toLowerCase().indexOf('msie')>-1 && navigator.userAgent.indexOf('7.0')<0){
        SLs.showSelect();
      }
      SLs.countList = -1;
     // SLs.inputField = null;
      SLs.container = null;
      SLs.currentTop = 0;
      SLs.currentBottom = 9;
    }
  },

  // Get x-positon of element
  getPosX: function(element){
    var curleft = 0;
    if (element.offsetParent){
       while (element.offsetParent){
          curleft += element.offsetLeft;
          element = element.offsetParent;
       }
    }
    else if (element.x)	curleft += element.x;
    return curleft;
  },

  // Get y-position of element
  getPosY: function(element){
    var curtop = 0;
    if (element.offsetParent)	{
       while (element.offsetParent){
          curtop += element.offsetTop;
          element = element.offsetParent;
       }
    }
    else if (element.y)	curtop += element.y;
    return curtop;
  },

  // hide select boxes in MSIE 6
  hideSelect: function(){
    var currentSelects = document.getElementsByTagName("select");

    for(var i=0; i<currentSelects.length; i++){
      var hideCurrentSelectX = false;
      var hideCurrentSelectY = false;
      var currentX = SLs.getPosX(currentSelects[i]);
      var currentY = SLs.getPosY(currentSelects[i]);

      if(SLs.pos_x <= currentX && currentX < SLs.pos_x+SLs.container.clientWidth)
        hideCurrentSelectX = true;
      else if(SLs.pos_x < currentX+currentSelects[i].clientWidth && currentX+currentSelects[i].clientWidth <= SLs.pos_x+SLs.container.clientWidth)
        hideCurrentSelectX = true;
      else if(SLs.pos_x > currentX && currentX+currentSelects[i].clientWidth > SLs.pos_x)
        hideCurrentSelectX = true;
      if(SLs.pos_y < currentY && currentY < SLs.pos_y+SLs.container.clientHeight)
        hideCurrentSelectY = true;
      else if(SLs.pos_y < currentY+currentSelects[i].clientHeight && currentY+currentSelects[i].clientHeight < SLs.pos_y+SLs.container.clientHeight)
        hideCurrentSelectY = true;

      if((hideCurrentSelectX) && (hideCurrentSelectY))
        currentSelects[i].style.visibility = "hidden";
    }
  },

  // show select boxes in MSIE 6
  showSelect: function(){
     var currentSelects = document.getElementsByTagName("select");
     for(var i=0; i<currentSelects.length; i++){
       if(currentSelects[i].style.visibility == "hidden")
         currentSelects[i].style.visibility = "visible";
     }
  }

};

function klonen(original, copy) {
  // Hilfsfunktion fuer suggestion-Darstellung im DOM
  // rekursiver Aufruf baut die gesamte Struktur des zu klonenden Elements nach.
  for(var i = 0; i < original.childNodes.length; i++) {
    var knoten = original.childNodes[i];
    switch (knoten.nodeType) {
      case 1:	// Elementknoten
        var neu = copy.appendChild(document.createElement(knoten.nodeName));
        for (var j = 0; j < knoten.attributes.length; j++) {
          neu.setAttribute(knoten.attributes[j].nodeName, knoten.attributes[j].nodeValue);
        }
        if(knoten.nodeName == "div"){
          //neu.onmousedown = new Function("ereignis", "selectEntry(this.firstChild.nodeValue);");
          neu.onmousedown = new Function("ereignis", "SLs.inputField.value = this.firstChild.nodeValue;clickSel = 1;");
        }
        sugCount++
        klonen(knoten, neu);
        break;
      case 3:	// Textknoten
        subknoten = document.createTextNode(knoten.nodeValue);
        copy.appendChild(subknoten);
      // andere Knotentypen sind nicht relevant
    }
  }
}
