Enhance autocomplete feature
kkaefer - March 6, 2007 - 14:55
| Project: | Drupal |
| Version: | 7.x-dev |
| Component: | javascript |
| Category: | feature request |
| Priority: | normal |
| Assigned: | Unassigned |
| Status: | needs work |
| Issue tags: | accessibility |
Description
The attached patch enhances the autocomplete list in serveral ways:
- It improves the code quality of the
autocomplete.jsand moves all JS objects to theDrupal.autocompletenamespace. - The cursor is now moved to the end of the textfield in Safari when a user selects an autocomplete item.
- It allows modules to provide more than just one string for an autocomplete entry, allowing “rich” items. For example, you can use bold formatting, links and even images (e.g. avatars when autocompleting users). This allows modules to give more context when selecting an item. E.g. when a node should be selected, it’s often hard to tell from the title of the node if it’s the correct one. Additional information are often useful.
Also, there is a new theme functiontheme_autocomplete_itemthat allows themes to modify the structure of an autocomplete item. - There is a new field
infoin the autocomplete JSON object which can contain general information about the autocompletion. In the patch it is for example used to display the user who many items in addition to the 10 displayed were found. This is a freeform HTML field that is not selectable (as opposed to regular items).
| Attachment | Size | Status | Test result | Operations |
|---|---|---|---|---|
| autocomplete_3_0.patch | 18.92 KB | Ignored | None | None |

