Autocomplete : make not automatically select first item

125 views
Skip to first unread message

SDB

unread,
Jul 9, 2008, 8:40:08 AM7/9/08
to Prototype & script.aculo.us
Hi

I'm using Autocomplete for the first time.

I would like it not to automatically select the first item in the
list.

In other words, it is entirely possible for the user to type something
that is not in the list, so I need the user to be able to press
escape, return or tab, and for the list to just dissapear, and the
text box contents to remain unchanged.

Any ideas?

Thanks in advance.

T.J. Crowder

unread,
Jul 9, 2008, 8:58:29 AM7/9/08
to Prototype & script.aculo.us
Simon -

When posting to a moderated group, it's sufficient to post *once* and
wait for the moderators to clear your message, rather than posting
repeatedly.

I've cleared this copy and binned the others.
--
T.J. Crowder
tj / crowder software / com

SDB

unread,
Jul 9, 2008, 8:59:21 AM7/9/08
to Prototype & script.aculo.us
Thanks a lot!

Apologies.

david winterbottom

unread,
Jul 9, 2008, 5:36:26 PM7/9/08
to Prototype & script.aculo.us
My solution to this one was to return a hidden first LI element and
use the updateElement callback to submit the form in the standard way
when the first (hidden) item is selected. This replicated the user
experience of being able to search normally, or select from the
options.

This autocompleter can be seen at www.borders.co.uk

dtrenz

unread,
Aug 25, 2008, 10:23:59 AM8/25/08
to Prototype & script.aculo.us
In controls.js; Line: 286; change "this.index = 0;" to "this.index =
-1;"

I would like to see this become an Autocompleter option in future
releases (e.g. { autoSelectFirst: false } )

On Jul 9, 8:40 am, SDB <simondeba...@hotmail.com> wrote:
> Hi
>
> I'm usingAutocompletefor thefirsttime.
>
> I would like it not to automaticallyselectthefirstitem in the
Message has been deleted

Jesper Rønn-Jensen

unread,
Oct 20, 2008, 9:00:47 AM10/20/08
to Prototype & script.aculo.us
Thanks for your really helpful advice.

I turned your suggestion into the following patch and also modified
the Rails auto_complete helper as well.
(the revision numbers unfortunately point at my local application
where I made the modification).

If you find this helpful, could you help me getting this committed
into the proper projects? :)
Thanks!

/Jesper Rønn-Jensen
Blog http://justaddwater.dk/

--
Index: vendor/plugins/auto_complete/README
===================================================================
--- vendor/plugins/auto_complete/README (revision 878)
+++ vendor/plugins/auto_complete/README (working copy)
@@ -20,4 +20,6 @@
* http://script.aculo.us/demos/ajax/autocompleter
* http://script.aculo.us/demos/ajax/autocompleter_customized

+* Autocompleter URL: http://github.com/rails/auto_complete/
+
Copyright (c) 2007 David Heinemeier Hansson, released under the MIT
license
Index: vendor/plugins/auto_complete/lib/auto_complete_macros_helper.rb
===================================================================
--- vendor/plugins/auto_complete/lib/auto_complete_macros_helper.rb
(revision 878)
+++ vendor/plugins/auto_complete/lib/auto_complete_macros_helper.rb
(working copy)
@@ -55,6 +55,9 @@
# the entire element is used.
# <tt>:method</tt>:: Specifies the HTTP verb to use
when the autocompletion
# request is made. Defaults to
POST.
+ # <tt>:auto_select_first</tt>:: Toggle auto selection of first
item found in autocompleter.
+ # 'true'~=mac style, 'false'~=pc
style
+ # (defaults to true)
def auto_complete_field(field_id, options = {})
function = "var #{field_id}_auto_completer = new
Ajax.Autocompleter("
function << "'#{field_id}', "
@@ -62,15 +65,16 @@
function << "'#{url_for(options[:url])}'"

js_options = {}
- js_options[:tokens] =
array_or_string_for_javascript(options[:tokens]) if options[:tokens]
- js_options[:callback] = "function(element, value) { return
#{options[:with]} }" if options[:with]
- js_options[:indicator] = "'#{options[:indicator]}'" if
options[:indicator]
- js_options[:select] = "'#{options[:select]}'" if
options[:select]
- js_options[:paramName] = "'#{options[:param_name]}'" if
options[:param_name]
- js_options[:frequency] = "#{options[:frequency]}" if
options[:frequency]
- js_options[:method] = "'#{options[:method].to_s}'" if
options[:method]
+ js_options[:tokens] =
array_or_string_for_javascript(options[:tokens]) if options[:tokens]
+ js_options[:callback] = "function(element, value) { return
#{options[:with]} }" if options[:with]
+ js_options[:indicator] = "'#{options[:indicator]}'" if
options[:indicator]
+ js_options[:select] = "'#{options[:select]}'" if
options[:select]
+ js_options[:paramName] = "'#{options[:param_name]}'" if
options[:param_name]
+ js_options[:frequency] = "#{options[:frequency]}" if
options[:frequency]
+ js_options[:method] = "'#{options[:method].to_s}'" if
options[:method]
+ js_options[:autoSelectFirst] =
"'#{options[:auto_select_first].to_s}'" || "true"

- { :after_update_element => :afterUpdateElement,
+ { :after_update_element => :afterUpdateElement,
:on_show => :onShow, :on_hide => :onHide, :min_chars
=> :minChars }.each do |k,v|
js_options[v] = options[k] if options[k]
end
Index: public/javascripts/controls.js
===================================================================
--- public/javascripts/controls.js (revision 883)
+++ public/javascripts/controls.js (working copy)
@@ -40,14 +40,15 @@
var Autocompleter = { }
Autocompleter.Base = Class.create({
baseInitialize: function(element, update, options) {
- element = $(element)
- this.element = element;
- this.update = $(update);
- this.hasFocus = false;
- this.changed = false;
- this.active = false;
- this.index = 0;
- this.entryCount = 0;
+ element = $(element)
+ this.element = element;
+ this.update = $(update);
+ this.hasFocus = false;
+ this.changed = false;
+ this.active = false;
+ this.index = 0;
+ this.entryCount = 0;
+ this.autoSelectFirst = 'true';//toggle auto selection of first
item found in autocompleter.'true'~=mac, 'false'~=pc
this.oldElementValue = this.element.value;

if(this.setOptions)
@@ -55,11 +56,12 @@
else
this.options = options || { };

- this.options.paramName = this.options.paramName ||
this.element.name;
- this.options.tokens = this.options.tokens || [];
- this.options.frequency = this.options.frequency || 0.4;
- this.options.minChars = this.options.minChars || 1;
- this.options.onShow = this.options.onShow ||
+ this.options.paramName = this.options.paramName ||
this.element.name;
+ this.options.tokens = this.options.tokens || [];
+ this.options.frequency = this.options.frequency || 0.4;
+ this.options.minChars = this.options.minChars || 1;
+ this.options.autoSelectFirst = this.options.autoSelectFirst ||
this.autoSelectFirst;
+ this.options.onShow = this.options.onShow ||
function(element, update){
if(!update.style.position ||
update.style.position=='absolute') {
update.style.position = 'absolute';
@@ -281,8 +283,7 @@
}

this.stopIndicator();
- this.index = 0;
-
+ this.index = this.options.autoSelectFirst==='false' ? -1 : 0;
if(this.entryCount==1 && this.options.autoSelect) {
this.selectEntry();
this.hide();

doofus

unread,
Oct 21, 2008, 6:30:06 PM10/21/08
to Prototype & script.aculo.us
thanks for the tip guys.

Setting the index to -1 works, but i get the following error when I
actually hit enter to submit the form (the form does submit though,
but I can see the error):

Index or size is negative or greater than the allowed amount" code: "1

on this line:

return this.update.firstChild.childNodes[index];

in:
controls.js (line 228 for me)

I tracked it down to the onkeypress event and what is triggered when
you hit ENTER. this triggers the selectEntry method which calls
updateElement(this.getCurrentEntry()), and of course there is no
current entry ...

replacing the contents of selectEntry with this seemed to work:
if(this.index != -1){
this.updateElement(this.getCurrentEntry());
}

but if you use afterUpdateElement for any additional processing, this
will not run because it is called within updateElement.

so until somebody fixes this (because this is a ugly hack), I modified
selectEntry to this:

selectEntry: function() {
this.active = false;
if(this.index != -1){
this.updateElement(this.getCurrentEntry());
}else{
if (this.options.afterUpdateElement)
this.options.afterUpdateElement(this.element, new Element('li',
{id: '', name: ''}));
}
}


On Oct 20, 6:00 am, Jesper Rønn-Jensen <jespe...@gmail.com> wrote:
> Thanks for your really helpful advice.
>
> I turned your suggestion into the following patch and also modified
> the Rails auto_complete helper as well.
> (the revision numbers unfortunately point at my local application
> where I made the modification).
>
> If you find this helpful, could you help me getting this committed
> into the proper projects? :)
> Thanks!
>
> /Jesper Rønn-Jensen
> Bloghttp://justaddwater.dk/
>
> --
> Index: vendor/plugins/auto_complete/README
> ===================================================================
> --- vendor/plugins/auto_complete/README (revision 878)
> +++ vendor/plugins/auto_complete/README (working copy)
> @@ -20,4 +20,6 @@
>  *http://script.aculo.us/demos/ajax/autocompleter
>  *http://script.aculo.us/demos/ajax/autocompleter_customized

luniki

unread,
Oct 22, 2008, 7:49:41 AM10/22/08
to Prototype & script.aculo.us
You could fork the official scriptaculous git repository at github
(http://github.com/madrobby/scriptaculous/tree/master), patch it and
send a pull request to madrobby. I like your patch and would vote +1
if necessary :-)
Reply all
Reply to author
Forward
0 new messages