Seiten

Freitag, 8. Januar 2010

AJAX: HTML-Element für Autovervollständigung

Nachdem ich nach einigem Suchen kein stabiles Element für eine AJAX-Autocomplete Funktion gefunden habe, hier mein Mix aus einem Text- und Listenfeld.

Zum Test einfach etwas eingeben (ohne Datenanbindung).

var charCode = 0;      // Tastencode aus beiden Steuerelementen
var optText  = null;   // Textfeld
var optList  = null;   // Listenfeld
var topOpt   = false;  // Hilfsvariable zum Steuern des Uebergangs
var oldText  = "";     // Vorwert aus Textbox merken

function Init(obj)  {
  if(optList)  // Falls noch andere Liste offen
    //CloseList(false);  // IE hängt sich auf
    optList.style.display = 'none';
    
  optText = obj;
  optList = GetSelect(optText);  // SELECT-Element ermitteln
  // geerbte Breite des Eingabefeldes an SELECT-Element weitergebn
  optList.style.width = optText.offsetWidth + "px";
  // Variable charCode setzen
  document.onkeydown = GetKeyCode;
}
function OpenList()  {  
  oldText = optText.value;  // Wert für Abbruch merken

  if(charCode == 27)  {  // ESC
     optList.style.display = 'none';  // Liste wieder zu machen
     return;
  }
  if(charCode == 13)  {  // ESC
     optList.style.display = 'none';  // Liste wieder zu machen
     // Event valuefixed auslösen
     return;
  }  

  if(optText.value.length > 0)  {  // ist etwas im Textfeld
    topOpt = true;  // Pfeiltaste nach oben soll Textfeld aktivieren
     
    with(optList)  {
      // bei diesen Tasten Liste anzeigen
      if(
          charCode ==   8 ||  // Backspace
          charCode ==  40 ||  // Pfeil nach unten
          charCode ==  46 ||  // Delete
         (charCode >=  48 && charCode <= 57) ||  // 0-9
         (charCode >=  65 && charCode <= 90) ||  // a-z
          charCode == 109 ||  // - 
          charCode == 190 ||  // .
          charCode ==  59 ||  // ü
          charCode == 192 ||  // ö          
          charCode == 219 ||  // ß
          charCode == 222     // ä
        )  {
      style.display = 'block';  // Liste anzeigen
      selectedIndex = -1;       // nichts auswaehlen
    }
    }
  }
  else
    CloseList(false);  // wurde z.B. alles geloescht, Liste schliessen
  
  // Übergang zur Liste bei...  
  if(charCode == 40 &&  // ... Pfeiltaste nach unten
     optList.style.display == 'block')  {  // und Liste offen
     
    optText.value = optList.options[0].value;  // Textbox aktualisieren
    optList.focus();                // Liste aktivieren
    optList.selectedIndex = 0;      // ersten Eintrag auswählen 
  }
}
function CloseList(setOpt)  { 
  if(setOpt && (optList.options.length != optList.selectedIndex + 1))  {
    optText.value = optList.value;  // Listenwert ins Textfeld
    // Event valuefixed auslösen
  }
  else  {
    optText.value = oldText;
    oldText = null;
  }  
  optText.focus();  // Textfeld aktivieren
  optList.style.display = 'none';  // Liste ausschalten
}
function CancelSelect()  {
  optList.style.display = 'none';  // Liste ausschalten 
  optText.value = oldText;  // gemerkten Text einsetzen
  optText.focus();  // Textfeld aktivieren
}
function CtrlList()  {

  if(charCode == 13)  // Enter
     CloseList(true);
  if(charCode == 27)  // ESC
     CancelSelect();        
  if((charCode == 38 || charCode == 40) &&  // Pfeiltaste oben unten
     optList.options.length != optList.selectedIndex + 1)  // nicht letzte Option
     optText.value = optList.value; 
      
  if(charCode != 38)  // nicht Pfeiltaste nach oben
    topOpt = false;
        
  // Pfeiltaste nach oben und oberster Eintrag ausgewaehlt  
  if(charCode == 38 && optList.selectedIndex == 0)  {
    if(topOpt)  {  // beim ersten Mal noch nichts machen
      optList.style.display = 'none';  // Liste ausschalten
      optText.focus();  // Textfeld aktivieren 
    }
    else
      topOpt = true;  // um beim zweiten Pfeiltaste nach oben      
  }                   // Steuerelement zu wechseln
}
function GetKeyCode(e) {
  if (!e)
    e = window.event;
  charCode = e.keyCode;
}
function GetSelect(obj)  {
  var count = 0;
  do  {    
    var elem = obj.nextSibling;
    obj = elem;
    
    count++;
    if(count > 3) break;
  } while(elem.type != "select-one")
  
  return elem;
}
function FixValue()  {
  // TODO: Event valuefixed auslösen
  // aktives Element oder Tastencodes prüfen
}
CSS im HEAD:
input.autocomplete  {
 width: inherit;
}
input.autocomplete  {
  display: block;
}
select.autocomplete  {
  display: none;
  position: absolute;
}
#autocomplete1  {
 float: left;
 width: 200px;
}
#autocomplete2  {
   float: left;
 width: 200px;
}
.lastopt  {
  background-color: lightgray;
}
HTML im BODY:
<div id="autocomplete1">
  <input type="text" name="autocomplete2" class="autocomplete" onclick="this.focus();" onfocus="Init(this)" onkeyup="OpenList();" onblur="FixValue();" tabindex="2" />
  <select size="4" class="autocomplete" onclick="CloseList(true);" onkeyup="CtrlList();">
    <option value="Peter">Peter</option>
    <option value="Peters">Peters</option>
    <option value="Petersen">Petersen</option>
    <option value="Petersohn">Petersohn</option>
    <option class="lastopt" title="Schließen">⇑</option>
  </select>
</div>
Download komplettes Beispiel komplettes Beispiel

Keine Kommentare:

Kommentar veröffentlichen