Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HTML <select>: focus option based on user input?

I have an HTML select element:

<select id='poetslist'>
    <option value="shakespeare">William Shakespeare</option>
    <option value="milton">John Milton</option>
    <option value="keats">John Keats</option>
    <option value="wordsworth">William Wordsworth</option>
    <option value="larkin">Phillip Larkin</option>
</select>

In Chrome, when the page loads, the William Shakespeare option is selected. If the user starts typing 'Phil', the list focusses itself on Phillip Larkin. Familiar behaviour.

What I'd like to do (preferably using jQuery) is also allow the user to type the initials of the poet and have the relevant option come into focus.

So if you typed JK, then the John Keats option should come into focus. JM and John Milton, etc.

I don't even know how the HTML select element works, whether it's different in different browsers, etc - and it seems to be hard to find good documentation for this.

Can anyone figure out a smart way to do this in jQuery?

like image 786
AP257 Avatar asked Dec 28 '22 03:12

AP257


2 Answers

Here is a complete solution:

  1. Add attributes to each option, as @JMC suggests. However, I'd prepend the attribute name with "data-" to be in line with HTML5 standards. jQuery (as of v1.4.3) also supports retrieving attributes beginning with "data-" using .data().
  2. Bind to the keypress event. This is more correct than keyup for the following reasons:
    1. Semantically, keypress means user input has happened, while keyup means the physical key is lifted. For example, holding down a key will generated multiple keypress events (for each character that appears on screen), while only one keyup event. Keypress is also not prone to incorrectly receiving the order of keypresses when the user types "QW" quickly, but lifts the "W" key (a keyup) before the "Q" key.
    2. Keyup will be generated on non-character keys such as the arrows, backspace, etc..., while keypress will not.
  3. Use a timer to distinguish between two isolated key presses and a single sequence of key presses, e.g. did the user mean "W" for William Shakespeare and then "P" for Phillip Larkin, or just "WP" for ... Whatever Poet.

HTML

<select id="poetslist">
    <option value="shakespeare" data-initial="WS">William Shakespeare</option>
    <option value="milton" data-initial="JM">John Milton</option>
    <option value="keats" data-initial="JK">John Keats</option>
    <option value="wordsworth" data-initial="WW">William Wordsworth</option>
    <option value="larkin" data-initial="PL">Phillip Larkin</option>
</select>

Javascript

var timer = null, initials = "";

$("#poetslist").keypress(function (e) {
    initials += String.fromCharCode(e.which).toUpperCase();

    // Look for option with initials beginning with the typed chars
    $(this).find("option").filter(function () {
        return $(this).data("initial").toUpperCase().indexOf(initials) === 0;
    }).first().attr("selected", true);

    // Set/reset timer
    if (timer) {
        clearTimeout(timer);
        timer = null;
    }
    timer = setTimeout(function () {
        timer = null;
        initials = "";
    }, 2000); // Max 2 second pause allowed between key presses

    return false;
});
like image 101
David Tang Avatar answered Jan 11 '23 00:01

David Tang


With @Charlie's answer in mind, if you have access to build the html in the first place, it might be easiest to add an extra attribute to the option element, like

<option init="WW" value="wordsworth">William Wordsworth</option>
<option init="PL" value="larkin">Phillip Larkin</opt

If you can't do this on the server-end, jQuery could easily insert an extra attribute to an option based on it's value. Assuming, of course, that you know in advance each of the values you'll have in there.

After getting the extra attribute into the option, it would just be a matter of checking those values on keyup of the search box.

like image 43
JakeParis Avatar answered Jan 11 '23 00:01

JakeParis