Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / HTML

Auto-suggest Control

4.90/5 (124 votes)
10 Oct 2009Zlib12 min read 1   2.6K  
This article presents code that augments any INPUT box with an auto-suggest feature, AJAX-capable
Autosuggest in action

Foreword

Thanks to those of you who take the time to read through this article. If you feel like dropping off a vote (and particularly if it's a low one), please include a comment that mentions what the problem was. Feedback is what drives improvement.

Introduction

The Auto-complete control article by zichun has gained much publicity in the last several years. The "Auto-complete" feature (also known as "auto-suggest," named after Google Suggest) greatly increases site usability and enriches user experience. Unfortunately, the original author has given up code support and didn't answer my e-mails. Furthermore, requirements for auto-complete controls have risen in the last few years.

In order to address all script issues and to provide ongoing user support, the auto-suggest control was born. What was changed and fixed:

  • Script now supports both offline (via client-side array) and online (via AJAX) way of populating the suggestion list
  • Script is now 100% compatible with all major browsers (Mozilla/Firefox, Opera, Safari, Chrome, Microsoft Internet Explorer)
  • Script was moved to a single file
  • All styling info was moved to CSS
  • Memory leaks were found and fixed
  • Many useful options added

Setup

At first, you should upload autosuggest.js, autosuggest.css, arrow-down.gif, arrow-down-d.gif, arrow-up.gif and arrow-up-d.gif to your server. Next, assume that we have a simple page with a single input field:

HTML
<html>
    <body>
        <input type="text"
            id="tb" value=""
            style="font-family:verdana;width:300px;font-size:12px" />

    </body>
</html>
  • The first thing you should do is add references to autocomplete.js and autocomplete.css files:
    HTML
    <html>
        <head>
    
            <link rel="stylesheet" type="text/css" href="autosuggest.css"></link>
            <script type="text/javascript" src="autosuggest.js"></script>
    
        </head>
    
     ...
  • Next, initialize the auto-suggest control with the id of the bound INPUT element:
    JavaScript
    <input type="text" id="tb" value=""
    
        style="font-family:verdana;width:300px;font-size:12px" />
    
       <script> new autosuggest("tb"); </script>
  • If you wish to use a static client-side array:

    1. Create it in the head of the page:
      JavaScript
      <head>
          <script type="text/javascript" src="autosuggest.js"></script>
      
          <script>
              var customarray =
                           ["apple", "alligator", "banana", "elephant",
                            "pear", "kingbird", "kingbolt", "kingcraft",
                            "kingcup', "kingdom", "kingfisher"];
          </script>
      
      </head>
    2. Pass it as a second parameter to the autosuggest object:
      JavaScript
      <script>
          var obj = new autosuggest("tb", customarray);
      
      </script>
    3. Make sure that the autosuggest_url variable at the very beginning of autosuggest.js is empty ("").
    4. You can change the bound static array at any time with the help of bindArray method:

      JavaScript
      var customarray2 = [ ... ];
      
      ...
      
      obj.bindArray(customarray2);
      

      This is particularly helpful if you want to create linked autosuggest controls.

    Note: To use all advantages of caching, consider moving custom_array to either autosuggest.js or any other external JavaScript file.

  • If you wish to retrieve suggestions through AJAX:

    1. Pass the URL of the server-side script (that will be used to retrieve the suggestion list) as a third parameter to the autosuggest object:
      JavaScript
      <script>
          var obj = new autosuggest("tb", "", "http://mysite.org/suggest.asp?");
      </script>

      Note: Be sure to append the ? symbol at the end of webservice's URL.

    2. Optionally, you can set the global autosuggest_url variable (inside autocomplete.js) to the path of the server-side script; then you can avoid the third parameter of autosuggest (this may be useful when you use several autosuggest controls on a page). However, if you do specify that third parameter, it overrides the global autosuggest_url.

      Note: Script awaits the returned data to be the following XML:

      XML
      <?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
      	<listdata>item1|item2|...</listdata>

      (i.e. a set of strings, delimited by a vertical bar character, inside a single listdata tag.)

      Note: The delimiting | (vertical bar) is the default one; ajax_delimiter variable controls this.

    3. Similarly to static array, you can re-bind the webservice URL at any time with the help of bindURL method:
      JavaScript
      obj.bindURL("http://mysite.com/suggest?");
      

Options

  • When testing the script locally, the Mozilla/Firefox browser will not allow you to make AJAX queries due to security limitations. Circumvent this by uncommenting the following inside autosuggest.js:

    JavaScript
    // try { netscape.security.PrivilegeManager.enablePrivilege 
    // 	("UniversalBrowserRead"); } catch (e) { }
  • If you wish to use up/down arrows instead of a scrollbar in this control, you can change the use_scroll variable to false.

  • By default, the script populates the suggestion list with all items that start with a string that the user typed. If you wish to change it, thus having all variants that contain the typed string, set the limit_start variable to false. Otherwise, it is recommended to keep it true.

  • If you choose limit_start variable to be false, you have one more option to look at: match_first. It controls the order of the suggestions' appearance. Set to true, it first shows all the items that start with a string that the user typed, then all other items that contain the typed string; set to false it shows all items in the order that they appear in an internal array, regardless of part matching.

  • If you have several input/combo boxes on a page, and encounter a situation when a suggestion list is rendered behind one of the other controls, you should change the use_IFrame variable to true. Otherwise, it is recommended to keep it false.

  • By default, the suggestion list is not displayed until a special timeout - response_time - elapses; this is done to improve usability (and save a bit of traffic for AJAX users). You can change it to fit your needs.

  • By default, no item is selected when the suggestion list first opens. This can be controlled by changing the no_default variable of autosuggest object to false.

  • Currently, the script loads suggestion variants only once - when the user enters the first character; then the actual filtering occurs. If you wish to set up a more sophisticated filtering technique, consider changing the full_refresh option that instructs the script to make an AJAX call on every key pressed.

  • If you wish to use the autosuggest object as an ordinary select element, you can look at the selectedIndex property that contains the index (zero-based) of the selected suggestion.

  • You may want to restrict the typing and selection to the predefined set of values. In this case, use the restrict_typing option (works with client-side array only); it won't allow a user to type the value that isn't in the key array. Please take a note that this option doesn't safeguard the text field from accepting the "wrong" value (by pasting it from the clipboard, for example) - so server-side checks are always a good thing.

  • One more thing you can do is to turn this auto-suggest control into an AJAX-powered select is to use the key/value pairs instead of an ordinary strings; together with a selectedIndex, this can be used to retrieve item's value. The case for a client-side array is:

    JavaScript
    <head>
        <script type="text/javascript" src="autosuggest.js"></script>
    
        <script>
            var customarray =
               [['apple', 1], ['alligator', 2], ['banana', 3],
                ['elephant', 4], ['pear', 5], ['kingbird', 6],
                ['kingbolt', 7], ['kingcraft', 8],
                ['kingcup', 9], ['kingdom', 10], ['kingfisher', 11]];
        </script>
    
    </head>

    And the AJAX string must be:

    XML
    <listdata>key1,value1|key2,value2|...</listdata>

    Note: Delimiting character (comma by default), that separates the key and the value, can be controlled with item_delimiter property.

  • autosuggest constructor function can also accept the 4th parameter - reference to a function, that is called when user selects a suggestion:

    JavaScript
    new autosuggest("tb", customarray, null, function(index, control)
    {
        alert("You've selected the key: " + control.keywords[index]);
    });

    Function is given two parameters: the index of a selected item (in the keywords array) and the reference to a control object that called this callback function.

The End?

No, of course. Feel free to post your questions in the forum below, e-mail me if you have questions, and please vote for this article. :) I'll try to answer all requests and provide user support.

Enjoy!

History

  • August 22nd, 2007 - version 1.0
    • Initial release
  • August 30th, 2007 - version 1.1
    • actb objects are now independent of each other
    • Scrolling with mouse made possible
    • ESC key now closes the suggestion list
    • Arrow images now play better with browser caching
    • Fixed problem with TAB key switching focus too early
    • Fixed problems with INPUT box losing focus (and making auto-suggest control dysfunctional) in some cases
  • September 10th, 2007 - version 1.2
    • Added the ability to use a standard scrollbar instead of up/down "buttons" (actb_useScroll, on by default) - contributed by LTSpeed
    • Added a workaround for the Microsoft Internet Explorer bug, when suggestion list was rendered behind page controls (actb_useIFrame, off by default) - contributed by Jac Steyn
    • 2 of 4 icons saved with better compression - contributed by Jac Steyn
    • Other minor corrections and fixes
    • Corrected some misleading statements in the article
  • September 20th, 2007 - version 1.3
    • Fixed faulty actb_useIFrame option, now it works OK
    • Fixed another problem with actb_useIFrame option, when the user couldn't select a suggestion with a mouse click
    • Added the ability to specify a server-side URL for each actb object
    • Added the ability to avoid initial selection of the first suggestion variant (actb_noDefault, on by default)
    • Added the ability to reload a list of suggestions on every key pressed (actb_fullRefresh, off by default)
    • Added the actb_selectedIndex property, containing the index (zero-based) of the variant last selected
    • Various minor fixes and improvements
  • October 10th, 2007 - version 1.4
    • Added actb_response option
    • Added actb_firstMatch option
    • Added the ability to use key/value pairs (getting close to an AJAX-powered SELECT)
    • Added the ability to use the down arrow key to retrieve the suggestion list (for non-empty INPUT box)
    • Suggestion list is now redrawn only if the user actually changes the text in an INPUT box
    • Fixed the bug when actb_selectedIndex wasn't properly assigned when using keyboard to navigate through the suggestion list
    • Other minor bugfixes
  • January 10th, 2008 - version 1.5
    • (Hopefully) solved all problems with suggestion box appearing under the HTML controls ("IFRAME mode")
    • Construction of the suggestion box is now significantly faster than before (2x faster for Microsoft Internet Explorer, more than 8x for Firefox)
    • Pressing "down arrow" key will now bring all the available suggestions (doesn't work in AJAX mode)
    • PageUp and PageDown keys now can be used to scroll the suggestions
    • Width of the suggestion box now increases if any suggestion is wider than the suggestion box
    • Long suggestions with hyphens do not span multiple lines but increase the width of the suggestion box
    • Fixed annoying issue with "'actb_display' is null or not an object" error
    • Minor bugfixes
  • December 16th, 2008 - version 1.6
    • Fixed a bug with incorrect positioning of suggestion list in a scrolling document
    • Fixed a Firefox-related issue with lengthy AJAX responses
    • actb_selectedIndex now always has the correct value
    • Building of suggestion list with many (hundreds of) suggestions is now much faster
    • You can now easily tune the autosuggest control to use your webservice's output by using ajax_delimiter and item_delimiter variables.
    • You can now control the color of current selection's text with actb_htextColor
  • January 30th, 2009 - version 1.7
    • Fixed an issue when suggestion list disappeared after user clicked on the scroll bar in Microsoft Internet Explorer and Webkit-based browsers (when using actb_useScroll)
    • Fixed a minor issue with non-canon scrolling behavior when scrolling down (when using actb_useScroll)
    • Fixed a minor display issue when suggestion list was a bit wider than parent input field
    • Introduced the actb_restrict option, that allows you to restrict typing to the keys of client-side array
    • Added more comments to the code
  • February 2nd, 2009 - version 1.7
    • Fixed an issue (introduced in the previous release) that didn't allow focusing other input fields while suggestion box was open (Internet Explorer- and Webkit- related)
  • February 8nd, 2009 - version 1.8
    • Fixed an issue when, in a scrolling document, suggestion list disappeared after user clicked on the scroll bar in Microsoft Internet Explorer and Webkit-based browsers
      (this is an additional patch to an earlier fix)
    • All global variables (except suggesturl) and functions were moved into the actb object (either as member methods or inner functions), so script now won't interfere with the global namespace
    • Script was tuned to produce XHTML-compatible output
  • April 10th, 2009 - version 1.9
    • In scroll mode, suggestion list now appears almost instantly, no matter how long the suggestion list is (+ many performance optimizations)
    • Returned the lost (since adoption of zichun's code) ability to retrieve suggestions for the keyword in-between the other keywords
    • Fixed an issue with item_delimiter not being used correctly in the code
    • Fixed an issue with actb_noDefault option not being respected after input field value changes
    • actb_selectedItem now contains the index of selected item in the original suggestion list, not in the filtered list
    • actb constructor can now accept the 4th parameter - onSelect - reference to a callback function that fires every time user selects a suggestion
  • April 16th, 2009 - version 2.0
    *** Incompatible with previous releases ***
    • Name of main object changed - actb changed to autosuggest - and all member variables, methods and generated ids were given human-readable names
    • Variables in the code now use underscore_notation (with the exception of selectedIndex), while methods now use lowerCamelCase notation
    • After many optimizations and code size reductions, script is now ~12% smaller than the previous version
    • You can now use PageUp and PageDown keys to navigate through suggestions in arrow-mode
    • Script now doesn't generate any CSS warnings (as seen by Firefox's error console)
    • 2 of 4 GIF images were optimized (the other two were compressed already)
    • Fixed some issues with autosuggest box in arrow-mode
  • April 20th, 2009 - version 2.1 (contributed by Marco Vervoort)
    • Fixed a Firefox-only issue when restrict_typing was set to true and any suggestion containing the upper-case symbol became unavailable
    • Fixed a bug with all suggestions appearing as selected when no_default was set to false
    • Fixed a bug in insertWord method that appeared when no delimiters were defined
    • Fixed a minor issue with getCaretEnd method generating a warning in Firefox
    • onSelect callback now receives the second parameter - reference to the caller autosuggest object
  • August 4th, 2009 - version 2.2
    • Fixed an issue with incorrect sorting of results, caching the results of previous search in some cases
    • Fixed an Internet Explorer-only issue when you couldn't use the onblur attribute on the target input field (it got re-written by script)
    • Fixed a bug when scrolling to the end of a long list that is still in the process of loading could cause rendering issues and render the suggestion list disfunctional
    • Fixed incorrect behavior of restrict_typing option when there are multiple delimited terms in the input field (collaboration with Marco Vervoort)
    • Fixed a bug when, after typing the keyword that doesn't have a matching suggestion, suggestion list stayed visible with the latest legit suggestion(s)
    • You can now dynamically bind the array and/or the URL for the AJAX webservice with bindArray and bindURL methods
    • After the browser window is resized, suggestion list will now correctly reposition itself under the parent input field
    • Behavior with Home/End/PageUp/PageDown keys is now more consistent across browsers
    • Version number is now written in autosuggest.js
  • August 18th, 2009 - version 2.3
    • Fixed a bug that rendered AJAX support disfunctional
    • Fixed a bug that caused the use_iframe option disfunctional
  • October 10th, 2009 - version 2.4
    *** Incompatible with previous releases ***
    • All styling info moved to CSS (autosuggest.css)
    • Fixed a bug with incorrect functioning of scrollbars when using autosuggest controls in lengthy XHTML documents
    • Sample page was corrected to validate as XHTML 1.0 Strict

License

This article, along with any associated source code and files, is licensed under The zlib/libpng License