Click here to Skip to main content
15,878,871 members
Articles / Web Development / HTML
Article

Auto select (Incremental search, Auto-complete) an item from a dropdown as user keys in

Rate me:
Please Sign up or sign in to vote.
4.35/5 (16 votes)
23 Sep 2008CPOL2 min read 104.8K   878   20   30
HTML lacks the auto-select feature for dropdowns. Users familiar with desktop applications expect browsers to select the correct item from a dropdown list as they key in. I am trying to solve this using simple JavaScript.

Sample screenshot

Introduction

Normally, HTML does not support nearest match. It always treats each key stroke as the starting of a new search. But, that is useless. If I type 'C', it will go to the first item that starts with C; if I type 'O' immediately, it will go to the first item that starts with 'O'. But in this implementation, it will go to 'CO'.

If the user misspelled, the user can use the backspace key to delete the char 'O' and type another letter to select another item. The user can wait for 3 seconds to start a fresh search, or use backspace to delete the entire search key, or shift delete to restart again.

It finds the nearest possible match. So, it does not need to be in any order.

  1. Just include the .js file in the target HTML:
  2. HTML
    <script language="JavaScript" src="dropdown.js"></script>
  3. Add these events to your dropdown field:
  4. HTML
    onfocus="this.enteredText='';" onkeydown="return handleKey();" 
      onkeyup="event.cancelbubble=true;return false;" onkeypress="return selectItem();"

    For example:

    HTML
    <select name="test" onfocus="this.enteredText='';" onkeydown="return handleKey();" 
      onkeyup="event.cancelbubble=true;return false;" onkeypress="return selectItem();">
    • onfocus resets the search text.
    • onkeydown handles certain keys (left, right, top, down, shift, delete, backspace) and takes the appropriate action.
    • onkeypress handles the selection of an item from the list.
    • onkeyup ignores the event as onkeypress has already handled the key stroke.
  5. Open the HTML file using IE.
  6. Type 'a', it will take you to the first item that starts with 'a'. Then, type 'b'; this will take you to the first item that starts with 'ab'. This uses a nearest match algorithm. So, the list does not need to be in any order.
    1. The user can search a string within a dropdown list.
    2. It automatically selects the list item that starts with the search key.
    3. The user can use backspace to delete a char before the current index from the search key.
    4. The user can use the delete button to delete a char after the current index from the search key.
    5. The user can use left or right arrow keys to move back and forth over the search key, and use delete or backspace to delete a char; the script will automatically find the item in the list, or enter a new char from the current index.
    6. Pressing the Shift and Delete keys will remove the search key and start over the search again.
    7. The user can see the search key on the Windows status bar. It shows the current index too.

I am adding Hugh Nelson's suggestion also here, so that it is available for every one. If you want to change all the dropdowns in a page to have this functionality, call the following in the onload event:

JavaScript
function setSelectEvents() {
    // set javascript event attributes
    // for all select items in the current page
    var selects = document.getElementsByTagName("select");
    var arrOnfocus = new Array(); // array of onfocus functions
    var arrOnkeydown = new Array(); // array of onkeydown functions
    var arrOnkeyup = new Array(); // array of onkeyup functions
    var arrOnkeypress = new Array(); // array of onkeypress functions

    for (var i = 0; i < selects.length; i++) {
        // we need to ensure that
        // we don't overwrite any existing function

        // save index to array as an element attribute
        // (using i directly did not work)
        selects[i].title = i;

        // onfocus
        if(typeof(selects[i].onfocus) == 'function') {
        // there is a pre-existing function
            // save pre-existing function
            arrOnfocus[selects[i].title] = selects[i].onfocus;
            selects[i].onfocus = 
              function() { arrOnfocus[this.title](); this.enteredText=''; }
              // set event to call our code plus the pre-existing function
        }
        else { // there is no pre-existing function
            selects[i].onfocus = function() { this.enteredText=''; }
        }

        // onkeydown
        if(typeof(selects[i].onkeydown) == 'function') {
        // there is a pre-existing function
            // save pre-existing function
            arrOnkeydown[selects[i].title] = selects[i].onkeydown;
            selects[i].onkeydown = 
              function() { arrOnkeydown[this.title](); return handleKey(); }
              // set event to call our code plus the pre-existing function
        }
        else { // there is no pre-existing function
            selects[i].onkeydown = function() { return handleKey(); }
        }

        // onkeyup
        if(typeof(selects[i].onkeyup) == 'function') {
        // there is a pre-existing function
            // save pre-existing function
            arrOnkeyup[selects[i].title] = selects[i].onkeyup;
            selects[i].onkeyup = 
              function() { arrOnkeyup[this.title](); 
                           event.cancelbubble=true;return false; }
              // set event to call our code plus the pre-existing function
        }
        else { // there is no pre-existing function
            selects[i].onkeyup = 
              function() { event.cancelbubble=true;return false; }
        }

        // onkeypress
        if(typeof(selects[i].onkeypress) == 'function') {
        // there is a pre-existing function
            // save pre-existing function
            arrOnkeypress[selects[i].title] = selects[i].onkeypress;
            selects[i].onkeypress = 
               function() { arrOnkeypress[this.title](); return selectItem(); }
               // set event to call our code plus the pre-existing function
        }
        else { // there is no pre-existing function
            selects[i]. &#246;nkeypress = function() { return selectItem(); }
        }
    }
}

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
United States United States
Fourteen years of progressive experience in Software Product Development, tactical planning, project and client management, demonstrated success in leadership, critical thinking, problem solving and analysis. Diverse knowledge and experience with multiple development methodologies, reengineering, software engineering, and integration of heterogeneous systems.

