var typeAheadInfo = {last:0, 
                     accumString:"", 
                     delay:500,
                     timeout:null, 
                     reset:function() {this.last=0; this.accumString=""}
                    };
function typeAhead()
{
 if (window.event && !window.event.ctrlKey)// limit processing to IE event model supporter; don't trap Ctrl+keys
 {
  var now = new Date();// timer for current event
      // process for an empty accumString or an event within [delay] ms of last
      if (typeAheadInfo.accumString == "" || now - typeAheadInfo.last < typeAheadInfo.delay) {
         var evt = window.event;         // make shortcut event object reference
         var selectElem = evt.srcElement;         // get reference to the select element
         var charCode = evt.keyCode;         // get typed character ASCII value
         var newChar =  String.fromCharCode(charCode).toUpperCase();         // get the actual character, converted to uppercase
         typeAheadInfo.accumString += newChar;         // append new character to accumString storage
         var selectOptions = selectElem.options;         // grab all select element option objects as an array
         var txt, nearest;         // prepare local variables for use inside loop
         for (var i = 0; i < selectOptions.length; i++) { // look through all options for a match starting with accumString
            txt = selectOptions[i].text.toUpperCase(); // convert each item's text to uppercase to facilitate comparison (use value property if you want match to be for hidden option value)
            nearest = (typeAheadInfo.accumString > txt.substr(0, typeAheadInfo.accumString.length)) ? i : nearest;// record nearest lowest index, if applicable
            // process if accumString is at start of option text
            if (txt.indexOf(typeAheadInfo.accumString) == 0) {
               clearTimeout(typeAheadInfo.timeout);               // stop any previous timeout timer
               typeAheadInfo.last = now;               // store current event's time in object 
               typeAheadInfo.timeout = setTimeout("typeAheadInfo.reset()", typeAheadInfo.delay);// reset typeAhead properties in [delay] ms unless cleared beforehand
               selectElem.selectedIndex = i;// visibly select the matching item
               evt.cancelBubble = true;// prevent default event actions and propagation
               evt.returnValue = false;
               return false;   
            }            
         }
         // if a next lowest match exists, select it
         if (nearest != null) {selectElem.selectedIndex = nearest;}
      } else {
         // not a desired event, so clear timeout
         clearTimeout(typeAheadInfo.timeout);
      }
      typeAheadInfo.reset();
   }
   return true;
}         

