Autocomplete without AJAX

Today you will find many JavaScript autocomplete solutions. Every JavaScript library has autocomplete functionality but my goal was to create it short and simple as possible. Autocomplete doesn't imply AJAX, and this post shows how to implement autocomplete without AJAX.

Please try enter any text to the input fields. It should work in IE6, FF and Google Chrome. Example uses PHP to generate random autocomplete answers.

Instead of AJAX, script uses IFRAME and sets only src attribute to access web server for autocomplete answers. IFRAME will also cover drop down menu in IE6 (drop down menu will not stay on the top of div popup). So, the trick is in DIV that contains IFRAME and returned answers wrapped as SELECT MULTIPLE.

Install instructions:

  1. Include script.js file to the Web page (script is only 70 lines).
  2. Place "hidden" DIV below BODY tag (DIV contains IFRAME and it should be in one line).
  3. Make DIV hidden - apply styles to the DIV with id="autocomplete".
  4. Add onkeydown and onblur event handlers to the input fields (don't forget to set name to the input field).
  5. Add logic to the answers.php for typed text.

Here is complete JavaScript code for preview, or you can download redips3.tar.gz (2.8KB) demo.

var div;					   // reference to the div that contains iframe
var oInput;				   // current input field
var timer = null;    // timer reference (needed to cancel previous call)
var delay = 500;     // time to wait after last typed char to send request (milliseconds)
var stayVisible = 0; // div visibility flag
var url = 'answers.php?query='; // autocomplete url 

// set reference to the invisible div (after page is loaded)
window.onload = function () {div = document.getElementById('autocomplete')}

// called on keydown event in input field
function autocomplete(field, e){
	oInput = field; // set current input field
	switch(e.keyCode || window.event.keyCode){
		// tab, enter, shift, ctrl, alt, pause, caps lock
		case 9: case 13: case 16: case 17: case 18: case 19: case 20:
		// page up, page down, end, home, arrow left, arrow up, arrow right
		case 33:  case 34:  case 35:  case 36:  case 37:  case 38: case 39:
		case 45:  case 145:	// insert, scroll lock
		case 112:	case 113:	case 114: case 115: case 116: case 117: // F1,F2,F3,F4,F5,F6
		case 118: case 119: case 120: case 121: case 122: case 123: // F7,F8,F9,F10,F11,F12
			break;
		case 27: hidePopup(); break; // escape (hide div element)
		case 40: setFocus();  break; // arrow down (set focus to the multiple select)
		case 8: case 46: default:    // backspace, delete and default
			if (timer != null) clearTimeout(timer);         // cancel previous call
			timer = setTimeout(function(){popup()}, delay); // set new popup call
	}
}

// div popup
function popup(){
	// if user deletes content from input box, then hide popup and return
	if (oInput.value.length == 0) {hidePopup(); return}
	// define oTop, oLeft and box variables
	var oTop = oLeft = 0;
	var box = oInput;
	// find input field position and set popup position
	do {oLeft+=box.offsetLeft; oTop+=box.offsetTop} while (box=box.offsetParent);
	div.style.top  = (oTop + 22) + 'px';
	div.style.left = oLeft + 'px';
	// find iframe in div and set src attribute with parameters query and field name
	div.getElementsByTagName('iframe')[0].src = url+oInput.value+'&fname='+oInput.name;
}

// set focus to the multiple select (contentWindow works for IE6 and FF)
function setFocus(){
	stayVisible = 1; // set stayVisible flag (needed for onblur event on input field)
	div.firstChild.contentWindow.document.getElementsByTagName('select')[0].focus();
}

// hide popup
function hidePopup(){
	if (stayVisible == 1) {stayVisible = 0; return} // don't hide if flag exisits
	if (timer != null) clearTimeout(timer);         // cancel previous call
	div.style.visibility = 'hidden';                // hide div
}

// called on keydown event in multiple select (from iframe)
function keydown(oSelect, e){
	switch(e.keyCode || window.event.keyCode){
		// escape, backspace (hide popup and set focus to the input field)
		case 27: case 8:  hidePopup(); oInput.focus(); break;
		// tab, return (set value to the input field)
		case 9:  case 13: setValue(oSelect); break;
	}
}

// set value to the input box (used by keydown and ondblclick event)
function setValue(oSelect){
	var idx = oSelect.selectedIndex;
	oInput.value = oSelect.options[idx].text;
	div.style.visibility = 'hidden';
	oInput.focus();
}


Bookmark and Share

Leave a Reply