Wednesday, September 8, 2010

jQuery, jRails and autocomplete

Recently, I choose to switch the Rails-bundled Prototype library with jQuery/jRails for a project. All went smooth (great job guys!) save for a catch: the autocomplete plugin stopped working :(

Looking for an alternative I stumbled on jrails_auto_complete plugin. It is supposed to be a drop-in replacement for the DHH Prototype one. And it indeed was.

With the DHH plugin, I had been using multi-line formating and styling in my list elements using DIVs insile the LIs. With the new jRails thing these multil-ine elements exhibited a small problem with mouse navigation and clicking in the drop down list elements:

  • Mousing over list elements, would only highlight them when the pointer was hovering on the element border. Move a bit inside and the highlight was gone.
  • Clicking to select would cause all the list element titles to be pasted in the text field causing a mess and of course, no actual selection was made.

Funny though, there was no problem navigating with the keyboard.

Googling I only found one relevant post by a guy experiencing the same thing and thanks to him I got some insight on what was actually going on. The plugin is relying on the mouseover event firing from the element to make the highlight and update the internal selection index. However, in my (our) case, child objects inside the LI element fired their own mouseovers as well, which bubbled up and where intercepted too. As child objects don't get a selection index property added, the plugin code just invalidated the selection, hence no highlight anywhere.

My (naive) solution was to change jrails_autocomplete.js as follows:

    onHover: function(e) {
var my_index = e.target.autocompleteIndex;
if (!my_index) {
my_index = $(e.target).closest('li').attr('autocompleteIndex');
}
if (this.index != my_index) {
this.index = my_index;
this.render();
}
stopEvent(e);
},

This basically searches the closest LI parent for an autocompleteIndex property if one isn't found in the element that fired the event.

For the second problem I just glanced over the keyboard part of the code which looked similar and finally decided to just comment out the line (re)setting the index out of the element clicked:

    onClick: function(e) {
/*this.index = e.target.autocompleteIndex;*/
this.selectEntry();
this.hide();
},


Thanks to the guy over at StackOverflow who gave me the heads-up with his question. It has been some time since he posted but I hope he finds my solution of some use.

No comments:

Post a Comment