Developing Reusable Form Creation Routines

As promised, in this section we will examine reusable methods to create HTML forms with the proper form fields, complete with client-side form validation. These methods will hide the specific details of properly naming form fields and will not bother the developer with creating client-side form validation routines.

Form Implementation Complexity

Usually, creating a form is a trivial task; it’s just a matter of HTML coding. However, due to our reusable server-side validation code, creating a form has become a much more complex issue. When using a global server-side form validation page that all forms initially submit to, all the forms need to follow a certain standard. Specifically, the NAME of each form element that requires form validation must contain an exclamation point followed by the validation regular expression. Furthermore, the form’s ACTION property must direct to the validation page ( /CODEREUSE/ValidateForm.asp) and pass two HIDDEN variables: Collection and Redirect.

Remembering these specific details is cumbersome and serves as an easy place to make a mistake, resulting in a bug. Also, if other developers are to be working on creating the HTML forms, they will be less familiar with the conventions specified by the server-side form validation script, /CODEREUSE/ValidateForm.asp.

As discussed earlier, client-side form validation is a nice option, although not as critical as server-side form validation. As with server-side form validation, client-side form validation lends itself to reuse.

Masking Implementation Complexity Using Classes

To reduce implementation complexity and provide a black box-like interface, we’ll use classes! Two classes can be created that will provide the following benefits:

  • Provide the end developer with an easy interface to create forms that contain complex implementation details.

  • Provide automatic code generation for client-side form validation.

The first class defines a form field element as an object. Each form field object has a certain set of properties: NAME, TYPE, SIZE, and VALUE are four standard ones. For our custom server-side validation routines, an optional validation regular expression is yet another property. Our rather simplistic form field class, FormElement , contains the following definition, which is stored in the file CODEREUSEFormCreation.Class.asp :

<%
Class FormElement
  '****************** PROPERTIES ********************
  Private strName
  Private strRegExp
  Private strType
  Private strPreHTML
  Private strPostHTML
  Private strSize
  Private strValue
  '**************************************************

  '************* PROPERTY LET STATMENTS *************
  Public Property Let Name(str)
     strName = str
  End Property

  Public Property Let RegularExpression(str)
     strRegExp = str
  End Property

  Public Property Let ElementType(str)
     'Only one of six types possible: SELECT, TEXTAREA, TEXT,
     '    RADIO, HIDDEN, or CHECKBOX (TEXT is the default)
     If Ucase(str) = "TEXT" OR Ucase(str) = "SELECT" _
            OR Ucase(str) = "TEXTAREA" OR Ucase(str) = "RADIO" _
            OR Ucase(str) = "CHECKBOX" OR Ucase(str) = "HIDDEN" then
       strType = str
     Else
       strType = "TEXT"      'TEXT is the default type
     End If
  End Property

  Public Property Let Size(str)
     strSize = str
  End Property

  Public Property Let PreHTML(str)
     strPreHTML = str
  End Property

  Public Property Let PostHTML(str)
     strPostHTML = str
  End Property

  Public Property Let Value(str)
     strValue = str
  End Property
  '**************************************************

  '************* PROPERTY GET STATMENTS *************
  Public Property Get Name(  )
     Name = strName
  End Property

  Public Property Get RegularExpression(  )
     RegularExpression = strRegExp
  End Property

  Public Property Get ElementType(  )
     ElementType = strType
  End Property

  Public Property Get Size(  )
     Size = strSize
  End Property

  Public Property Get PreHTML(  )
     PreHTML = strPreHTML
  End Property

  Public Property Get PostHTML(  )
     PostHTML = strPostHTML
  End Property

  Public Property Get Value(  )
     Value = strValue
  End Property
  '**************************************************

  '********************* METHODS ********************
  Public Sub Clear(  )
     strName = ""
     strRegExp = ""
     strType = ""
     strSize = ""
     strPreHTML = ""
     strPostHTML = ""
     strValue = ""
  End Sub
  '**************************************************
End Class
%>

A FormElement class instance represents a discrete form field element in a form. This implementation of FormElement contains only a small subset of the properties a form field element can contain. If your web site requires more elegant form fields, add the needed form field properties in the above class. The following list shows the various properties of the FormElement class:

