A select box always
stays on top of any div placed above it, even if the div has
a greater z-index athough any other form element will behave
correctly.
Example 1
above you'll find the most common form elements
Reason
The reason this happens is simple. Any HTML element can be
categorized as windowed or windowless. All windowless controls
will follow the z-index structure set in place for them. While
windowed controls will still follow a z-index. They follow
their own order of things. A windowless control will never
overlap a windowed control because it's z-index is not comparable
to that of a windowed control.
So the question is why did Microsoft make the select box
windowed. Is there a valid reason?
I've taken a good hard look and there is no obvious reason
why the select box was made windowed. DHTML might not have
been around when select elements were first introduced. Microsoft
is quick enough to state the problem, but have yet to offer
us a valuable solution. Interestingly enough, in VB when you
create custom controls you get an option to create the control
as windowed or windowless. Both will function equally as well
in a web environment.
BIG YELLOW DIV
The solution - you've been waiting for
Lets re-create example 1 except this time the select box
will be correctly obscured by the div.
Example 2
above you'll find the most common form elements
WOW, ITS GONE, ONCE AND FOR ALL!
THE VERDICT
If something about that select box looks different it is
because it is not a select element at all. Thankfully it's
not a custom control that I created either. This control requires
no download of any kind. Even better, this control is part
of the windows operating system. It is the same control you
use day after day in your windows applications.
Its called the Microsoft Forms combo box control. Mostly
used in visual basic applications, it works on the web just
fine and everyone running windows is compatable.
Just the facts - let's get back to the look of this control.
Lets begin by illustrating the customizability of this control.(
looks only for now)
A very big one
A very small one
A 3d control Coloring is also possible.
There are a lot of combinations regarding the look of this
control. You can change its colors, borders, font, border
color, mouse cursor; just about everything imaginable. It
also supports CSS. That's right, you can attach inline style
attributes to this control.
Special effects - might be useful to your design.
This control may very well add an original feel to your
site. - take a look at the examples below
This one has no button.(This is not a text
element)
This ones button becomes visible when you
click the control.
This ones button does not have an arrow.
Three Dots.
Two Dots
Later you can play around with all the many combinations
of looks for this control.
Just the facts - how it works and how to implement it.
The code for the control is listed below - don't worry about
how you'll populate the control at this stage or how you'll
post, etc. as all will be explained in good time. This code
below may look like a lot but I can assure you you'll get
used to it and the benefits are great. Just replace your <select>
tag with this code
Style equivelant to background color='color'
- note : this color is in decimal notation not hex (being
a range from 000000 - FFFFFF) use calc.exe to convert
from hex to dec.
<param name="ForeColor" value="2147483656">
Foreground color of text
<param name="MaxLength" value="0">
Like maxlength in a text box / applicatable
only when you set the display style property to accept
user input - see below
<param name="BorderStyle" value="2">
2d / 3d / more border options
<param name="ScrollBars" value="0">
You'll notice the lists have scroll
bars - you can turn them on / off here - both vertical
and horizontal are supported
<param name="DisplayStyle" value="7">
VERY IMPORTANT - Use this setting to turn
user input off. When this is set to 7 , It behaves like
a select box. Remember it is after all a combo( combination
between a text and list box) box
<param name="MousePointer" value="1">
Like style="cursor:cursor" - a numeric
value expected
<param name="Size" value="2540;635">
<param name="PasswordChar" value="0">
<param name="ListWidth" value="4000">
Unlike select elements - this control
has a width you can set for your list items that drop
down. Handy when displaying very short or very long list
items.
<param name="BoundColumn" value="1">
<param name="TextColumn" value="65535">
<param name="ColumnCount" value="1">
<param name="ListRows" value="8">
Perhaps the number of list rows available
before scrolling occurs - plausable guess?
<param name="cColumnInfo" value="0">
<param name="MatchEntry" value="1">
<param name="ListStyle" value="1">
This is a nice feature add list
rings similar to having a <li> command in every list
item . You can play and configure for all the options.
<param name="ShowDropButtonWhen" value="2">
The button on the side need not be
visible all the time - you can customize it here
<param name="ShowListWhen" value="1">
Show / hide the list when you decide
- play around a bit might make more sense
<param name="DropButtonStyle" value="1">
You can make the button plain / dots
/ arrow using this feature
<param name="MultiSelect" value="0">
Select more than one option at a
time.
<param name="Value" value>
<param name="Caption" value>
<param name="PicturePosition" value="458753">
<param name="BorderColor" value>
Adjust the color of the border here
<param name="SpecialEffect" value="3">
I'll let you discover this one -
it changes the way you interact / view the control
<param name="Accelerator" value="2">
<param name="GroupName" value>
<param name="FontName" value="Arial">
<param name="FontEffects" value="1073741824">
<param name="FontHeight" value="150">
<param name="FontOffset" value="0">
<param name="FontCharSet" value="0">
<param name="FontPitchAndFamily" value="2">
<param name="ParagraphAlign" value="1">
<param name="FontWeight" value="200">
</object>
I would also like to add at this point that a great deal
of these params are optional and once you find the configuration
that suits you, you can disregard a lot of these tags.
Naming the control
With a select box you need not specify the id, however with
the combo box control it is nessessary to specify both the
name and the id of the control. The reason for ths is that
you will need to referrence the control by id when assigning
events to it.
Populating the control using VBScript (JavaScript will
work just as well).
So how do we populate the control? You need to create a short
script to populate the combo.
Here are a few population examples assuming a combo box object
is placed within the form tags of a form named 'form1' and
the combo has a name of 'combo' and an id of 'combo':
' asp population example from a
recordset
<script type="text/vbscript">
<% while not rs.eof %>
form1.combo.additem("<%= rs("name") %>")
<%
rs.movenext
wend
%>
<script>
The scripts are always placed after the object.
A script error will occur if it tries to reference your control
before it is created
Most of you more advanced users must have some questions
at this stage. The two that I know you must be thinking are
How do you select an item? - equivalent to <option
value="" selected >
What happened to the values that are submitted in place
of the friendly name? eg <option value="1">Userid
Lets start with the first question. Obviously both these
questions have valid answers or else I would not consider
using the forms control. It also occurred to me that the following
sections might seem much more complicated than they really
are. Just keep a clear head and build the control in slowly
to your design. Then advance step by step untill you've mastered
all of the required scripts.
Selecting an item from the list is easy - let's review a
static script and then an ASP example.
<script type="text/vbscript">
form1.combo.additem("item one")
form1.combo.additem("item two")
form1.combo.listindex = 1 <!-------- heres the line that
selects -->
</script>
This will select the second item in the list and populate
the combo. Note two things: the index count starts at zero
(0), and importantly: there is no need to use the text property
of the combo.
The ASP example: you want to select a client based on request.form("clientid")
<script type="text/vbscript">
x = 0
<% while not rs.eof %>
form1.combo.additem("<%= rs("clientname")
%>")
<% if request.form("clientid") = rs("clientid")
then %>
form1.combo.listindex = x
<% end if %>
x = x + 1
<%
rs.movenext
wend
%>
</script>
Now for the interesting and final part - passing the value
and not the display name with the form.
I've done a fair bit of research into the likes of the combo
box. In visual basic you can simply pass the values through
using the item data property. However I have tried this while
the combo is embedded in a web page and I didn't get this
to work. So I came up with a work around.
The theory is simple - populate the combo from a recordset
or static list, displaying only the friendly names in the
combo and in the same loop creating an array with the values
you really want to pass through the form. The array and the
friendly names are linked by their indexes in either the array
or the combo box.
<!-- Now create the population script. The
array is also generated here.-->
<script type="text/vbscript">
' the counter variable. keeps track of
your array size and the script wont work without it.
x = 0
' note: the brackets are what define
the array - the empty set
' means that the initial size of the array has not been
' defined - this we will do later.
dim client_array()
<% while not rs.eof %>
' extend the size of the array by one
- because x increments by one.
redim preserve client_array(x)
' now give the newly defined space
a value - this is the clientid not the name.
client_array(x) = <%= rs("clientid") %>
' populate the combo now with x being
the listindex of the combo at any given point in the loop.
form1.combo.additem("<%= rs("client_name")
%>")
' inc x - this is important make sure
x gets incremented in the loop
x = x + 1
<%
rs.movenext
wend
%>
</script>
Now we have an array called client_array and a combo called
'combo'. The array stores the clientid and the combo the client
name. The index is the common bond between them.
For example, 'client_array(3)' holds the id for the client
with the name 'form1.combo.listindex(3)'.
Finally we need to populate the hidden form element because
the array is not submitted with the form. To do this we need
to assign an event to the combo box so that whenever the combo
box changes the hidden form element gets updated from the
array.
Here is the script to do this.
<script type="text/vbscript">
' note: not onchange or onclick - its just change or
click.
function combo_change()
form1.true_clientid.value = client_array(form1.combo.listindex)
</script>
</form>
Simple yet effective. Now when you submit the form you get
the name and id.
An important note: if you are selecting an item in the list
based on request.form, the box will be selected. If the user
decides not to reselect another item from the list and instead
just re-submits the form, the value of 'true_clientid' will
be null because the change event for the combo was not processed.
To counteract this issue, just assign the 'true_clientid'
a value when you select the item in the combo.
Also be aware that these controls have a way of retaining
the focus. So when you select an item in the combo and then
press submit, you will find nothing will happen. To counteract
the need to double click the submit, try this:
function combo__change()
' your script here
' submit being the name of your submit button
form1.submit.focus()
end function
Basically do something to get the focus away from the control
once an action has occurred. If you are using a submit button
without a border you might have a small problem, unless you
have a text element after the control you can move the focus
to.
About the author - Jeremy Leppan can be reached at the following
email address: mjleppan@hotmail.com