Comments and Discussions

 
Newsmodified version Pin
Member 35920213-Nov-08 4:09
Member 35920213-Nov-08 4:09 
GeneralOrder of Selection. Pls respond. [modified] Pin
Nav1120-May-08 3:19
Nav1120-May-08 3:19 
GeneralRe: Order of Selection. Pls respond. Pin
Member 35920213-Nov-08 21:28
Member 35920213-Nov-08 21:28 
Why don't you order dropdown list items at the time they are filled? Then everything should be ok...
GeneralRe: Order of Selection. Pls respond. Pin
rajapandian8114-Dec-09 3:51
rajapandian8114-Dec-09 3:51 
GeneralCommercial usage Pin
Emerson Takahashi20-Mar-08 6:20
Emerson Takahashi20-Mar-08 6:20 
GeneralJavaScript Pin
Vinug29-Nov-07 18:47
Vinug29-Nov-07 18:47 
GeneralChange all select items in a page Pin
hugh.nelson5-Sep-07 18:48
hugh.nelson5-Sep-07 18:48 
GeneralGreat simple solution Pin
hugh.nelson4-Sep-07 13:58
hugh.nelson4-Sep-07 13:58 
QuestionWhat are these? (Ele.lastEntered, ele.EnteredText ) Pin
ckwizard7719-Jul-07 5:50
ckwizard7719-Jul-07 5:50 
AnswerRe: What are these? (Ele.lastEntered, ele.EnteredText ) Pin
senthil karuppaiah6-Aug-07 6:18
senthil karuppaiah6-Aug-07 6:18 
Generalproblem on old machines Pin
zum12327-Jun-07 3:04
zum12327-Jun-07 3:04 
GeneralRe: problem on old machines Pin
senthil karuppaiah3-Jul-07 6:41
senthil karuppaiah3-Jul-07 6:41 
GeneralRe: problem on old machines Pin
Rafael Nicoletti24-Sep-08 6:25
Rafael Nicoletti24-Sep-08 6:25 
GeneralProblems with status in IE 7 Pin
mrortner10-Apr-07 6:38
mrortner10-Apr-07 6:38 
GeneralRe: Problems with status in IE 7 Pin
mrortner10-Apr-07 6:41
mrortner10-Apr-07 6:41 
GeneralBrowser Limitations Pin
TBBASEFLUG20-Nov-06 5:22
TBBASEFLUG20-Nov-06 5:22 
Generalproblem with too many options Pin
Pranav Kaushik18-Aug-06 2:53
Pranav Kaushik18-Aug-06 2:53 
GeneralRe: problem with too many options [modified] Pin
senthil karuppaiah18-Aug-06 19:03
senthil karuppaiah18-Aug-06 19:03 
GeneralRe: problem with too many options Pin
Pranav Kaushik18-Aug-06 22:22
Pranav Kaushik18-Aug-06 22:22 
GeneralRe: problem with too many options [modified] Pin
senthil karuppaiah19-Aug-06 4:34
senthil karuppaiah19-Aug-06 4:34 
GeneralTerm Pin
NormDroid6-Aug-06 21:34
professionalNormDroid6-Aug-06 21:34 
GeneralRe: Term Pin
senthil karuppaiah7-Aug-06 6:48
senthil karuppaiah7-Aug-06 6:48 
AnswerIncremental Search Pin
rlivelyppk8-Aug-06 12:26
rlivelyppk8-Aug-06 12:26 
GeneralRe: Incremental Search Pin
NormDroid8-Aug-06 20:42
professionalNormDroid8-Aug-06 20:42 
GeneralRe: Incremental Search Pin
senthil karuppaiah9-Aug-06 5:59
senthil karuppaiah9-Aug-06 5:59 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.