Name (Read/Write)

Specifies the NAME property of the form element. It is essential this property is specified. Furthermore, it is recommended that you give the NAME property an English-like name, since if there is a validation error, this property is reported in the error message.

RegularExpression (Read/Write)

Specifies the regular expression validation code. Remember the validation routine will search to see if the user’s input matches this regular expression.

ElementType (Read/Write)

Specifies the TYPE for the form element. This can have one of six possible values: SELECT, TEXTAREA, TEXT, RADIO, CHECKBOX, or HIDDEN, which create a list box, a multi-row text box, a single-row text box, a radio button, a checkbox, or a hidden form field, respectively.

PreHTML (Read/Write)

This property specifies any HTML that should occur before the actual INPUT tag.

PostHTML (Read/Write)

This property specifies any HTML that should occur after the actual INPUT tag.

Size (Read/Write)

This property specifies the SIZE property for the form element. In a multi-row text box, there are as many columns as specified by the Size property and one-fourth as many rows.

Value (Read/Write)

This property specifies the VALUE property of the INPUT tag. It is meaningless if you are creating a list box, multi-row text box, radio button, or checkbox. The Value property is very useful when creating HIDDEN form fields.

The FormElement class uses the Clear method, as described in the following definition:

Clear

The Clear method erases all of the property values. Normally such a method wouldn’t be needed. The Adding Form Elements later in this chapter explains why I chose to supply such a method.

We’ll look at how to use the FormElement class and its properties and methods once we examine the GenerateForm class.

GenerateForm is the class used to create the HTML that will physically construct the form on the users’ browsers. Each function of GenerateForm’s properties is outlined here:

Collection (Read/Write)

Specifies whether to submit the form using an ACTION of POST (the default) or GET. To use GET, Collection must be set equal to QueryString. If it equals any other value, the form will submit with an ACTION of POST.

Redirect (Read/Write)

The URL of the actual form-processing script. Once the data is validated by /CODEREUSE/ValidateForm.asp, this is the page the user is passed to.

FormName (Read/Write)

Specifies the NAME property of the form. If not specified, frmForm1 is used. If you plan to use the GenerateForm class to create more than one form on an HTML page, it is essential that each form have its own, unique FormName for client-side form-validation purposes.

FormAction (Read/Write)

Specifies the URL of the server-side form validation script. Set to /CODEREUSE/ValidateForm.asp in the Initialize event, but can be modified.

SubmitTitle (Read/Write)

The title for the form’s submit button. The title, if not specified, defaults to “Submit Query!”

objFormElementDict (Write (indirectly))

This property is indirectly write-only. This property is a Dictionary object that contains zero to many HTML strings that correspond to form field elements. To add a new form field element, use the AddElement method.

The following list discusses the GenerateForm class’s methods:

AddElement(objFormElement)

Adds a form field element to objFormElementDict. objFormElement is expected to be an instance of the FormElement class. A more thorough discussion of why this technique is used to add a form element appears in a later sidebar.

GenerateForm( )

Returns the HTML that will generate a form specified by the form field elements in objFormElementDict.

GenerateValidation( )

Returns the client-side JavaScript code that will validate the form field inputs. The client-side JavaScript takes advantage of regular expressions; hence the client-side validation code will only work properly in browsers that support JavaScript 1.2 or greater: Internet Explorer or Netscape Navigator 4.0 and up.

GenerateHTMLDocument(strTitle)

Returns the entire HTML document in one string. Only useful if the HTML page will contain one form and one form only. The strTitle parameter displays a title at the beginning of the HTML page (right after the <BODY> tag). GenerateHTMLDocument(X ) is synonymous with:

<HTML><HEAD>
GenerateValidation(  )
</HEAD><BODY>      X
                        GenerateForm(  )
</BODY></HTML>

The GenerateForm class definition, which is listed in Example 5.5 and is also stored in the file CODEREUSEFormCreation.Class.asp along with the definition of the FormElement class, is fairly straightforward and easy to use. To create a form, two object instances are needed: an instance of GenerateForm and an instance of FormElement. Start by creating the GenerateForm instance and set its properties. Next, create a single FormElement instance, set the needed properties in the FormElement instance, and call the AddElement method of the GenerateForm instance, passing in the FormElement instance. Finally, call the FormElement instance’s Clear method and repeat the previous three steps for each element in the form.

