Programmer to ProgrammerTM  
Wrox Press Ltd  
   
  Search ASPToday Living Book ASPToday Living Book
Index Full Text
 
ASPToday Home
 
 
Home HOME
Site Map SITE MAP
Index INDEX
Full-text search SEARCH
Forum FORUM
Feedback FEEDBACK
Advertise with us ADVERTISE
Subscribe SUBSCRIBE
Bullet LOG OFF
                         
      The ASPToday Article
August 8, 2000
      Previous article -
August 7, 2000
  Next article -
August 9, 2000
 
   
   
   
Using JavaScript to Create Combo Boxes   Bill Wilkinson  
by Bill Wilkinson
 
CATEGORY:  Scripting  
ARTICLE TYPE: Overview Reader Comments
   
    ABSTRACT  
 
Article Rating
 
   Useful
  
 101 responses

If you have ever needed to create a combo box ASP can provide the soloution, but the coding is


cumbersome. Microsoft's ActiveX ComboBox control could do the job instead, but only if your visitors


all use Internet Explorer. Here, Bill Wilkinson shows us an alternative method.

   
                   
    Article Discussion   Rate this article   Related Links   Index Entries  
   
 
    ARTICLE

This article was prompted by viewing numerous "shopping cart" sites. On some sites, you can buy an item by checking a CheckBox. On other sites, you fill in a number in an INPUT Type=Text form control. But why can't a user .check a box to buy one item or type into a text box to buy more than one? If you look at the server side ASP coding needed to handle something like this, you can begin to understand why site designers limit the options in the browser. If we allowed both a check box and a text entry, the ASP code might look something like this:

    <%
    Dim quantity ' how many of this item user wants
    quantity = 0 ' assume nothing in text box
    On Error Resume Next
        ' get value from text box...ensure it's a number
        quantity = CInt( Request.Form("Item33Quantity") )
    On Error GoTo 0
    If quantity = 0 Then
        ' no number found in the text box...did 
        ' the user check the CheckBox instead?
        If ("X" & Request.Form("Item33CheckBox") ) <> "X" Then
            ' CheckBox checked...buy just one
            quantity = 1
        End If
    End If
    If quantity <> 0 Then
        ' ... do processing to buy given quantity ... 
    End If
    %>

Now that code certainly works, but it is cumbersome at best. Plus the poor browser user might be confused: "Do I check the box and enter a 1 in the text field? What do I do if I change my mind? Is unchecking the box enough?" Because of the lack of immediate feedback, the use of such a disconnected pair of controls is not obvious. Enter the "Combo Box".

The Combo Box is, unfortunately, one of the more useful visual form controls that was omitted from the HTML specifications. In its best possible form, a Combo Box is a drop down list that you can select from that also allows you to type in a custom value in place of (or instead of) the topmost selectable item. The Microsoft Forms ComboBox control allows this capability among many, many other options. If you will be designing forms for an ASP site that will only be used via Internet Explorer (e.g., on an Intranet site), then perhaps you may wish to use that particular ActiveX control. But if not...

The Combo Box presented in this article doesn't quite match the capabilities of the Microsoft ActiveX version. For one thing, the drop down list is physically separate from the editable text field. Yet, for most practical purposes, this "poor man's" Combo Box is probably more than adequate. If presented properly in an HTML page, its use should be obvious to even a novice browser user – as seen in the screenshot below. And it simplifies the ASP code needed to process the page: You can simply code one statement and be confident that you are getting a valid value requested by the user:

    <%
    quantity = Request.Form("SelNum");
    %>

The trick to this HTML–based Combo Box is that we use a pair of standard HTML controls in tandem. A normal <SELECT> control provides the drop down list; a standard <INPUT Type=Text> control is used to allow the user to enter custom data. And then we use some fairly straightforward JavaScript to tie the two controls together into a single coordinated unit.

The major controls here are the two JavaScript functions changeSel and changeTxt that serve to keep the two HTML form controls coordinated. Whenever the user selects a different item in the drop–down list, the logical value of that item is copied to the partnered text control. Whenever the user types a new value into the text control, the Other item in the drop-down list has its value changed (unless the value happens to match a value already in the list). And, when requested by the caller of changeTxt , the visible name in the drop–down list will also be changed. As noted above, a nice side effect of all this is that on the server side the ASP code is extremely simple, since the value of the drop–down list is guaranteed to be "correct." If you push the Submit button on the demonstration page, you’ll see a confirmation of that fact.

Let's look at the first of the Combo Box controls on that demonstration page to see how it is coded:

   <SELECT Name="SelNum" 
      onChange="changeSel(this, this.form.TxtNum);" >
      <OPTION Value=0>0
      <OPTION Value=1>1
      <OPTION Value=2>2
      <OPTION Value=3>3
      <OPTION Value=4>4
      <OPTION Value=5>5
      <OPTION Value=0>Other
   </SELECT>
   <INPUT Type=Text Name="TxtNum" Size=8 Value="0"
      onChange="changeTxt(this, this.form.SelNum,6,checkForInt);" >

The <SELECT> control is simple. Every option has a value that is the same as the displayed drop down text except the Other option. Note that it was given a value of zero, so that selecting Other initially gives you the same result that selecting 0 (zero) would. But the important feature here is the onChange event handler that is specified: It makes a call to our universal changeSel JavaScript function. More about that function in a moment, but for now note the arguments passed to it: The first argument is just this , meaning this particular <SELECT> control. The second argument is a reference to the input text control that is paired with this particular <SELECT> .

If we look at the source code for the changeSel function, then, we can see how those arguments are used:

   function changeSel( sel, txt )
   {
      // get index of selected item and then the value thereof
      var selix = sel.selectedIndex;
      var seltxt = sel[selix].value;
      // if there is no value for this item, use the text
      // of the item as the value, instead...
      if ( ("x" + seltxt) == "x" )
         seltxt = sel[selix].text;
      // and simply set the text box value to match...
      txt.value = seltxt;
   }

The sel parameter is given the this argument, so it refers to our <SELECT> control. The txt parameter is given the this.form.TxtNum argument, so it refers to the paired <INPUT> control. All we do is get the value of the selected item from the drop down list and set it as the value of the text control. In the case where the item in the drop down list has no given value, then we use the text associated with that particular item, instead (and an example illustrating this is given below; it's more useful that you might think!).

The <INPUT Type=Text...> control is even simpler. The only thing special about it is the onChange event handler and its call to our universal changeTxt function. Let's discuss each argument as it is handled by that function, starting with a listing of the function:

function changeTxt( txt, sel, otherIndex, validate, changeText )
{
   // get value as entered by user
   var val = txt.value;

   // if a validate function is specified...   
   if ( validate != null )
   {
      // then invoke it...
      if ( ! validate( val ) )
      {
         // but if that value can't be validated, then
         // simply change the text box value back to 
         // what it was before the user changed it...
         changeSel( sel, txt );
         return;
         }
      }
   // if no validate function or if validation was ok, 
   // then first check to see if the given value matches
   // an existing drop-down value...
   for ( ix = 0; ix < sel.length; ++ix )
      {
      // get value for "ix" entry in the drop-down list;
      // to be consistent with changeSel, if there is 
      // no value we use the ".text" of the option, instead.
      var selval = sel[ix].value;
      if ( ("x" + selval) == "x" ) selval = sel[ix].text;
      if (    ( val == selval )
         || ( Number(val) == Number(selval) )
      )
      {
         // a string or numeric match!  use the existing
         // drop-down option instead of changing "other"
         sel.selectedIndex = ix;
         txt.value = selval; // converts 2.0 to 2, etc.
      return;
      }
   }
    
   //
   // then if we are asked to change the text of the
   // drop down item to match the text box, do so here:
   if ( changeText == true ) 
   {
      sel[otherIndex].text  = val;
   }
   // in any case, we put the text box value into the
   // value of the "other" item in the drop down list
   // and then make it the selected item:
   sel[otherIndex].value = val;
   sel.selectedIndex = otherIndex;
   }

   function changeTxt( txt, sel, otherIndex, validate, changeText )
   {
      // get value as entered by user
      var val = txt.value;

      // if a validate function is specified...   
      if ( validate != null )
      {
         // then invoke it...
         if ( ! validate( val ) )
         {
            // but if that value can't be validated, then
            // simply change the text box value back to 
            // what it was before the user changed it...
            changeSel( sel, txt );
            return;
         }
      }

The first argument is just this , meaning this particular <INPUT Type=Text> control; it is passed to the parameter txt . The first thing the function does, then, is get the value of the control (that is, the text typed in by the user). It then checks to see if a non–null argument was given to the validate parameter. Note that validate is the fourth parameter, and in the control we are looking at the value given in checkForInt . So that the function is called, to ensure the user entered a non–negative integer only, and if the input is invalid then we simply call the changeSel function to change the value back to what it was. We assume that the validate function displayed an appropriate error message to the user.

To more closely emulate a standard Combo Box, we then check to see if the value entered by the user matches an entry in the set of existing drop–down list values. Both a numeric and a text test are made, and either kind of match causes the corresponding drop–down list item to be chosen. Just in case the user typed in 002.000 when the list value is 2 (which produces a numeric match), we copy the list value to the text box before exiting.

After that it gets easier. The last parameter to changeTxt is named changeText , and it controls whether or not the value typed in by the user is assigned to the text associated with the Other item in the drop–down list. If the argument is false – or if it is not given at all, as in the example we are discussing here – then the text is not changed. We chose this option for this particular pair of controls because retaining the text label Other looked better than changing it. But see below for another example.

Finally, we always change the value of the Other drop down item. How do we know which one is the Other item? What else? That's the third parameter (in this example, the argument 6) to the function. And then we set the selected item in the drop down list to be that of the Other item, just to be sure it is properly displayed.

That's really all there is to it. But the optional arguments to the changeTxt function and the optional drop down list values make for some interesting possible variations. In the second Combo Box on the page, we code this:

    <SELECT Name="SelEmail"
            onChange="changeSel(this, this.form.TxtEmail);" >
        <OPTION Value="you@where.what">your email address?
        <OPTION>billw@chilisoft.com
        <OPTION>reno@justice.us.gov
        <OPTION>mickey@disney.com
        <OPTION>bill@microsoft.com
    </SELECT>
    <INPUT Type=Text Name="TxtEmail" Size=20 Value=""
   onChange= _
"changeTxt(this,document.TestFormthis.form.SelEmail,0,checkForEmail,false);"
    >

Notice that we do not give explicit values to (all but one of) the various <SELECT> options. So when we select one of those options, the associated text is copied to the text control instead. This happens to work especially well because that is exactly what happens automatically when the Submit button is pressed and the form is sent to our ASP page.

Note that the Other item in the <SELECT> list this time is the first item, number zero ( 0 ). And we use a different validate function for this Combo Box, one that does a minimal check for a valid email address. Finally, in this example, the last argument in the call to changeTxt is explicitly coded as false . As with the first example, it could have been omitted with the same results.

Our last Combo Box example demonstrates a few other options:

    <SELECT Name="SelSilly"
            onChange="changeSel(this, this.form.TxtSilly);" >
        <OPTION>Zambonis rule!
        <OPTION>T'was brillig...
        <OPTION>Call me Ishmael...
        <OPTION Value="You can do better than this!">Other
    </SELECT>
    <INPUT Type=Text Name="TxtSilly" Size=25 Value="Zambonis rule!"
           onChange=
           "changeTxt(this,document.TestFormthis.form.SelSilly,3,null,true);"
    %>

Here, we do not use a validate function (the fourth argument is explicitly given as null ) and we do ask that the user input value be copied to the "text" portion of the "other" item in the <SELECT> control. In other words, when the user types something into the text box, the new value does appear as the displayed item in the drop down list.

Conclusion

And there you have it – a lot of flexibility in just a little code, and an easy to code result for the ASP page that will process the form. There are just a couple of things to watch out for:

 
 
   
  RATE THIS ARTICLE
  Please rate this article (1-5). Was this article...
 
 
Useful? No Yes, Very
 
Innovative? No Yes, Very
 
Informative? No Yes, Very
 
Brief Reader Comments?
Your Name:
(Optional)
 
  USEFUL LINKS
  Related Tasks:
 
 
   
  Related ASPToday Articles
   
  • Dynamic Selection Lists (April 14, 2000)
  •  
           
     
     
     
           
      Search the ASPToday Living Book   ASPToday Living Book
     
      Index Full Text Advanced 
     
     
           
      Index Entries in this Article
     
  • ActiveX ComboBox control
  •  
  • ActiveX ComboBox control, using
  •  
  • ASP
  •  
  • Combo Boxes
  •  
  • Combo Boxes, creating
  •  
  • creating using ASP
  •  
  • creating using JavaScript
  •  
  • HTML controls, using in tandem
  •  
  • input controls
  •  
  • JavaScript
  •  
  • optional arguments and values, variations
  •  
  • Other item, changing values
  •  
  • Select control
  •  
  • troubleshooting
  •  
     
     
    HOME | SITE MAP | INDEX | SEARCH | REFERENCE | FEEDBACK | ADVERTISE | SUBSCRIBE
    .NET Framework Components Data Access DNA 2000 E-commerce Performance
    Security Admin Site Design Scripting XML/Data Transfer Other Technologies

     
    ASPToday is brought to you by Wrox Press (http://www.wrox.com/). Please see our terms and conditions and privacy policy.
    ASPToday is optimised for Microsoft Internet Explorer 5 browsers.
    Please report any website problems to webmaster@asptoday.com. Copyright © 2001 Wrox Press. All Rights Reserved.