#1
It allows modules to provide more than just one string for an autocomplete entry
Isn't this possible already ?
the autocomplete widget for CCK nodereference fields can currently be set to return stylable Views-generated HTML.
#2
This looks good, thanks for giving autocomplete some needed attention. I've given the code only a quick initial review. The namespace introduction is a good simple improvement. I like the move to pass autocomplete data in settings rather than the current awkward encoding in a form field.
There are various other issues with the autocomplete implementation. Likely they should be left for separate patches. I'll mention them, though, in case you're inspired to tackle one or more along with these improvements.
_element_info(). Here, like many other places (notably our form element theme functions), we've rather crudely hacked js behaviours into core. The yardstick should be, can this same approach be applied by contrib modules (where we don't have the option of hacking core)? If not, then we're not doing it correctly. In this case, we should look at registering a #process callback to the textfield form element insystem_elements()to handle the processing.Drupal.ACDB.prototype.searchfunction. It would be nice to leave an opening for contrib behaviours to respond to a 'no matches' return.A comment and question or two:
exit();at the end ofdrupal_autcomplete().this.popup =to a jquery result set is an interesting approach. The subsequentthis.popup[0].ownerseemed awkward the first time I looked at it, but I see the power of returning a jquery reference rather than a direct object reference.$(this.input.form).submit(Drupal.autocomplete.submit);Why submit the autocomplete when the form is being submitted?#3
Does core take advantages of any of the new features? Could it take advantage of them? It's always nice to set good examples.
Update: looks like the user and taxonomy code takes advantage of this. Care to share a screenshot? It would save many of us time to setup such a large list of taxonomy terms. :-)
The taxonomy and user module changes needs more work. It's not a good idea to use the pager, and then to read out internal pager variables by setting them global. That's a hack, IMO.
This patch has great potential, but needs a little bit more work. ;)
#4
Yes, this is possible at the moment, but not officially supported. The implementation for this is not really bullet-proof at the moment. Currently, it’s done using
.html('<div>'+ matches[key] +'</div>')withmatches[key]being the “string” returned from autocomplete. However, I could imagine that there are some weird combinations of HTML tags that confuse jQuery and break the autocompletion. Therefore, I changed that to the “correcter” way.html(matches.matches[key]). Using HTML in the autocomplete string is now recommended and “officially allowed”.Yeah, forgot to mention that. I think killes once had some issues with differing IDs in the hidden form field and the actual autocomplete field.
nedjo’s first point is so true: Currently, we add the autocomplete JS files in a theme function instead of adding them programmatically somewhere during the build process. The second point is also a logical step.
Drupal.autocomplete.fieldis completely independent ofDrupal.autocomplete.handlerand can be used separately. In fact, I’ve even used to do non-AJAX autocompletion.We had
exit;calls there before, but I removed them on purpose. Just exiting in the middle of a script makes it impossible for other modules do perform actions inhook_exit(). And if everything is correctly implemented (like it is atm), everything works fine and we don’t get JavaScript errors. If we do, we made something wrong (e.g. not checking for the Content-type when outputting something). So this can be understood as a kind of “indicator” for the exitting system working correctly.You misunderstood something here. There is no submit handler called in this line. However, a new submit handler (the function
Drupal.autocomplete.submit) is added as submit handler to the current form. This submit function (which has been present before) checks if the autocomplete popup is open. So when the user hits enter for the first time, the popup closed instead of the form being submitted right away.Yes, it could be considered a hack and could be refactored. Any suggestions?
#5
It has always been possible to use HTML in the autocomplete matches. There was nothing hackish or unofficial about this, and this is why check_plain() was needed for autocomplete matches. I don't see what the presence of a wrapper div would do to change that. It just ensures the items stack vertically and automatically have a block-level enclosing. PS:
<code>tags on Drupal.org escape for you.While I applaud moving towards clean settings rather than hidden form items, and cleaning up the JS code, I'm not sure about some of the other bits though:
form_autocomplete()is a weird function. It adds the JS headers, but not the CSS class... so it is useless for re-use. Either rename it and document it as an internal helper, or just move it back in. It's only two lines after all.I also think we should do more useful things with these in core, for example by displaying avatars in user results and displaying the number of nodes that have a certain tag in brackets (and grayed out) behind the tag name.
#6
This looks very interesting, as I'm currently dealing with dynamically altered autocomplete fields. By using a global storage (
Drupal.autocomplete.handlers) it'd be finally possible to alter the autocomplete uri on the fly, ie. extend it with a dynamic value from another form field.The only question that arises for me is: could the code by changed to store the handlers by id instead of uri? That is, change
Drupal.autocomplete.attach()toif (!handlers[id]) {handlers[id] = new Drupal.autocomplete.handler(url);
}
instead of assigning to handlers[uri]? I'm primarily asking if this would have any negative consequences. The use should be obvious: the autocomplete uri could be much easier updated, because I can access the storage by a static id instead of an ever changing uri.
#7
Couldn't we even go beyond the above said and make the two central handlers dealing with the autocomplete results –
Drupal.autocomplete.field.found()andDrupal.autocomplete.field.select()– user-definable? Placing the handlers in the very same Drupal.settings object and falling back to the default if nothing has been overridden would allow a 3rd party module to reuse 90+% of the existing code. It would just have to provide said functions and set them via a new forms api element#autocomplete_handler, for example. Of course, refactoring common stuff out of Drupal.autocomplete.field.found() would make such "add-ons" even shorter, probably leaving only the block commented// Prepare matchesin.#8
Any updates?
#9
Please update or re-roll the patch..
I'll give this a proper review when the code is updated or the patch is rerolled.
(While i'm not a jQuery guru, I can not test the patch right now)
#10
@Steven:
theme_autocomplete_item()anymore.form_autocomplete()back into every single autocomplete function.@smk-ka: The reason we use url here is that we can have multiple autocomplete fields with the same url per page. Now, if you type “ab” in one field, the results are cached. If you type “ab” in the other field with the same AJAX callback but another ID, it requeries the server instead of obtaining the results from the cache. Do you have a use case where you want to change autocomplete callbacks? Wouldn’t it be easier to negiocate that on the server side?
By the way, it is already possible to override every single autocomplete function: Just create a new object and overwrite the function (yes, JavaScript is that flexible!):
var x = new Drupal.autocomplete.field($('#' + id)[0], handlers[url]);x.search = function(searchString) {
// Do your stuff here
this.owner.found(...);
}
There are still no avatars in user autocompletion as I think that the popup could grow too big (10 * 85 pixels = 850 pixels at least). Maybe we can look into resizing them, but afaik, we don’t have small avatars in core as of now.
Now, the title is not bold anymore in its entirety. Instead, the parts of the text the user entered is highlighted. If the user enters “ue”, the last two characters of “Blue” are now bold.
Also, it is now possible to search for any parts of user names instead of just from the beginning. Searching for “kaefer” will now also return “kkaefer”. with all but the first character highlighted.
#11
No longer applies. This is usability so leaving in D6.
#12
I'd just like to add on and say that this is a necessary update to autocomplete functionality.
There are countless situations like http://drupal.org/node/52568 where you would want the autocomplete display value (even in the textfield) to be different than the returned value from the form.
This will happen anytime there is a non-unique display item (like node title or a user's name) and a non-displayable unique ID (like uid or nid). It presents information that is useless to the user. While it may be acceptable for entering such data, going back and editing a field like that means you just see a meaningless number.
I will be trying this code but it probably still needs work...
The user avatar problem can be solved with imagecache. We can create a module for enhanced user autocomplete with a dependency or optional extension if imagecache is enabled.
#13
Moving feature requests to D7 queue.
#14
Just bumping, because we had a discussion at FosDem about autocomplete in core, what people are looking for is something like this
http://jquery.bassistance.de/autocomplete/ ans since we're using jquery 1.2.3, I guess it can't be that hard to do :p
For the moment I don't have the time to do this myself, but ...
Cheers,
Peter
#15
Subscribing.
#16
I'm gonna bring this up at MIT Codesprint after Drupalcon. I guess we'll see if we do it!
#17
subscribing...
#18
Subscribing...
I had conversations with several people about this in Boston. I've been working on an add-on module for a Drupal 5x client that adds the unique key behavior described above. It's not currently a one-size-fits-all solution. In addition, I've done some client-focused autocomplete work for taxonomy that routes through a theme function. In Boston we updated my 5x module to a proof of concept for D6 but it needs a JS overhaul.
So I think all of these things are possible. The problem I anticipate with the unique key situation is usability. What happens for screen readers or JS-disabled situations? I propose gathering the possible responses with a user-supplied function that returns a structured array. Then upon validation error (indicating that JS may not have been enabled) we display a select list of the possible matches. Some modules like nodequeue append the unique ID to the displayed string like:
Node Title [nid0234]
This works to a point, but no human being should be expected to conform to this format.
Quicksketch suggested gathering the autocomplete parameters using the JS settings array. I think this is a great idea. He also encouraged me to work on the HEAD branch rather than a contrib module for D6.
I'd also like to see a client-side API for clearing the autocomplete cache or manually adding items. This is something that I worked around in my 5x solution.
#19
sub'ing
#20
subscribing, and second #14
#21
Subscribing
#22
subscribing.
#23
subscribing
#24
Science Collaboration Framework could use this for both an enhanced nodereference and custom autocomplete fields. So... uh... subscribing until i have more to offer.
benjamin, Agaric Design Collective
#25
There are nice auto complete options in both google & yahoo. Important to have this function available to screen readers.
#26
hi. @mgifford, how exactly is this related to screen readers and accessibility? thanks.
#27
Look at #18. But also feedback from a blind user who was surprised to hear that there were autocomplete features because his modern screen reader didn't display it.
Mike
#28
Related improvement that should probably be folded into this: #490092: Autocomplete should have everything selected when clicked
#29
I think it's important to allow to show anything to the user, while passing something else to the module. Otherwise we always have to process the entry.
The node selection is a good example, like in CCK Nodereference. Since the node title is not unique, we need to specify also the NID :
- for the user, but knowing the difference of NIDs is not very usable
- for Drupal, otherwise only the first result value will be displayed
Resolving that issue would suppose :
- to have the NID in the returned JSON, but hidden from the user
- when a result is clicked on, to display the node title in the Nodereference Autocomplete field, but it should not be the value, it is the NID which should be the value (is this even possible ??? maybe with Javascript ? modifying the display of the value but not really the value itself ?)
- same problem when editing a node with an already filled-in value in the autocomplete field.
Consider this as a big "Subscribe", work on core is still beyond my skills :)
#30
second #14: the autocomplete script at http://jquery.bassistance.de/autocomplete/ works also when pasting text in the textfield.
Actually if you try to copy/paste content in an autocomplete field in Drupal, makes autocomplete fail and give out all values.
Copy/Paste functionality would be nice in Drupal too.
#31
Yes, patch in comment #10 is pretty busted now.
How did you apply the auto complete script in #14 or are you just proposing it?
Was just, just updated it seems -->> 22-Aug-2009
#32
I have noticed something very annoying when using Keyword Autocomplete, which uses autocomplete.js to auto-complete a search box with popular search strings. Basically, a user has to hit enter/return TWICE to submit the search form if the popup window is open, even if they have strictly typed their search term and not selected anything in the popup. I understand that we don't want to accidentally submit the form if people are selecting items in the popup- but instead of blocking the form submit on the enter/return keystroke whenever the popup is open, can we just block the submit if an item in the popup menu is actually selected?
#33
@marcoBauli I'm not sure that the software license or ownership of the code is clear here - http://jquery.bassistance.de/autocomplete/
This looks like it's not as actively developed, but more official - http://plugins.jquery.com/project/jq-autocomplete
There's this one http://dyve.net/jquery/?autocomplete & variations http://www.pengoworks.com/workshop/jquery/autocomplete.htm
Looks interesting, but not Apache license & not GPL - http://code.google.com/p/jqac/
Is there a reason for a drupal specific auto-complete form? have any of the ones above been tested for accessibility? Others?