Example 5-5. The GenerateForm Class Definition

<%
Class GenerateForm
  '****************** PROPERTIES ********************
  Private strRedirect
  Private strCollection
  Private strFormAction
  Private objFormElementDict
  Private strFormName
  Private strSubmitTitle
  '**************************************************

  '************** INITIALIZE/TERMINATE **************
  Private Sub Class_Initialize(  )
     'Set the default property values
     strCollection = "FORM"
     strFormAction = "/CODEREUSE/ValidateForm.asp"
     strFormName = "frmForm1"
     strRedirect = Request.ServerVariables("SCRIPT_NAME")
     strSubmitTitle = "Submit Query!"

     Set objFormElementDict = CreateObject("Scripting.Dictionary")
  End Sub

  Private Sub Class_Terminate(  )
     Set objFormElementDict = Nothing    ' Clean up
  End Sub
  '**************************************************


  '************* PROPERTY LET STATMENTS *************
  Public Property Let Collection(str)
    'Set the strCollection private property, making sure it is
    'set to either QueryString or Form (default to Form)
    If Ucase(str) = "QUERYSTRING" then
      strCollection = "QueryString"
    Else
      strCollection = "Form"
    End If
  End Property

  Public Property Let Redirect(str)
    'Set the strRedirect private property; if trying to assign it
    'a blank string, assign it the value of the current ASP page
    If Len(str) = 0 then
      strRedirect = Request.ServerVariables("SCRIPT_NAME")
    Else
      strRedirect = str
    End If
  End Property

  Public Property Let FormAction(str)
    'Set the strFormAction private property
    strFormAction = str
  End Property

  Public Property Let FormName(str)
    'Set the strFormName private property
    strFormName = str
  End Property

  Public Property Let SubmitTitle(str)
    'Set the strSubmitTitle private property
    If Len(str) = 0 then
      strSubmitTitle = "Submit Query!"
    Else
      strSubmitTitle = str
    End If
  End Property
  '**************************************************

  '************* PROPERTY GET STATMENTS *************
  Public Property Get Collection(  )
     Collection = strCollection
  End Property

  Public Property Get Redirect(  )
     Redirect = strRedirect
  End Property

  Public Property Get FormAction(  )
     FormAction = strFormAction
  End Property

  Public Property Get FormName(  )
     FormName = strFormName
  End Property

  Public Property Get SubmitTitle(  )
     SubmitTitle = strSubmitTitle
  End Property
  '**************************************************

  '********************* METHODS ********************
  Public Function AddElement(objFormElement)
    'Adds a form field element to the objFormElementDict object
    'Expects to be passed a valid objFormElement instance
    Dim strHTML, strTechnicalName

    'Determine if this form field needs to be validated
    If Len(objFormElement.RegularExpression) > 0 then
       strTechnicalName = objFormElement.Name & "!" & _
                          objFormElement.RegularExpression
    Else
       strTechnicalName = objFormElement.Name
    End If

    'Determine what form field type we are dealing with
    If objFormElement.ElementType = "SELECT" then
       strHTML = objFormElement.PreHTML & vbCrLf & _
               "<SELECT NAME=""" & objFormElement.Name & """"

       If Len(objFormElement.Size) > 0 then
          strHTML = strHTML & " SIZE=" & objFormElement.Size
       End If
                    
       strHTML = strHTML & ">" & vbCrLf & _
                 objFormElement.PostHTML & _
                 vbCrLf & "</SELECT>" & vbCrLf & vbCrLf
    Elseif objFormElement.ElementType = "TEXTAREA" then
       strHTML = objFormElement.PreHTML & vbCrLf & _
                 "<TEXTAREA NAME=""" & strTechnicalName & """"

       If Len(objFormElement.Size) > 0 then
          strHTML = strHTML & " COLS=" & objFormElement.Size & _
                 " ROWS=" & objFormElement.Size / 4
       End If

       strHTML = strHTML & "></TEXTAREA>" & _
                 vbCrLf & objFormElement.PostHTML & _
                 vbCrLf & vbCrLf
    Else 'must be one of the other types
       strHTML = objFormElement.PreHTML & vbCrLf & _
                 "<INPUT NAME=""" & strTechnicalName & """"

       If Len(objFormElement.Size) > 0 then
          strHTML = strHTML & " SIZE=" & objFormElement.Size
       End If

       If Len(objFormElement.Value) > 0 then
          strHTML = strHTML & " VALUE=""" & objFormElement.Value & """"
       End If

       strHTML = strHTML & " TYPE=" & objFormElement.ElementType & _
                 ">" & vbCrLf & objFormElement.PostHTML & _
                 vbCrLf & vbCrLf
    End If

    'Add the HTML to the FormElement dictionary
    objFormElementDict.Add strTechnicalName, strHTML
  End Function


  Public Function GenerateForm(  )
    'Iterates through the objFormElementDict collection and
    'generates the resulting form
    Dim strResultingForm

    strResultingForm = "<FORM NAME=""" & strFormName & _
                       """ METHOD="
    If strCollection = "QueryString" then
       strResultingForm = strResultingForm & "GET"
    Else
       strResultingForm = strResultingForm & "POST"
    End If

    strResultingForm = strResultingForm & " ACTION=""" & _
         strFormAction & """ ONSUBMIT=""return ValidateData(  );"">" & _
         vbCrLf

    'Add the HIDDEN form variables
    strResultingForm = strResultingForm & vbTab & "<INPUT TYPE=HIDDEN " & _
             "NAME=Collection VALUE=""" & strCollection & """>" & vbCrLf & _
             vbTab & "<INPUT TYPE=HIDDEN NAME=Redirect VALUE=""" & _
             strRedirect & """>" & vbCrLf

    'Iterate through the form element dictionary, outputting the
    'form field elements
    Dim strName
    For Each strName in objFormElementDict
      strResultingForm = strResultingForm & vbTab & objFormElementDict(strName)
    Next

    strResultingForm = strResultingForm & "<P><INPUT TYPE=SUBMIT VALUE=""" & _
           strSubmitTitle & """>" & vbCrLf & vbCrLf
    strResultingForm = strResultingForm & "</FORM>" & vbCrLf & vbCrLf

    GenerateForm = strResultingForm
  End Function


  Public Function GenerateValidation(  )
    'Creates the client-side validation code
    Dim strCode
    strCode = "<SCRIPT LANGUAGE=""JavaScript"">" & vbCrLf & "<!--" & vbCrLf & _
              "function ValidateData(  )" & vbCrLf & "{" & vbCrLf & _
              vbTab & "var iLoop;" & vbCrLf & vbCrLf

    'Now, for each form element that contains regular expression code,
    'prepare it for validation!
    Dim strName, strRegExp
    For Each strName in objFormElementDict
       If InStr(1,strName,"!") then
          'We have form validation!!  Grab the regexp
          strRegExp = Right(strName, Len(strName) - InStr(1,strName,"!"))
          strCode = strCode & vbTab & "if (document.forms['" & strFormName & _
                   "'].elements['" & Replace(strName,"","\") & _
                   "'].value.search(/" & strRegExp & "/) == -1) {" & vbCrLf & _
                   vbTab & vbTab & "alert('" & Left(strName, InStr(1,strName,"!") _
                   - 1) & " is not valid.')," & vbCrLf & vbTab & vbTab & _
                   "return false;" & vbCrLf & vbTab & "}" & vbCrLf
       End If
    Next

    strCode = strCode & vbCrLf & vbTab & "return true;" & vbCrLf
    strCode = strCode & "}" & vbCrLf
    strCode = strCode & vbCrLf & "// -->" & vbCrLf & "</SCRIPT>" & vbCrLf

    GenerateValidation = strCode
  End Function     


  Public Function GenerateHTMLDocument(strTitleHTML)
    'This method generates the HTML/BODY tags, the form and client-side
    'form validation all in one call
    Dim strResultHTML
    strResultHTML = "<HTML><HEAD>" & vbCrLf & GenerateValidation(  ) & _
                    "</HEAD>" & vbCrLf
    strResultHTML = strResultHTML & "<BODY>" & vbCrLf & strTitleHTML & _
            vbCrLf & GenerateForm(  ) & vbCrLf & "</BODY></HTML>"

    GenerateHTMLDocument = strResultHTML
  End Function
  '**************************************************
End Class
%>

For example, the following code will create a form with four form fields (two text boxes, a text area, and a list box). The first two text boxes are validated on the client side when the form is submitted (and will also be subject to validation on the server side when submitted to /CODEREUSE/ValidateForm.asp). For the example, the two class definitions were placed in an separate file and included in the 5FormCreationDemo.asp file, whose contents are as follows:

<%@ LANGUAGE = "VBSCRIPT" %>
<% Option Explicit %>
<!--#include virtual="/CODEREUSE/FormCreation.Class.asp"-->
<%
     'Create an instance of the GenerateForm class
     Dim objGenerateForm
     Set objGenerateForm = New GenerateForm

     'Set the objGenerateForm properties
     objGenerateForm.Collection = "Form"
     objGenerateForm.Redirect = "/scripts/Something.asp"
     objGenerateForm.SubmitTitle = "--- GO! ---"     

     'Create an instance of the FormElement class
     Dim objFormElement
     Set objFormElement = New FormElement

     '*** Create the form field elements ***
     'Create an age form field element
     objFormElement.Name = "Age"
     objFormElement.Size = 4
     objFormElement.ElementType = "TEXT"
     objFormElement.RegularExpression = "d{1,2}"
     objFormElement.PreHTML = "What is your Age?<BR>"
     objGenerateForm.AddElement objFormElement  'Add it to the form

     'Create an email form field element
     objFormElement.Clear    'clear out the form element values before reuse
     objFormElement.Name = "Email"
     objFormElement.ElementType = "TEXT"
     objFormElement.RegularExpression = "^[a-z_0-9-.]+@w+.w+$"
     objFormElement.PreHTML = "<P>What is your email address?<BR>"
     objGenerateForm.AddElement objFormElement  'Add it to the form

     'Create a comment form field with no validation
     objFormElement.Clear    'clear out the form element values before reuse
     objFormElement.Name = "User Comments"
     objFormElement.ElementType = "TEXTAREA"
     objFormElement.PreHTML = "<P>Any comments?<BR>"
     objFormElement.Size = 40
     objGenerateForm.AddElement objFormElement  'Add it to the form

     'Create a list box
     objFormElement.Clear    'clear out the form element values before reuse
     objFormElement.Name = "Experience"
     objFormElement.ElementType = "SELECT"
     objFormElement.PreHTML = "<P>How many years have you been on the Net?<BR>"
     objFormElement.Size = 1
     objFormElement.PostHTML = "<OPTION VALUE=1>One Year</OPTION>" & vbCrLf & _
                               "<OPTION VALUE=2>Two Years</OPTION>"     
     objGenerateForm.AddElement objFormElement  'Add it to the form


     'Generate the entire HTML document
     Response.Write objGenerateForm.GenerateHTMLDocument("<H1>Information</H1>")

     '(synonymous to doing:
     '  Response.Write "<HTML><HEAD>"
     '  Response.Write objGenerateForm.GenerateValidation(  )
     '  Response.Write "</HEAD><BODY>"
     '  Response.Write objGenerateForm.GenerateForm(  )
     '  Response.Write "</BODY></HTML>")


     Set objFormElement = Nothing    'Clean up!
     Set objGenerateForm = Nothing   'Clean up!
%>

Note that the GenerateHTMLDocument method was used to generate the HTML output. A simple Response.Write sends the form HTML to the client. As with any generalized implementation, there are a few caveats when using the GenerateForm class:

  • The value of the Name property of the FormElement class should not have a double quote. Including one will result in unexpected behavior.

  • When creating a list box, it is imperative the series of HTML tags used to create the list box items be inserted in the PostHTML property. (The Experience form field properties provide a good example for creating a select box.)

  • These classes are not designed to create complex forms. The HTML they output is not pretty, and is not intended to be so. However, refinements of the GenerateForm and FormElement classes could be made to accommodate more complex forms and more detailed form fields.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.84.155