The Sciptaculous Autocompleter Disappears in IE!

By Jeff Denton Jun 30, 2009

Recently, a client was having trouble with an autocompleter implementation I had built for them.  This particular application contains a call log module that Autocomplete screenshotallows the client to log every contact made with a customer: phone, walk-in, email, etc.  In order to speed up call log entries while on the phone, I created a customer lookup feature that includes an autocompleter on the last name field.  The client begins typing in the last name field and a list of potential matches pops up. The client selects the correct customer if they exist, the customer information populates and the client can then begin entering information about this particular contact.

The contact log has reached over 2000 entries by now and there are many customers in the database with similar/same last name. This causes the autocomplete list to extend past the defined height of the container div in many instances which in turn causes scroll bars to appear.  Great - everything working as it should.  But...in IE 7 and 8 clicking on the scroll bars to view the hidden content causes the div and the autocomplete list to vanish!  Oops! In Firefox, everything works fine.

Here's a great forum post on how to fix this problem but I'll lay it out here a little more cleanly. The application UI is built on Prototype and Scriptaculous so we're using Ajax.Autocompleter to make this happen.

We're assuming the autocomplete textbox id is nameLast and the autocomplete div id is nameLastAutocompleter. First, replace your autocompete instantiation code with something like this:

var autocompleteLastName = new Ajax.Autocompleter('nameLast', 'nameLastAutocompleter', memberLookupLastNameURL, {paramName: "autoText", minChars: 3, updateElement: this.returnAutocompleterFieldsMember});
		
Event.observe('nameLastAutocompleter', "mouseover", autocompleteLastName.onHover.bindAsEventListener(autocompleteLastName));
Event.observe('nameLastAutocompleter', "click", autocompleteLastName.onClick.bindAsEventListener(autocompleteLastName));
			
		if (Prototype.Browser.IE) {
			$('nameLastAutocompleter').observe('mousedown', function(e) {
				autocompleteLastName.dontBlur = true;
				e.stop();
			});
			$('nameLastAutocompleter').observe('blur', (function(e) {
			setTimeout((function() {
			if (! $('nameLast').focused)
			this.onBlur(e);
			}).bind(this), 100);
			e.stop();
			}).bindAsEventListener(autocompleteLastName));

			$('nameLast').observe('focus', function() { $('nameLast').focused = true; });
			$('nameLast').observe('blur', function() { $('nameLast').focused = false; });
		} else {
			$('nameLastAutocompleter').observe('mousedown', function(e) {
				e.stop();
			});
		} 

 Then, at the bottom of the Scriptaculous controls.js file (or any other globally included js file), add the following:

Autocompleter.Base.prototype.render = function() {
	if(this.entryCount > 0) {
		if (this.selected_item)
			Element.removeClassName(this.getEntry(this.selected_item-1),"selected");
			Element.addClassName(this.getEntry(this.index),"selected");
			this.selected_item = this.index+1;
			if(this.hasFocus) {
				this.show();
			this.active = true;
		}
	} else {
		this.active = false;
		this.hide();
	}
};

Autocompleter.Base.prototype.onHover = function(event) {
	var element = Event.findElement(event, 'LI');
	if(element && defined(element.autocompleteIndex) && this.index != element.autocompleteIndex) {
		this.index = element.autocompleteIndex;
		this.render();
	}
	Event.stop(event);
};

Autocompleter.Base.prototype.addObservers = Prototype.emptyFunction;

if (Prototype.Browser.IE) {
Autocompleter.Base.prototype.onBlur = function(event) {
	setTimeout((function(e) {
		if (this.dontBlur) {
			this.dontBlur = false;
			return;
		}
		this.hasFocus = false;
		this.active = false;
		this.hide();
		}).bind(this), 100);
	};
}

 It's a lot of code, I know - but it did the trick for me.

 

Add Your Comments