Forum Moderators: open

Message Too Old, No Replies

Moving through a list with multiple character inputs

Event Handling

         

BlobFisk

5:06 pm on Oct 16, 2003 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Has anyone had any experience with trying to control drop down lists? Specifically, I would like user to be able to type multiple characters which match together rather than re-matching on every character as you enter them.

For example, if a list of usernames contains:
Ernie
Federico
Fred

The default behaviour on entering "f" and then "e" shows "Ernie" (as "e" was entered last). What I would like to achieve is that "f" and "e" shows "Federico".

I'd appreciate all input and will post the final code here when it's done...

mikejson

7:19 pm on Oct 16, 2003 (gmt 0)

10+ Year Member



I thought about this before. One interesting idea that came through my brain was, have an input field for them to enter text into, and have another drop down to show what is the matching text(kinda like what a word processor will do in a thesaurus thing).

I never put anymore thought into it hehe.

DrDoc

8:03 pm on Oct 16, 2003 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Yes, I have done that successfully a couple times. I'll have to dig for the code though...

BlobFisk

8:57 am on Oct 17, 2003 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



DrDoc, I'd be very interested in seeing you code if you're willing to share?

mikejson, I actually have done this, have an input box that allows you to search the list... however, I am looking to take this further and remove the input box!

DrDoc

3:43 pm on Oct 17, 2003 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Well, I couldn't find the code, so I re-wrote it as best I could. I haven't tested this code thoroughly in all browsers, so if you find any issues - let me know.

<html>
<head>
<script type="text/javascript">
function listSearch(which) {
fontSearch = which.field.value;
if(event.keyCode==40) {
//Pressed down key
selNow = which.list.selectedIndex;
selMax = which.list.length - 1;
if(selNow!=0 && fontSearch!=which.list.options[selNow].value) {
which.field.value = which.list.options[which.list.selectedIndex].value;
which.field.focus();
which.field.select();
}
else {
which.list.selectedIndex = (selNow==selMax?selMax:selNow+1);
which.field.value = which.list.options[which.list.selectedIndex].value;
which.field.focus();
which.field.select();
}
}
else if(event.keyCode==38) {
//Pressed up key
selNow = which.list.selectedIndex;
if(selNow!=0 && fontSearch!=which.list.options[selNow].value) {
which.field.value = which.list.options[which.list.selectedIndex].value;
which.field.focus();
which.field.select();
}
else {
which.list.selectedIndex = (selNow<2?1:selNow-1);
which.field.value = which.list.options[which.list.selectedIndex].value;
which.field.focus();
which.field.select();
}
}
else if(fontSearch!="") {
regexp = new RegExp("^" + fontSearch, "i");
found = 0;
for(i=1; i<which.list.length; i++) {
listFont = which.list.options[i].value;
if(listFont.match(regexp)) {
found = i;
i = which.list.length;
}
}
which.list.selectedIndex = found;
}
}
</script>
</head>

<body>
<form name="foobar">
<input type="text" name="field" size="25" onkeypress="if(event.keyCode==8) { listSearch(this.form); }" onkeyup="listSearch(this.form)"><br>
<select name="list" size="1">
<option value="">Select font</option>
<option value="Algerian">Algerian</option>
<option value="Arial">Arial</option>
<option value="Arial Black">Arial Black</option>
<option value="Arial Narrow">Arial Narrow</option>
<option value="Courier">Courier</option>
<option value="Times New Roman">Times New Roman</option>
<option value="Trebuchet MS">Trebuchet MS</option>
<option value="Verdana">Verdana</option>
</select>
</form>

</body>
</html>

  • While you type, the dropdown list will select the matching font
  • Pressing the up/down key allows you to select the font in the dropdown list (you have typed "ar" and "Arial" is showing. Pressing up/down will put "Arial" in the input field)
  • Pressing up/down lets you navigate up or down the list of fonts. You will not be able to navigate past either end of the list.
  • DrDoc

    3:56 pm on Oct 17, 2003 (gmt 0)

    WebmasterWorld Senior Member 10+ Year Member



    As a side note... It would be possible to do this without the separate text field, but this might confuse users. What if they press "f" when they meant to press "e" in the first place? So, they try to correct by pressing "e"... The normal behavior for a dropdown list is to skip to "e". You don't want to break that ;)

    BlobFisk

    1:07 pm on Oct 20, 2003 (gmt 0)

    WebmasterWorld Senior Member 10+ Year Member



    Thanks a million for that DrDoc.... funny, I was half way down the route of some nasty OO JS to try and do this!

    I agree that superceeding the default behaviour is not a good thing, but this is an internal application and I'll do some user testing to see how people react.

    Thanks again!

    BlobFisk

    11:18 am on Oct 21, 2003 (gmt 0)

    WebmasterWorld Senior Member 10+ Year Member



    Thanks to DrDoc for putting me on track with this, as I said, my first idea was to use Object Oriented JS to do this (using parent and child node event handlers... not pretty!).

    The script below does exactly what I was looking for:


    <script type="text/javascript">

    var selectedOption = 0;
    var KeyPressEnabled = true;

    function SelectChange() {
    if (KeyPressEnabled) {
    main.Drop1.selectedIndex = selectedOption;
    }
    }

    function KeyPress()
    {

    KeyPressEnabled = true;

    var Drop1 = main.Drop1;

    // Keycode 38 and 40 are the up and down arrow
    // buttons,in case the user uses the arrow keys to select
    // items. We reset the value of what they have typed and
    //change the global selected item value.


    if (event.keyCode == 38) {
    main.Typed.value = "";
    selectedOption = Drop1.selectedIndex - 1;
    return;
    }

    if (event.keyCode == 40) {
    main.Typed.value = "";
    selectedOption = Drop1.selectedIndex + 1;
    return;
    }

    // Keycode 27 is escape, so the user can clear out
    // what they have typed so far


    if (event.keyCode == 27)
    {
    Drop1.selectedIndex = 0;
    main.Typed.value = "";
    return;
    }

    // Keycode 32 is a space

    if (event.keyCode!= 32) {
    // Only process the key if it's a letter or number
    if (event.keyCode < 65 ¦¦ event.keyCode > 90)
    return;
    }

    // Convert the ASCII keycode value to a character and
    // add the key entered to a "buffer" - a hidden field
    // called "Typed".


    main.Typed.value += String.fromCharCode(event.keyCode).toLowerCase();

    // Loop through the select list to find any matches
    for (x = 0; x < main.Drop1.length; x++)
    {
    var OptionText = Drop1.options[x].text;
    var tmpOptionText = "";

    // Loop through the value of each select item, and if
    // there is a match on what they have typed in, set the
    // global variable for that value.
    // The browser will run the onChange event since you
    // yped a key. We'll run SelectChange() in the
    // onChangeEvent just to be sure.

    for (y = 0; y < OptionText.length; y ++)
    {
    tmpOptionText += OptionText.charAt(y).toLowerCase();

    if (tmpOptionText == main.Typed.value) {
    Drop1.selectedIndex = x;
    selectedOption = x;
    return;
    }
    }
    }
    }
    </script>


    <form name="main">
    <select name="Drop1" onKeyDown="KeyPress();" onMouseDown="KeyPressEnabled = false;" onChange="SelectChange();">
    ...
    </select>
    <input type="hidden" name="Typed" value="">
    </form>

    <script type="text/javascript">
    main.Typed.value = ""; // Clear out our "buffer"
    </script>

    HTH