Ashley Sheridan​.co.uk

Combo Boxes

Posted on

Web pages have always been lagging behind when it comes to form controls that exist on most applications you find on a computer. It just about covers the basics and goes no further, leaving web developers without such useful things as spinners, sliders, tabs and combo boxes. There are scripts to emulate combo boxes online, but the ones I tested failed abysmally when script was turned off, so I set about creating a combo box that can offer a simple text box instead.

I've separated the code out into three files, as it makes it easier to work on, and share across various pages. To be useful, I've created a couple of compressed archives (pick your flavour) that contains all three files:

I won't show the whole HTML page here, as it is in the archive files. The important parts begin in the form:

<form name="comboboxtest"> <div class="combo"> <input type="text" name="colour" class="combo" onclick="showList('droplist')"/> <script language="javascript" type="text/javascript"> comboitems = Array('red','green','blue','yellow'); document.write('<input type="button" value="&#9662;" onclick="showList(\'droplist\')"/>'); document.write('<ul id="droplist">'); for(i=0; i<comboitems.length; i++) { document.write('<li class="item" onclick="setItem(\'comboboxtest\',\'colour\',\'droplist\',this);">'); document.write(comboitems[i]); document.write('</li>'); } document.write('</ul>'); </script> </div> </form>

The parts marked in red on lines 1 and 9 are the form name and the dropdown id respectively. These will change from form to form, and combo box to combo box as fits your requirements. The other two parts marked red are the CSS class definitions. Using the same definition for two different tags is perfectly valid, and can be preferred if you want a lot of HTML tags to share common attributes where they might not otherwise inherit them.

Line 6 sets up an array in JavaScript that is used to populate the dropdown once it is displayed. which is done in the loop at line 10. You can put this loop in a function if you want to be more generic, and pass the item list as an argument for it, but for this example I've kept it simple.

Line 12 shows each list item, and gives it the action to perform when an onclick event has been captured. The function it calls resides in the external combo.js file (in the archive). It passes as arguments the name of the form, the name of the input element holding the value, the id of the dropdown and the this object. this is basically a reference to itself, which is used in the setItem() function to obtain the actual value clicked on.

function setItem(formname, inputname, listname, item) { document.forms[formname].elements[inputname].value = item.innerHTML; list = document.getElementById(listname); list.style.display = 'none'; } function showList(listname) { list = document.getElementById(listname); if(list.style.display == 'block') { list.style.display = 'none'; } else { list.style.display = 'block'; } }

The first function is fairly simple. It just sets the value of the input element to the innerHTML value of the object that was clicked on. It then hides the dropdown. The second function hides and displays the dropdown, based on what the current state is.

Lastly, the CSS file tidies things up a bit:

div.combo { width: 220px; position: relative; } input.combo { width: 180px; } ul#droplist { position: absolute; top: 23px; left: 0px; display: none; padding: 0px; margin: 0px; background-color: #f0f0f0; border: 1px solid #999999; } li.item { display: block; cursor: default; width: 180px; } li.item:hover { background-color: highlight; }

Line 4 gives the containing div a relative position. This is so that the dropdown itself can be positioned absolutely, letting things flow around it without the whole div needing to take up more space.

The list that contains the dropdown items is given a 0 pixel padding and margin, and the display type is set to none. This is so that it doesn't show in the browser as an actual list, but starts out hidden.

The last style is a CSS selector which sets up a hover style on each item. This works on all good browsers, but fails on IE (surprise there!) If it's important to get it working for that browser, then you can use a mouseover and mouseout to set the style with JavaScript.