Re: [development] "Subclassing" the standard #autocomplete form
I may not have this quiet right but isn't this what hook_autocomplete is for? http://api.drupal.org/api/HEAD/function/user_autocomplete You can print drupal_to_js($my_array)? Mostly emailing a response because I would like to know the answer too. Date: Wed, 17 Jan 2007 17:43:10 -0800
From: Rob Thorne <rob@torenware.com> Subject: [development] "Subclassing" the standard #autocomplete form widget To: development@drupal.org Message-ID: <45AED0AE.5060806@torenware.com> Content-Type: text/plain; charset=ISO-8859-1; format=flowed
I need a widget for Forms API which *almost* identical to the textfield autocomplete widget in 5.0. I want the same user experience -- the user types and chooses an item. But I want the underlying AJAX and Drupal behavior to differ a bit.
An example of the type of widget I'd want would be a "Country Selection" widget where what I really want is the two-character country code (US, CA, GB, FR, and so on), but I want the user to think of typing "United States", "Canada", "Great Britain", "France" or so on in order to get the popup to get set on this code.
Looking through the 5.0 sources, the way the current autocompletion widget works is via includes/form.inc, where the theming function theme_textfield($element) special cases textfields with the '#autocompletion_path' , by making sure that autocomplete.js gets added to the page going out, and by adding a hidden <item> to store state information that the code in autocomplete.js needs to do its work.
I really don't need to change behavior very much; I just need to send back an array of array(key, value), where the standard widget sends back an array of string values. But pretty much everything else that Unconed's code does exactly what I want, and while I can copy if if that's easiest, I don't want or need to change what he did.
What's the best way to create my modified Forms API widget? It looks like I'd want to "override" or "subclass" theme_textfield, although only to add behavior: I don't want standard autocomplete widgets to behave any different than usual (although I'd not want both sets of code to compete on the same widget). I'd then copy autocomplete.js and make very small changes in it, changing function names where required.
Is there a better way to do this? Or even better, has someone else already done this?
Thanks, Rob
Rob Thorne Torenware Networks
Scott, user_autocomplete() takes the string returned by the JavaScript widget, does the search -- in this case, for possible Drupal user name matches -- and returns the result as a JavaScript-formatted array. The one thing that's really interesting is the format of the array, which I see is really an associative array (and not a simple indexed array). I don't know how the standard widget would behave if it the key and value did not match. But at this point, I'd like to know as well. Rob Scott Reynolds wrote:
I may not have this quiet right but isn't this what hook_autocomplete is for? http://api.drupal.org/api/HEAD/function/user_autocomplete
You can print drupal_to_js($my_array)? Mostly emailing a response because I would like to know the answer too.
Date: Wed, 17 Jan 2007 17:43:10 -0800 From: Rob Thorne < rob@torenware.com <mailto:rob@torenware.com>> Subject: [development] "Subclassing" the standard #autocomplete form widget To: development@drupal.org <mailto:development@drupal.org> Message-ID: <45AED0AE.5060806@torenware.com <mailto:45AED0AE.5060806@torenware.com>> Content-Type: text/plain; charset=ISO-8859-1; format=flowed
I need a widget for Forms API which *almost* identical to the textfield autocomplete widget in 5.0. I want the same user experience -- the user types and chooses an item. But I want the underlying AJAX and Drupal behavior to differ a bit.
An example of the type of widget I'd want would be a "Country Selection" widget where what I really want is the two-character country code (US, CA, GB, FR, and so on), but I want the user to think of typing "United States", "Canada", "Great Britain", "France" or so on in order to get the popup to get set on this code.
Looking through the 5.0 sources, the way the current autocompletion widget works is via includes/form.inc, where the theming function theme_textfield($element) special cases textfields with the '#autocompletion_path' , by making sure that autocomplete.js gets added to the page going out, and by adding a hidden <item> to store state information that the code in autocomplete.js needs to do its work.
I really don't need to change behavior very much; I just need to send back an array of array(key, value), where the standard widget sends back an array of string values. But pretty much everything else that Unconed's code does exactly what I want, and while I can copy if if that's easiest, I don't want or need to change what he did.
What's the best way to create my modified Forms API widget? It looks like I'd want to "override" or "subclass" theme_textfield, although only to add behavior: I don't want standard autocomplete widgets to behave any different than usual (although I'd not want both sets of code to compete on the same widget). I'd then copy autocomplete.js and make very small changes in it, changing function names where required.
Is there a better way to do this? Or even better, has someone else already done this?
Thanks, Rob
Rob Thorne Torenware Networks
An example of the type of widget I'd want would be a "Country Selection" widget where what I really want is the two-character country code (US, CA, GB, FR, and so on), but I want the user to think of typing "United States", "Canada", "Great Britain", "France" or so on in order to get the popup to get set on this code.
Why do you need to submit the country code through the form? If the autocomplete is smart enough to change "Canada" into ".ca", then the code that processes the form can do so too. Various requests have been made top make the autocomplete 'smarter', by letting the displayed value be different from the submitted value. Usually, this is an abuse of the autocompleter that would be better solved by custom code, and it doesn't degrade without JavaScript at all. As far as subclassing autocomplete, the menu scout module does something like this. But I would only do it if you need significantly different behaviour. Here's how I would do it: - Make the text field always take a country name. It is the most user- friendly input format. - When the user types something, it does an ajax request to the server to look up the country and its code. If it is found, it is returned in a list that shows "Country (country code)" e.g. "Belgium (be)". Clicking a suggestion will fill in "Belgium", not "be". - When the user submits the form, the field value (country name) is compared to the database and the first match is used. - If nothing matches, a validation error is thrown. This applies both to JS and non-JS, as you can still type in random crap. For JS users, they get a nice, user-friendly direct autocomplete. Non- JS users just have to wait for the whole form to submit instead, but still get completion and validation. To really spice it up, you can use a suffix unit on the autocomplete field to display the country's flag, when found. Steven Wittens
Steven, The country example was just an example; I'm aware there are nicer ways to do country selection. I'm actually most interested in autocompleting from much larger sets, such as a voter file with thousands of records. I want the user to type a name, but get back the internal ID used to access that voter's information. For now, I'm doing what the CCK people are doing with their nodereference code. It's a bit of a hack (you append the $nid at the end of the string like this: Autocomplete Widget: This Is The Title Of My Node [NID] The submit code parses off the NID and throws the rest away. My Voter ID example would work the same way. The non-JavaScript code for this sort of thing embeds a look-up form where the AC widget would be. This is ugly, but the advantage of autocompleting is so great in this case that it's worth the effort. Some AJAX frameworks have a "combo-box" object that does exactly what I want to do here. I suspect there's some way to do this with JQuery, but since I'm just getting started with it, I'm open to suggests how this would work. Thanks, Rob Steven Wittens wrote:
An example of the type of widget I'd want would be a "Country Selection" widget where what I really want is the two-character country code (US, CA, GB, FR, and so on), but I want the user to think of typing "United States", "Canada", "Great Britain", "France" or so on in order to get the popup to get set on this code.
Why do you need to submit the country code through the form? If the autocomplete is smart enough to change "Canada" into ".ca", then the code that processes the form can do so too.
Various requests have been made top make the autocomplete 'smarter', by letting the displayed value be different from the submitted value. Usually, this is an abuse of the autocompleter that would be better solved by custom code, and it doesn't degrade without JavaScript at all.
As far as subclassing autocomplete, the menu scout module does something like this. But I would only do it if you need significantly different behaviour.
Here's how I would do it: - Make the text field always take a country name. It is the most user-friendly input format. - When the user types something, it does an ajax request to the server to look up the country and its code. If it is found, it is returned in a list that shows "Country (country code)" e.g. "Belgium (be)". Clicking a suggestion will fill in "Belgium", not "be". - When the user submits the form, the field value (country name) is compared to the database and the first match is used. - If nothing matches, a validation error is thrown. This applies both to JS and non-JS, as you can still type in random crap.
For JS users, they get a nice, user-friendly direct autocomplete. Non-JS users just have to wait for the whole form to submit instead, but still get completion and validation.
To really spice it up, you can use a suffix unit on the autocomplete field to display the country's flag, when found.
Steven Wittens
participants (3)
-
Rob Thorne -
Scott Reynolds -
Steven Wittens