+ };
+
+ // selects a portion of the input string
+ function createSelection(start, end){
+ // get a reference to the input element
+ var field = $input.get(0);
+ if( field.createTextRange ){
+ var selRange = field.createTextRange();
+ selRange.collapse(true);
+ selRange.moveStart("character", start);
+ selRange.moveEnd("character", end);
+ selRange.select();
+ } else if( field.setSelectionRange ){
+ field.setSelectionRange(start, end);
+ } else {
+ if( field.selectionStart ){
+ field.selectionStart = start;
+ field.selectionEnd = end;
+ }
+ }
+ field.focus();
+ };
+
+ // fills in the input box w/the first match (assumed to be the best match)
+ function autoFill(sValue){
+ // if the last user key pressed was backspace, don't autofill
+ if( lastKeyPressCode != 8 ){
+ // fill in the value (keep the case the user has typed)
+ $input.val($input.val() + sValue.substring(prev.length));
+ // select the portion of the value not typed by the user (so the next character will erase)
+ createSelection(prev.length, sValue.length);
+ }
+ };
+
+ function showResults() {
+ // get the position of the input field right now (in case the DOM is shifted)
+ var pos = findPos(input);
+ // either use the specified width, or autocalculate based on form element
+ var iWidth = (options.width > 0) ? options.width : $input.width();
+ // reposition
+ $results.css({
+ width: parseInt(iWidth) + "px",
+ top: (pos.y + input.offsetHeight) + "px",
+ left: pos.x + "px"
+ }).show();
+ };
+
+ function hideResults() {
+ if (timeout) clearTimeout(timeout);
+ timeout = setTimeout(hideResultsNow, 200);
+ };
+
+ function hideResultsNow() {
+ if (hidingResults) {
+ return;
+ }
+ hidingResults = true;
+
+ if (timeout) {
+ clearTimeout(timeout);
+ }
+
+ var v = $input.removeClass(options.loadingClass).val();
+
+ if ($results.is(":visible")) {
+ $results.hide();
+ }
+
+ if (options.mustMatch) {
+ if (!input.lastSelected || input.lastSelected != v) {
+ selectItem(null);
+ }
+ }
+
+ hidingResults = false;
+ };
+
+ function receiveData(q, data) {
+ if (data) {
+ $input.removeClass(options.loadingClass);
+ results.innerHTML = "";
+
+ // if the field no longer has focus or if there are no matches, do not display the drop down
+ if( !hasFocus || data.length == 0 ) return hideResultsNow();
+
+ if ($.browser.msie) {
+ // we put a styled iframe behind the calendar so HTML SELECT elements don't show through
+ $results.append(document.createElement('iframe'));
+ }
+ results.appendChild(dataToDom(data));
+ // autofill in the complete box w/the first match as long as the user hasn't entered in more data
+ if( options.autoFill && ($input.val().toLowerCase() == q.toLowerCase()) ) autoFill(data[0][0]);
+ showResults();