A better select one or many

April 7, 2008

“Better” is an exaggeration. It may be that occasionally it is more appropriate.

At issue is presenting a control to the user where she can select one of many, or several of many. When the selection is fairly small (arbitrary at 7 items) – radio and checkbox groups are standard. But when the choice number goes over a certain number, there are various mechanisms to be seen, of which the most common are single select <select /> and multiple select <select /> – the problem is how to fit large number of choices into a cramped area.

This came up in the context of the Sakai Course Evaluation tool, where any number of question types need to be constructed and presented to the user. One of these questions, used in a Cambridge course evaluation, involved a really long list of choices.

Occasionally you might want a control that is a bit friendlier and stylable than a <select />. A colleague alerted me to: http://c82.net/posts.php?id=25

Here is an example from C82:

Nice! The clickable area indicated by the dark green hover is created by the <label /> element, wrapping the <input /> and the text and set to display:block. The height and width of the top container (a <ul />) are fixed and the overflow:auto for the scroll.

There are three possible improvements to the excellent widget.

  1. Having the overflow and height attributes set only if the height goes over a certain number (template or system set) – so scrollbars appear after a certain height, and groups of less than that height size automatically.
  2. Having the “checked” attribute of the input reflected in the style of the parent label
  3. Having a message display of the “you have made x selections” or something like that.

Setting the scroll and height dynamically

The markup looks like this:

<ol class="multchoiceholder">
<li>
<label for="1">
<input value="1" name="1" id="1" type="checkbox">
</label>
</li>
<li>
<label for="2">
<input value="2" name="2" id="2" type="checkbox">
</label>
</li>
(etc)
</ol>

And the CSS is pretty much what the C82 article above is using, except no height is set for the container, allowing it to grow to fit the contents. To get the “intelligence” about the height I added jquery.js to the <head />

<script src="jquery.js" language="JavaScript" type="text/javascript">

And the following at the end of the document:

<script type="text/javascript">
$(".multchoiceholder").each(function(){
if ($(this).height() > 180) {
// if ($(this).children("li").size()  >  9) {
$(this).addClass("oversize")
}
})
</script>

This essentially adds the “oversize” class to the parent container if the parent container contents go over 180 pixels in height. This class, below, sets the height and the overflow that we need. I played around with counting the <li /> child nodes (commented above), but since a given list item could span multiple lines the pixel height seemed best.

ol.oversize{
border: 1px solid #ccc !important;
height: 12em !important;
overflow: auto !important
}
Advertisements