Javascript Combobox

Want to leave a question, comment, or some criticism? Click here!

1. Motivation

The default set of HTML controls do not include functionality like that of the WinForms combobox. For UI designers, this is usually resolved by having both a text box and a dropdown select box and allowing users to use one or the other. However, the big drawback of this approach is that it takes up what could be valuable real estate space and it's not necessarily the most elegant solution to the problem.

2. Objective

Using cross browser compatible DHTML, create a WinForms style combobox which allows users to enter values into a textbox or select values from a dropdown linked to the textbox. There are various possible solutions as to how to render the dropdown (including using a control replacement technique); I've chosen to use a floating unordered list (UL) simply because the structure for the UL is simpler in structure (less keystrokes!) and it allows for much more customization than a typical select, including the ability to create nested options!

3. Auxiliary Files/Prerequisites

To try this out for yourself, you will need the following:

4. What is It?

This is a custom WinForms style "combobox" which allows for entry of data by either typing in a value or selecting a value from a dropdown list. This is a very quick-and-dirty implementation done as a proof of concept for a client. Feel free to take some hints from this and build something better as this code is very specific.

The combobox, as implemented, has the following features:

5. Styling the List

Rather than covering the markup and script line-for-line, I've decided to just cover the most important part of the script, the styled, unordered list.

The advantages that this approach offers, as opposed to using a select dropdown, are:

We start with a typical unordered list. Since I love fruits (especially tropical fruits), we'll use a list of fruits.

Typical unordered list
  • Apple
  • Apricot
  • Avocado
  • Banana
  • Blueberry
  • Cactus Pear
  • Cantaloupe
  • Cherry
  • Dragon Fruit
  • Fig
  • Grape
  • Guava
  • Honeydew
  • Kiwi
  • Lemon
  • Mango
  • Nectarine
  • Orange
  • Papaya
  • Passion Fruit
  • Peach
  • Pear
  • Persimmon
  • Pineapple
  • Plum
  • Pomegranate
  • Raspberry
  • Star Fruit
  • Strawberry
  • Tangerine
  • Watermelon
Typical unordered list (HTML)
<ul class="value_list">
    <li>Apple</li>
    <li>Apricot</li>
    <li>Avocado</li>
    <li>Banana</li>
    <li>Blueberry</li>
    <li>Cactus Pear</li>
    <li>Cantaloupe</li>
    <li>Cherry</li>
    <li>Dragon Fruit</li>
    <li>Fig</li>
    <li>Grape</li>
    <li>Guava</li>
    <li>Honeydew</li>
    <li>Kiwi</li>
    <li>Lemon</li>
    <li>Mango</li>
    <li>Nectarine</li>
    <li>Orange</li>
    <li>Papaya</li>
    <li>Passion Fruit</li>
    <li>Peach</li>
    <li>Pear</li>
    <li>Persimmon</li>
    <li>Pineapple</li>
    <li>Plum</li>
    <li>Pomegranate</li>
    <li>Raspberry</li>
    <li>Star Fruit</li>
    <li>Strawberry</li>
    <li>Tangerine</li>
    <li>Watermelon</li>
</ul>

Notice that we've added the value_list CSS classname to the list. To make this work like a dropdown box, we'll obviously need to first clip the visible area of the UL. ULs, like DIV elements are block level elements and react similarly to the addition of overflow styles. We'll add the following CSS styles:

CSS style to clip the list
ul.value_list {
    overflow-y: scroll;
    list-style: none;
    width: 300px;
    height: 100px;
    border: 1px solid #333;
    background: #fff;
}

The result should look like:

Our minimally styled unordered list
  • Apple
  • Apricot
  • Avocado
  • Banana
  • Blueberry
  • Cactus Pear
  • Cantaloupe
  • Cherry
  • Dragon Fruit
  • Fig
  • Grape
  • Guava
  • Honeydew
  • Kiwi
  • Lemon
  • Mango
  • Nectarine
  • Orange
  • Papaya
  • Passion Fruit
  • Peach
  • Pear
  • Persimmon
  • Pineapple
  • Plum
  • Pomegranate
  • Raspberry
  • Star Fruit
  • Strawberry
  • Tangerine
  • Watermelon

Using only the above CSS, you should notice that there in FF, there is a large white gap between the text in the LI and the left border. In IE, there is a large gap between the left edge of the border on the unordered list and the border of the code container. To fix this, we add some remedial margins in the CSS:

CSS styles with adjusted margins
ul.value_list {
    overflow-y: scroll;
    list-style: none;
    width: 300px;
    height: 100px;
    border: 1px solid #333;
    background: #fff;
    margin-left: 0px; /* does not affect FF, IE only */
}

ul.value_list li {
    margin-left: -40px; /* adjustment for FF */
}

* html ul.value_list li {
    margin-left: 0px; /* re-adjust for IE */
}
Our minimally styled unordered list with adjusted margins
  • Apple
  • Apricot
  • Avocado
  • Banana
  • Blueberry
  • Cactus Pear
  • Cantaloupe
  • Cherry
  • Dragon Fruit
  • Fig
  • Grape
  • Guava
  • Honeydew
  • Kiwi
  • Lemon
  • Mango
  • Nectarine
  • Orange
  • Papaya
  • Passion Fruit
  • Peach
  • Pear
  • Persimmon
  • Pineapple
  • Plum
  • Pomegranate
  • Raspberry
  • Star Fruit
  • Strawberry
  • Tangerine
  • Watermelon

While the result looks like a typical multiline select, it is indeed an unordered list which allows us to create a highly customized look and feel (when compared to using select and option elements.

The rest of the script isn't that interesting to be honest :) It's all fairly easy plumbing to handle events and there's that little binary search bit, but it's a very generic implementation of binary search.

6. Wrap Up

In this workshop, we covered general techniques for formatting lists for some unique use cases and also demonstrated how we can create a custom combobox like control using DHTML. This script can be generalized and further improved to allow dynamically hooking up the text boxes to corresponding lists and even to an AJAX framework to dynamically draw results.

7. Resources

Additional resources for further exploration: