Team LiB
Previous Section Next Section

Chapter 8: Handling and Validating Forms

One of the best features of JavaScript is its ability to handle forms. Before the introduction of JavaScript, form validation required that the contents of a form be sent back to the originating server, checked, and if there were errors in the form data, sent back to the client for corrections. This was not only complicated, but very time-consuming. When JavaScript was introduced, form validation became a one-step process—the client would fill out the form, and before the form data was submitted to the server, it was validated with JavaScript scripts located on the Web page itself. This made JavaScript-enabled Web pages not only faster but more user-friendly. Some of the Javascript techniques that can be used with forms are dynamic form creation, form validation prior to submission, and data manipulation within form elements. Each of these techniques will be described in this chapter.

Defining Dynamic Forms

With JavaScript, a Web page designer is no longer limited to the static elements that are part of HTML. With a JavaScript-enabled Web page, you can request specific data on a per-user basis. For example, if you are running an online store, you might want to know an account number from clients working for a business, but you would not want to ask for this information from a home shopper. With JavaScript, you can hide or disable the appropriate form fields for each of your visitors.

Adding Form Elements Depending on Visitor Form Selections

There are two ways to customize a form for the user. The first way is to build the form, with the proper elements already in place, while the page is loading. You can do so by using input either from a previous page, in the form of cookies (covered in Chapter 11), or by using previous form information passed through the page URL.

You have probably seen Web sites with pages that have been created using a server-side language such as ASP or PHP. Even though these sites appear to contain multiple pages, more often than not, they are made up of only one document. The programmer of such a site makes it appear as though the site is very large by passing parameter variables through the URL. A good example of this is the excellent search engine Google.com:

http://www.google.com/search?hl=en&ie=UTF-8&oe=UTF-8&q=JavaScript

There are several variables that have been stored in Google's URL. URL parameters that occur after the first question mark in the URL are separated by ampersands and are variable/value pairs. The Google example has four variables and corresponding values:

    hl=en
    ie=UTF-8
    oe=UTF-8
    q=JavaScript

The last variable corresponds to an example query I performed. In a server-side language such as ASP or PHP, these URL fields are automatically generated for the programmer in the form of variables, but with JavaScript they are not. This is important for JavaScript programmers because forms submit information through the URL in the same way. To get the information out of the URL, you simply need to parse it with the built-in String object methods.

The following example prompts the user to enter his age when the page first loads:

<html>
  <head>
    <title>
      JavaScript Professional Projects - Dynamic Forms 
    </title>
    <script language="JavaScript"> 
    <!--
         var visitorAge = -1;
         function getParams() 
         {
           var urlquery = location.href.split( "?" );
           var variable = ( urlquery[1] ? urlquery[1].split( "=" ) : 0);
           visitorAge = ( variable ? variable[1] : -1 );
         }
       // -->
    </script>

  </head>

  <body>
   
    <center>
      <font size=6>JavaScript Professional Projects</font><br>
      <font size=4>Chapter 9: Dynamic Forms</font>
    </center>

    <br><br>
    <br><br>

    <form>
      <script language="JavaScript">
      <!--
        getParams();
        if( visitorAge >= 12 ) 
        { 
          document.write( "Welcome to my page." ); 
        }
        else if( visitorAge == -1 ) 
        {
          document.write( 
             "Please tell me your age:&nbsp;&nbsp;" +
             "<input type='text' name='age'size='5'></input><br><br>" + 
             "<input type='submit' value='Continue'></input>"
           );
        }
        else 
        {
          document.write( "Sorry, you must be at least 12 years old" +
                            " to access this site." );
        }
      -->
      </script> 
    </form>

  </body>
</html>

After submitting the form, the page is reloaded with the form element name=value pairs in the URL. When the page reloads, the value of the first parameter is saved. If the value is less than 12, the page shows a message indicating that there is an age requirement. This would be, of course, a very insecure way to perform age checking, but the example does show how to get variables out of the URL.

Changing Selection List and Other Form Input Properties

One of the very useful features that JavaScript brings to your Web page is the ability to manipulate data that is already in the forms. For instance, if you were creating a form with which you planned to survey your Web site's visitors on their experience at the site, you might include something like, "Which products most interested you at this site? Select all that apply" and then a list all of the product lines sold on your Web site. You could list each product as a check box and require the visitor to click on each item that interested him or her. Unfortunately, if you have more than ten products this could get tedious. One alternative would be to place each item in a select box on your form and allow the user to select each item that interested him or her. Of course, if you used this approach, you would want to present the list in an ordered way so as to make answering the question as easy as possible. Before JavaScript, this would have been nearly impossible without hard-coding the list order into the HTML source. With JavaScript, you can now add items into the select box in any order and worry about sorting afterwards.

This example has two select boxes in a form. The first select box contains the names of each month in the year and the second select box is empty. Two buttons allow you to move items to and from the first select box into the second. After each move, both select boxes are sorted.

<html>
  <head>
    <title>
      JavaScript Professional Projects - Working with Forms
    </title>

    <style type="text/css">
    <!--;
         .sameSize{ width: 125; } 
       -->
    </style>

    <script language="JavaScript">
    <!--
      var months = new Array( "January", "February", "March",
                                "April", "May", "June", "July",
                                "August", "September", "October",
                                "November", "December" );
 
      function swapSelects( fromSelect, toSelect )
      {
        var toSelect_Length = toSelect.options.length;
        while( fromSelect.selectedIndex > -1 )
        {
          var index = fromSelect.selectedIndex;

          toSelect.options[toSelect_Length] = new Option(
            fromSelect.options[index].text ); 
          toSelect.options[toSelect_Length].value =
            fromSelect.options[index].value;
          fromSelect.options[index] = null;

          toSelect_Length++;
        }
        sortSelect( fromSelect ); 
        sortSelect( toSelect );
      }

      function compareTo( s ) 
      {
        var len1 = this.length;
        var len2 = s.length;
        var n = ( len1 < len2 ? len1 : len2 );

        for( i = 0 ; i < n ; i++ )
        {
           var a = this.charCodeAt( i );
           var b = s.charCodeAt( i ) 
           if( a != b )
           {
             return( a - b );             
           }
        }
        return( len1 - len2 ); 
      }
      String.prototype.compareTo = compareTo;

      function sortSelect( select )
      {
        var a = new Array();
        for( i = 0; i < select.options.length ; i++ )
        {
          a[a.length] = new Option( select.options[i].text,
                                      select.options[i].value,
                                      select.options[i].defaultSelected,
                                      select.options[i].selected ) ;
        }

        a = a.sort(
          function( s, t )
          { 
            return( s.text.compareTo( t.text ) ); 
          } 
        );

        for( i = 0; i < a.length ; i++ )
        {
          select.options[i] = new Option( a[i].text,
                                             a[i].value,
                                             a[i].defaultSelected,
                                             a[i].selected );
        }
      }
    // -->
    </script>

  </head>

  <body>

    <center>
      <font size=6>JavaScript Professional Projects</font><br>
      <font size=4>Chapter 8: Working with Forms</font>
    </center>

    <br><br>
    <br><br>


    <form name="theForm">
      <table cellspacing="6">
        <tr>
          <td>
            <select size="12" name="ListA" multiple width="125">
              <script language="JavaScript">
              <!--
                   for( i = 0 ; i < months.length ; i++ ) 
                   {
                     document.write( "<option>" + months[i] +
                            "</option>" ); 
                   }
                   sortSelect( document.theForm.ListA );
                 //-->
              </script> 
            </select> 
          </td>

          <td>
            <input type="button" value="=====&gt;"
                 onClick="JavaScript: swapSelects( document.theForm.ListA,
                                                  document.theForm.ListB );">
            <br><br>
            <input type="button" value="&lt;=====" 
                 onClick="JavaScript: swapSelects( document.theForm.ListB,
                                                  document.theForm.ListA );">
          </td>

          <td> 
            <select size="12" name="ListB" multiple
                     width="125"></select> 
            <script language="JavaScript">
            <!--
              if( navigator.appName != "Netscape" )
              { 
                document.theForm.ListA.style.width = 125; 
                document.theForm.ListB.style.width = 125; 
              }
            // -->
            </script> 
           </td>
          </tr>
        </table>
     </form>

  </body> 
</html>

This small example contains two very useful bits of code. The first function, swapSelects(),

function swapSelects( fromSelect, toSelect )
{
  var toSelect_Length = toSelect.options.length;
  while( fromSelect.selectedIndex > -1 )
  {
    var index = fromSelect.selectedIndex;

    toSelect.options[toSelect_Length] = new Option(
      fromSelect.options[index].text );
    toSelect.options[toSelect_Length].value =
      fromSelect.options[index].value;
    fromSelect.options[index] = null;

    toSelect_Length++;
  }

  sortSelect( fromSelect );
  sortSelect( toSelect );
}

will take all of the selected elements out of fromSelect and put them into toSelect

At the end of the swapSelect() function, both select boxes are sorted with the following function, sortSelect():

function sortSelect( select )
{
  var a = new Array(); 
  for( i = 0; i < select.options.length ; i++ )
  {
   a[a.length] = new Option( select.options[i].text, 
                               select.options[i].value,
                               select.options[i].defaultSelected,
                               select.options[i].selected ) ;
  }

  a = a.sort(
      function( s, t )
      {
        return( s.text.compareTo( t.text ) );
      } 
  );

  for( i = 0; i < a.length ; i++ ) 
  {
    select.options[i] = new Option( a[i].text,
                                       a[i].value,
                                       a[i].defaultSelected,
                                       a[i].selected );
  }
}

The sortSelect() function uses a custom version of the compareTo() function presented in Chapter 3 to sort the options in the select box.

It is also very useful to be able to insert a new item into a single select box, particularly when building a dynamic list of any sort. Here is a basic example that takes input from the user from a text box and inserts it into a select box:

<html>
  <head>
    <title>
      JavaScript Professional Projects - Dynamic Forms 
    </title>

    <style type="text/css">
    <!--
         .sameSize{ width: 125; } 
       -->
    </style>

    <script language="JavaScript"> 
    <!--
         function insertOption( select, text )
         { select.options[select.options.length] = 
             new Option( text, text, false, false );
           sortSelect( select );
         }
       
         function compareTo( s )
         { 
           var len1 = this.length;
           var len2 = s.length;
           var n = ( len1 < len2 ? len1 : len2 );

           for( i = 0 ; i < n ; i++ )
           {
             var a = this.toUpperCase().charCodeAt( i );

             var b = s.toUpperCase().charCodeAt( i ) 
             if( a != b )
             {
             return( a - b );
             }
           }
           return( len1 - len2 ); 
         } 
         String.prototype.compareTo = compareTo;

         function sortSelect( select )
         {
           var a = new Array(); 
           for( i = 0; i < select.options.length ; i++ )
           { 
             a[a.length] = new Option( select.options[i].text,
                                         select.options[i].value, 
                                         select.options[i].defaultSelected,
                                         select.options[i].selected ) ;
           }

           a = a.sort(
             function( s, t )
             {  
               return( s.text.compareTo( t.text ) );
             } 
           );

           for( i = 0; i < a.length ; i++ ) 
           { 
             select.options[i] = new Option( a[i].text,
                                                a[i].value,
                                                a[i].defaultSelected,
                                                a[i].selected );
           }
         }
       // -->
    </script>
    </head>
    
    <body>

      <center>
        <font size=6>JavaScript Professional Projects</font><br>
        <font size=4>Chapter 8: Dynamic Foms</font>
      </center>

      <br><br> 
      <br><br>

      <form name="theForm" onSubmit="return( false );">
        <table cellpadding="3">
          <tr>
            <td valign="bottom">
              <input type="text" name="theText" size="20"> 
             &nbsp;&nbsp;&nbsp; 
              <input type="button" value="Insert"
                   onClick="JavaScript:  
                     insertOption( document.theForm.theSelect, 
                                    document.theForm.theText.value );
                     document.theForm.theText.value = '';">
            </td>
            <td>
             &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
             <select size="10" name="theSelect"
                          class="sameSize" width=125></select>
           </td>
         </tr>
       </table>
     </form>
 
  </body> 
</html>

The text in the text box can be accessed through the text box's value property, as you can see above. All form elements have this property, but on some it is not always straightforward. For example, with select boxes, the value property is the value of the first option that is selected. All options, of course, have a value property, but you must iterate through the select box's options array to access them. The value property of a button is the text that is shown on the button.


Team LiB
Previous Section Next Section